410 likes | 556 Views
DEV312 Building Secure Web Applications: Defenses And Countermeasures. Jeff Prosise Co-founder Wintellect (www.wintellect.com). Holistic Approach To Security. Network. Host. Application. Port blocking Filtering Encryption. Updates Internet Information Server hardening ACLs CAS
E N D
DEV312 Building Secure Web Applications: Defenses And Countermeasures Jeff Prosise Co-founder Wintellect (www.wintellect.com)
Holistic Approach To Security Network Host Application Port blocking Filtering Encryption Updates Internet Information Server hardening ACLs CAS Logging Least privilege Account management Validation Hashing Encryption Secrets management Cookie management Session management Error handling Defend the network Spoofed packets, etc. Buffer overflows, illicit paths, etc. Defend the host SQL injection, XSS, input tampering, etc. Defend the application
Defending The Network Harden firewalls Stay current with patches and updates Block unused ports and protocols Use filtering to reject illicit requests Harden routers and switches Stay current with patches and updates Use ingress/egress filtering to reject spoofed packets Screen ICMP traffic from the internal network Screen directed broadcast requests from the internal network Reject trace routing requests Encrypt sensitive communications http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT16.asp http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT18.asp i http://msdn.microsoft.com/library/en-us/dnnetsec/html/THCMCh15.asp
Defending The Host Stay current with service packs and updates Harden Internet Information Server 5 by running IISLockdown Disables FTP, SMTP, and NNTP Removes key script mappings such as .idq, .htr, and .printer Removes IISSamples, IISHelp, Scripts, and other virtual directories ACLs system tools and Web content directories to limit access Disables WebDAV Installs URLScan Harden Internet Information Server 5 and 6 by installing URLScan Logs failed requests Limits request sizes to mitigate DoS attacks Masks content headers revealing IIS type and version number Blocks requests with potentially injurious characters (e.g., dots in path names) Canonicalizes and verifies path names to thwart directory traversal attacks Disables specified verbs (e.g., "DEBUG") i http://msdn.microsoft.com/library/en-us/dnnetsec/html/THCMCh16.asp
Defending The Host Harden the Web server’s TCP/IP stack http://msdn.microsoft.com/library/en-us/dnnetsec/html/HTHardTCP.asp Run ASP.NET using the principle of least privilege Avoid running as SYSTEM Consider running with partial trust Limit the size of file uploads <configuration> <system.web> <!-- Limit request length to 128K (default = 4 MB) --> <httpRuntime maxRequestLength="128" /> </system.web> </configuration>
Defending The Host Disable unused shares and services Delete nonessential shares and restrict access to others Disable nonessential services and protocols (e.g., SMB and NetBIOS) Remove or secure Remote Data Services (RDS) Harden user accounts Disable the Guest account Use strong passwords on all accounts Rename the administrator account Disallow null sessions (anonymous logons) Restrict remote logons to only those who need it Be aggressive about logging and auditing Log failed logon attempts Log failed actions anywhere in the system Secure IIS log files with NTFS permissions Audit access to Metabase.bin
Defending The Host Use ACLs to limit access to critical resources Restrict access to the %systemroot%\System32 directory Restrict access to %systemroot%\Microsoft.NET\Framework Restrict write access to %systemroot%\System32\Logfiles Restrict write access to Web content directories Restrict access to registry keys where secrets are stored See http://msdn.microsoft.com/library/en-us/dnnetsec/html/ THCMCh19.asp?frame=true#c19618429_025 for information on NTFS permissions required by ASP.NET
Defending The Application Never trust user input (validate!) Access databases securely Avoid vulnerabilities in forms authentication Secure ASP.NET session state Store secrets securely Anticipate errors and handle them appropriately i http://msdn.microsoft.com/library/en-us/dnnetsec/html/THCMCh10.asp
Validating Input Filter potentially injurious characters and strings HTML-encode all input echoed to a Web page Use "safe" character encodings <globalization requestEncoding="ISO-8859-1" responseEncoding="ISO-8859-1" /> Avoid using file names as input if possible
Accessing Data Securely Use stored procedures or parameterized commands Never use sa to access Web databases Store connection strings securely Apply administrative protections to SQL Server http://www.microsoft.com/sql/techinfo/administration/2000/security/securingsqlserver.asp Optionally use SSL/TLS or IPSec to secure the connection to the database server http://msdn.microsoft.com/library/enus/dnnetsec/html/SecNetHT18.asp http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT19.asp
Dynamic SQL Commands • Vulnerable to SQL injection attacks // DANGER! User input used to generate database query string sql = String.Format ("select count (*) " + "from users where username=\'{0}\' and cast " + "(password as varbinary)=cast (\'{1}\' as " + varbinary)", username, password); SqlCommand command = new SqlCommand (sql, connection); int count = (int) command.ExecuteScalar ();
Parameterized Commands • Less vulnerable to SQL injection attacks // BETTER: Input passed to parameterized command SqlCommand command = new SqlCommand ("select count (*) from users where " + "username=@username and cast (password as " + "varbinary)=cast (@password as varbinary)", connection); command.Parameters.Add ("@username", SqlDbType.VarChar).Value = username; command.Parameters.Add ("@password", SqlDbType.VarChar).Value = password; int count = (int) command.ExecuteScalar ();
Stored Procedures • Less vulnerable to SQL injection attacks • Added security via EXECUTE permission // BEST: Input passed to stored procedure SqlCommand command = new SqlCommand ("proc_IsUserValid", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.Add ("@username", SqlDbType.VarChar).Value = username; command.Parameters.Add ("@password", SqlDbType.VarChar).Value = password; command.Parameters.Add ("@return", SqlDbType.Int).Direction = ParameterDirection.ReturnValue; int count = (int) command.ExecuteScalar ();
The sa Account • For administration only; never use it to access a database programmatically • Instead, use one or more accounts that have limited database permissions • For queries, use SELECT-only account • Better yet, use stored procs and grant account EXECUTE permission for the stored procs • Reduces an attacker's ability to execute harmful commands
Creating A Limited Account USE Login GO -- Add account named webuser to Login database EXEC sp_addlogin 'webuser', 'm1x2y3z4p5t6l7k8', 'Login' -- Grant webuser access to the database EXEC sp_grantdbaccess 'webuser' -- Limit webuser to calling proc_IsUserValid GRANT EXECUTE ON proc_IsUserValid TO webuser
Storing Data Securely • Sensitive data stored persistently should be encrypted or hashed • Credit card numbers • Login passwords, etc. • For maximum security, connection strings should also be encrypted • Encryption is easy • System.Security.Cryptography classes • Windows Data Protection API (DPAPI) • Securing decryption keys is not
Data Protection API (DPAPI) • Present in Windows 2000 and higher • Provides strong encryption, automatic key generation, and secure key storage • Triple-DES encryption • PKCS #5 key generation • Two “stores” • User store • Machine store Great tool for ASP.NET programmers! • Operating system manages keys
Building A DPAPI Library • The .NET Framework Class Library 1.x doesn’t wrap DPAPI • See “How to Create a DPAPI Library” for instructions on creating your own • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/-SecNetHT07.asp • Managed wrapper around DPAPI • Handles interop and marshaling for you • Features DataProtector class with simple methods named Encrypt and Decrypt • Supports machine store and user stores
Encrypting Connection Strings Web.config <configuration> <appSettings> <add key="ConnectionString" value="AQNCMnd8BFdERjHoAwE/Cl+sBAAAA..." /> </appSettings> </configuration> Page DataProtector dp = new DataProtector (DataProtector.Store.USE_MACHINE_STORE); string val = ConfigurationSettings.AppSettings ["ConnectionString"]; byte[] data = Convert.FromBase64String (val); string connect = Encoding.ASCII.GetString (dp.Decrypt (data, null));
Encrypting And ACLingConnection Strings Registry Admins: Full SYSTEM: Full ASP.NET: Read Page DataProtector dp = new DataProtector (DataProtector.Store.USE_MACHINE_STORE); RegistryKey key = Registry.LocalMachine.OpenSubKey ("SOFTWARE\\MyWebApp"); string val = (string) key.GetValue ("ConnectionString"); byte[] data = Convert.FromBase64String (val); string connect = Encoding.ASCII.GetString (dp.Decrypt (data, null));
Windows Authentication • Microsoft SQL Server supports two types of authentication • Authentication using SQL Server logins • Authentication using Windows identities • Windows authentication reduces threat surface area by eliminating user names and passwords from connection strings server=localhost;database=pubs;Trusted_Connection=yes
Forms Authentication Protect login credentials with SSL/TLS http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT16.asp Don't store passwords; store password hashes Limit authentication cookie lifetimes to minimize windows for replay attacks Assume authentication cookies are spoofed or stolen when performing sensitive operations Don't rely on forms authentication to protect resources not owned by ASP.NET
Protecting Logins • Place login forms in directories protected by SSL/TLS to guard against eavesdropping <authentication mode="Forms"> <forms loginUrl="https://.../LoginPage.aspx" /> </authentication> Encrypted connection
Storing Login Passwords Don’t store plaintext passwords Store encrypted passwords or password hashes for added security
Password Hashes • FormsAuthentication.HashPassword-ForStoringInConfigFile makes hashing easy • SHA-1 hashes • MD5 hashes string hash = FormsAuthentication.HashPasswordForStoringInConfigFile (password, "SHA1"));
Generating Salted Hashes string CreateSaltedPasswordHash (string password) { // Generate random salt string RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider (); byte[] saltBytes = new byte[16]; csp.GetNonZeroBytes (saltBytes); string saltString = Convert.ToBase64String (saltBytes); // Append the salt string to the password string saltedPassword = password + saltString; // Hash the salted password string hash = FormsAuthentication.HashPasswordForStoringInConfigFile (saltedPassword, "SHA1"); // Append the salt to the hash string saltedHash = hash + saltString; return saltedHash; }
Validating Salted Hashes bool ValidatePassword (string password, string saltedHash) { // Extract hash and salt string string saltString = saltedHash.Substring (saltedHash.Length - 24); string hash1 = saltedHash.Substring (0, saltedHash.Length - 24); // Append the salt string to the password string saltedPassword = password + saltString; // Hash the salted password string hash2 = FormsAuthentication.HashPasswordForStoringInConfigFile (saltedPassword, "SHA1"); // Compare the hashes return (hash1.CompareTo (hash2) == 0); }
Authentication Cookies • Forms authentication cookies are encrypted and validated by default • Prevents reading and alteration • Doesn’t prevent theft and replay • Preventative measures are required to defend against unauthorized access
Auth Cookie Lifetime • Temporary authentication cookies • Lifetime limited (by default) to 30 minutes • Controlled by <forms> timeout attribute • Subject to sliding renewal in ASP.NET 1.0 • Sliding renewal disabled by default in 1.1 • Controlled by <forms> slidingExpiration attribute • Persistent authentication cookies • Default lifetime = 50 years! • Longer lifetime = Greater vulnerability to replay attacks
Limiting The Lifetimes Of Persistent Authentication Cookies if (Authenticate (name, password)) { string url = FormsAuthentication.GetRedirectUrl (name, true); FormsAuthentication.SetAuthCookie (name, true); HttpCookie cookie = Response.Cookies [FormsAuthentication.FormsCookieName]; // Set the cookie to expire 7 days from now cookie.Expires = DateTime.Now.AddDays (7); Response.Redirect (url); }
Securing Session State Limit session time-outs as much as possible Avoid using cookieless session state if possible Close port 42424 in firewall if using state service Disable ASP.NET state service if you're not using it Close ports 1433 and 1434 if using SQL Server Encrypt connection string if using SQL Server http://support.microsoft.com/default.aspx?scid=kb;en-us;329290
Session State Don’t store potentially injurious data (such as credit card numbers) in session state Optionally use SSL/TLS to protect session ID cookies http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT16.asp Optionally use SSL/TLS or IPSec to secure the connection to the database server http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT18.asp http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT19.asp
Error Handling Anticipate errors and handle them sensibly Use <customErrors> to display custom error pages Don't reveal too much information in error pages Beware mode="off" and debug="true" Log unhandled exceptions Be aggressive about logging failures
Logging Unhandled Exceptions Global.asax void Application_Error (Object sender, EventArgs e) { // Formulate message to write to event log string msg = "Error accessing " + Request.Path + "\n" + Server.GetLastError ().ToString (); // Write the message to Windows event log EventLog log = new EventLog (); log.Source = "My ASP.NET Application"; log.WriteEntry (msg, EventLogEntryType.Error); }
Why Is This Code Insecure? Input is neither validated nor constrained; user can type anything! <html> <body> <form runat="server"> <asp:TextBox ID="Input" runat="server" /> <asp:Button Text="Click Me" OnClick="OnSubmit" runat="server" /> <asp:Label ID="Output" runat="server" /> </form> </body> </html> <script language="C#" runat="server"> void OnSubmit (Object sender, EventArgs e) { Output.Text = "Hello, " + Input.Text; } </script> Input is echoed to page without HTML encoding
Microsoft Products And Services For Lifelong Learningwww.microsoft.com/learning Microsoft Products and Services for Lifelong Learning
DEV312 Building Secure Web Applications: Defenses And Countermeasures Jeff Prosise Co-founder Wintellect (www.wintellect.com)