Basic Security Practices for Web Applications
The topic of creating a secure Web application is a long one. It requires study to understand security vulnerabilities. You also need to familiarize yourself with the security facilities of Windows, the .NET Framework, and ASP.NET. Finally, it is essential to understand how to use these security features to counter threats.
However, even if you are not experienced with security, there are basic measures that you should take to protect your Web application. The list below provides minimum-security guidelines that apply to all Web applications.
- General Web Application Security Recommendations
- Run Applications with Least Privileges
- Know Your Users
- Guard Against Malicious User Input
- Access Databases Securely
- Create Safe Error Messages
- Keep Secrets Safely
- Guard Against Denial-of-Service Threats
Some of the most basic security recommendations are also the most obvious ones. However, even the most elaborate application security can fail if a malicious user can use simple ways to get to your computers.
- Back up often and keep your backups physically secure.
- Keep your Web server computer physically secure so that unauthorized users cannot get to it, turn it off, take it, and so on.
- Use the Windows NTFS file system, not FAT32. NTFS offers substantially more security than FAT32. For details, see the Windows documentation.
- Secure the Web server computer and all computers on the same network with strong passwords.
- Secure IIS. For details, see the article Manage Security of Your Windows IIS Web Services in the Microsoft security Web site (http://microsoft.com/technet/treeview/default.asp?url=/technet/security/bestprac/mcswebbp.asp).
- Close unused ports and turn off unused services.
- Run a virus checker that monitors traffic.
- Establish and enforce a policy that forbids users from keeping their passwords written down in an easy-to-find location.
- Use a firewall. For recommendations, see Checklist: Install a Firewall) on the Microsoft security site. (http://microsoft.com/security/articles/firewall.asp)
- Learn about and install the latest security patches from Microsoft and other vendors. For example, the Microsoft security site (www.microsoft.com/security) has a list of the latest security bulletins for all Microsoft products. Other vendors have similar sites.
- Use Windows event logging and examine the logs frequently for suspicious activity. This includes repeated attempts to log on to your system and an extremely high number of requests against your Web server.
When your application runs, it runs within a context that has specific privileges on the local computer and potentially on remote computers. Follow these guidelines:
- Run the application in the context of a user with the minimum practical privileges. By default, under IIS version 5, an ASP.NET application runs in the context of a local user called ASPNET. In IIS 6 on Windows Server 2003, the account is called NETWORK SERVICE.For details, see ASP.NET Process Identity and Configuring ASP.NET Process Identity.
- Do not run your application within the context of a system user (administrator).
- Set permissions (ACLs, or Access Control Lists) on all the resources required for your application. Use the least permissive setting. For example, if practical in your application, set files to be read-only. For details, see the Windows documentation.
- Keep files for your Web application in a folder below the application root. Do not allow users the option of specifying a path for any file access in your application. This helps prevent users from getting access to the root of your server.
- Do not make anyone a member of the Debugger Users group who does not need to debug Visual Studio applications. This group has higher privileges than the VS Developers group. For details, see Adding Debugger Users and Configuring DCOM.
In many applications, it is possible for users to access the site without having to provide credentials. If so, your application accesses resources by running in the context of a predefined user. By default, this context is the local ASPNET user (Windows 2000 or Windows XP) or NETWORK SERVICE user (Windows Server 2003) on the Web server computer.
To restrict access to users who are authenticated, follow these guidelines:
- If your application is an intranet application, configure it to use Windows integrated security. That way, the user's logon credentials can be used to access resources.
- If you need to gather credentials from the user, use one of the ASP.NET authentication strategies. For more information, see ASP.NET Authentication. For an example, see Simple Forms Authentication.
As a general rule, never assume that input you get from users is safe. It is easy for malicious users to send potentially dangerous information from the client to your application. To guard against malicious input, follow these guidelines:
- In forms, filter user input to check for HTML tags, which might contain script. For details, see Protecting Against Script Exploits in a Web Application.
- Never echo (display) unfiltered user input. Before displaying untrusted information, encode HTML to turn potentially harmful script into display strings.
- Similarly, never store unfiltered user input in a database.
- If you want to accept some HTML from a user, filter it manually. In your filter, explicitly define what you will accept. Do not create a filter that tries to filter out malicious input; it is very difficult to anticipate all possible malicious input.
- Do not assume that information you get from the header (usually via the Request object) is safe. Use safeguards for query strings, cookies, and so on. Be aware that information the browser reports to the server (user agent information) can be spoofed, in case that is important in your application.
- If possible, do not store sensitive information in a place accessible from the browser, such as hidden fields or cookies. For example, do not store a user name or password in a cookie.
Note View state is stored in a hidden field in an encoded format. By default, it includes a message authentication code (MAC) so that the page can determine whether view state was tampered with.
Databases typically have their own security. An important aspect of a secure Web application is designing a way for the application to access the database securely. Follow these guidelines:
- Use the inherent security of your database to limit who can access database resources. The exact strategy depends on your database and your application:
- If practical in your application, use integrated security so that only Windows-authenticated users can access the database. Integrated security is more secure than using connection strings.
- If your application involves anonymous access, create a single user with very limited permissions, and perform queries by logging on as this user.
- Do not create SQL statements by concatenating strings that involve user input. Instead, create a parameterized query and use user input to set parameter values. For details, see Parameters in Data-Adapter Commands.
- If you must store a user name and password somewhere to use as the database login credential, store them securely. If practical, encrypt them. For details, see Encrypting and Decrypting Data. For an introduction to encryption, see Geek Speak Decoded #9: Cryptography and Encryption.
If you are not careful, a malicious user can deduce important information about your application from the error messages it displays. Follow these guidelines:
- Do not write error messages that echo information that might be useful to malicious users, such as a user name.
- Configure the application not to show detailed errors to users. If you want to display detailed error messages for debugging, check first that the user is local to the Web server. For details, see Displaying Safe Error Messages.
- Create custom error handling for situations that are prone to error, such as database access.
Secrets are any information that you do not want someone to know. A typical secret is a password or an encryption key. Of course, if a malicious user can get to the secret, then the data protected by the secret is compromised. Follow these guidelines:
- If your application transmits sensitive information between the browser and the server, consider using the Secure Sockets Layer (SSL). For details on how to implement SSL, see Microsoft Knowledge Base article Q307267, "HOW TO: Secure XML Web Services with Secure Socket Layer in Windows 2000."
- If you must store secrets, do not keep them in a Web page, even in a form that you think people will not be able to see it (such as in server code).
- If you encrypt information, do not create your own encryption algorithm. Use the Windows Data Protection API (DPAPI).
- Do not store any critical information in cookies. For example, do not store a user's password in a cookie, even temporarily. As a rule, do not keep anything in a cookie that, if spoofed, can bring you trouble. Instead, keep a reference in the cookie to a location on the server where the information is.
- Set expiration dates on cookies to the shortest practical time you can. Avoid permanent cookies if possible.
- Consider encrypting information in cookies.
An indirect way that a malicious user can compromise your application is by making it unavailable. The malicious user can keep the application too busy to service other users, or if nothing else can simply crash the application. Follow these guidelines:
- Close or release any resource you use. For example, always close data connections and data readers, and always close files when you are done using them.
- Use error handling (for example, try-catch). Include a finally block in which you release resources in case of failure.
- Configure IIS to use process throttling, which prevents an application from using up a disproportionate amount of CPU time. For details, see the technical article Using the New Features in Internet Information Server 5.0: Part 1.
- Test size limits of user input before using or storing it.
- Put size safeguards on database queries. For example, before you display query results in a Web Forms page, check that there are not an unreasonable number of records.
- Put a size limit on file uploads, if those are part of your application. You can set a limit in the Web.config file using syntax such as the following, where the
maxRequestLengthvalue is in kilobytes:
<configuration> <system.web> <httpRuntime maxRequestLength="4096" /> </system.web> </configuration>
Overview of Web Application Security Threats | Security Portal | Securability | Best Practices for Securability | Designing Secure ASP.NET Applications | ASP.NET Web Application Security | Security Bibliography