Limiting Exposure to Malicious Input
Application attacks are widespread and varied, but we have yet to discover all the possible ways a hacker could exploit your Web application. It is also improbable that every developer will write secure code 100% of the time. Security flaws are bugs, and no amount of developer training or funds can guarantee bug-free code. So while you should take every opportunity to secure your code, you must also take measures to limit exposure to attacks and make your application more resilient to hackers. In this section we will cover:
Reducing the attack surface
Limiting attack scope
Hardening server applications
Reducing the Attack Surface
Summary: | Reduce the attack surface of your application to provide fewer opportunities to hackers. |
Threats: | Malicious input |
All code has a certain probability of containing flaws. The more code you have, the higher the probability your application will have flaws. The more flaws you have, the greater the attack surface of your application. Attack surface represents your application’s exposure to attack, but not necessarily its vulnerability to attack. Consider a bank, for example: the outer walls and roof of the building are its attack surface. Some areas, such as windows and doors, are more vulnerable to attack than other areas, such as brick walls. And although brick walls are exposed and are part of the attack surface, they are likely not going to be vulnerable to attack. Nevertheless, a bank robber could drive a tank through a bank wall, so therefore it is part of the attack surface.
Vulnerability depends greatly on other factors, such as how easily a bank robber could get his hands on a tank, his willingness to rob the bank, or how much money is in the bank itself. It also depends on how quickly the robber could execute the plan without getting caught. Despite all these factors, the bank’s attack surface remains the same. In fact, the bigger the bank, the bigger the attack surface. And if a bank has multiple branches, each one increases the overall attack surface for the bank as a whole.
A Web application also has an attack surface. This attack surface is made up of every dynamic Web page, every open TCP/IP port, every system account, and every running application or service, among a list of other factors. Many security efforts address the need to reduce an application’s attack surface. A firewall, for example, limits the number of accessible TCP/IP ports. There are also a number of techniques for limiting attack surface within your application itself.
The attack surface consists of any component of your application that meets these requirements:
The component is visible or discoverable by the attacker.
The component is accessible to the attacker.
The component is potentially exploitable, even though actual vulnerability might not be foreseeable or likely.
Note that addressing any of these items will reduce your application’s attack surface. With this in mind, there are many creative strategies you could use to reduce exposure to attack.
Unused Code
As your Web application matures and grows in features, you might find yourself adding more and more functionality to key modules. Sometimes a central module expands to handle much of the functionality of the application. Consider, for example, this URL from Microsoft’s search engine application that contains nine parameters:
http://search.microsoft.com/search/results.aspx?na=81&st=a&View=enus& qu=asp.net&qp=&qa=&qn=&c=2&s=0
Notice that this particular search does not even make use of all the parameters, so therefore their values are empty. While this is not a vulnerability, it increases the attack surface because it offers the hacker a variety of potential attack vectors. If you are not using a parameter, don’t even show the parameter. The less the hacker can see, the less there is to exploit. Although this does not increase the actual attack surface of the application, it has the same effect because it limits the attacker’s ability to discover all the available parameters.
Warning | Hiding parameters does not mean that you need not secure the code that handles them. Obscurity does not replace security, but it does enhance other security measures you might have in place. If fewer people see the parameters, fewer will attack them; therefore it has the effect of reducing the attack surface. |
Even though you should hide unused parameters, you must also consider parameters that should not even be there in the first place. You might, for instance, have code that handles parameters that should not exist in the production application. Carefully review each module to identify any debugging, testing, or dead code. Never rely on obscurity to hide this type of parameter.
Limiting Access to Code
The most obvious way to limit attack surface is to limit the code in your application. A single static HTML page is much more secure than a fully functional e-commerce application. The less code you have, the less there is to attack. While this is not a realistic strategy, you can accomplish the same effect by limiting access to components of you application.
Carefully consider how you allow access to these features:
Online demos You might want to showcase the features of your application with an online demo, but this gives everyone access to all of your code. Instead, consider providing static HTML demos that only simulate the features of the full application. Doing this doesn’t fix any vulnerabilities you might have, but it does have the effect of reducing the attack surface, limiting access only to customers or registered users.
Administration or content-management modules Your administration pages might require authentication to gain access, but the authentication page itself might be vulnerable. Limit access to administration modules by enforcing IP restrictions, using obscure ports, using client certificates, and moving administration modules to a separate Web site.
Intranet or extranet modules Restrict access to intranet or extranet modules using the same strategies as with administration modules.
Sample code and applications Many Web servers or applications come with sample or default code, or programs that should always be removed when migrating to a production environment.
Third-party applications Many organizations opt to buy rather than build certain features in their Web application. There are thousands of widely available search engines, shopping carts, guest books, user management, and content management systems. Running one of these might not make you vulnerable, but consider that just about anyone can gain access to the source code. Wide code availability has the effect of increasing the attack surface, especially if it is a popular component used on many different Web sites. Some hackers will find a vulnerability in these components and then use a search engine to discover which sites use this component. If you do use third-party components, try obscuring their identities, and always review and test the code carefully.
Security Policy
Reduce the attack surface of the application to limit exposure to hackers.
Don’t show query string parameters if you do not use them in a particular context.
Remove testing, debug, and dead code from production applications.
If possible, use static content in application demos.
Limit access to administration or other private modules.
Remove sample code and programs from production servers.
Avoid or carefully audit third-party components.
Limiting Attack Scope
Summary: | Use security permissions to limit the scope of attacks. |
Threats: | Malicious input |
It might be impossible to build a bullet-proof application that is impervious to all current and future application-level attacks. You can filter input and reduce your attack surface, but you must also consider that someone might eventually find a way to exploit your code. Build your application so that exploiting your code does not provide much information for the attacker.
Least Privilege
An important strategy is to always follow the principle of least privilege. Consider the security context of the Web application user and evaluate this user’s access to the following:
The file system
Registry keys
Executables
COM components
WMI classes
TCP/IP ports
Databases
Other Web sites on the same server
Plan the security context of your Web application to properly limit access to these items. Careful attention to user security will contain and separate the Web application from the rest of the operating system.
Server-Side Code
A common mistake Web developers make is assuming that server-side code is protected from intruders. Although it is meant to be protected, experience has shown us that this is not always the case. You should work with the assumption that this code is not safe, and therefore take appropriate precautions with what you include in these files. Server-side code is not an appropriate place to store secrets such as passwords, database connection strings, or other sensitive information. Sometimes something as simple as a comment could reveal vital information for an intruder to further an attack. Look at your server-side code from the perspective of a hacker to see what information might be a security risk.
Security Policy
Use the principle of least privilege to limit the access of Web users.
Avoid storing passwords, private comments, or other sensitive information in server-side code.
Hardening Server Applications
Summary: | Many Web applications have settings to protect from various types of attacks. |
Threats: | Malicious input |
Writing secure code is an important way to defend yourself from attack, but ASP.NET and IIS both help in this effort by providing settings to prevent or mitigate application-level attacks. Some settings you can use to harden your Web server against attack are as follows:
Request Length
Some attacks rely upon being able to send data beyond expected limits. A buffer overflow, for example, might require sending a very large string as part of the Web request. IIS 6.0 allows you to limit the size of the entity body of a request with the MaxRequestEntityAllowed and AspMaxRequestEntityAllowed metabase settings. Both of these settings let you set the maximum size, in bytes, for the entity body of a request, as specified by the HTTP content-length header. In other words, the content-length header of a request cannot exceed the limits imposed by these settings. MaxRequestEntityAllowed can be set at any level of the metabase, such as for the server, a specific site, a virtual directory, or even for a single file. The AspMaxRequestEntityAllowed setting is similar, but applies only to ASP files.
IIS 6 also provides registry settings for specific control over the length of various parts of a request. Table 5.6 summarizes these settings.
Value | Range | Default Value | Description |
---|---|---|---|
MaxFieldLength | 64 to 65,534 (bytes) | 16k | Maximum length of any individual header |
MaxRequestBytes | 256 to 16,777,216 (bytes) | 16k | Maximum length of the request URI and any headers |
UrlSegment MaxLength | 0 to 32,766 (characters) | 260 | Maximum length of any single URL segment (that is, a single directory in a full path) |
UrlSegment MaxCount | 0 to 16,383 (segments) | 255 | Maximum number of URL segments in a request |
Allowed Characters
To limit exposure to directory traversal and encoding attacks, IIS 6 provides several registry settings to limit which characters users can send in a request. These two settings are shown in table 5.7.
Value | Range | Default Value | Recommended Value | Description |
---|---|---|---|---|
AllowRestrictedChars | 0 or 1 | 0 | 0 | If set to 0, accepts hex-escaped chars in request URLs that decode to U+0000 to U+001F and U+007F to U+009F ranges |
EnableNonUTF8 | 0 or 1 | 1 | 0 | If set to 1, the server allows requests that contain ANSI or DBCS characters. |
PercentUAllowed | 0 or 1 | 1 | 0 | If set to 1, allows requests that contains characters encoded in the %UNNNN format |
The first of these settings, EnableNonUTF8, allows you to limit requests so that they contain only UTF-8 encoded characters. This helps prevent ambiguity with various character encodings.
The second setting, PercentUAllowed, allows users to send request URLs using the format %UNNNN, where NNNN is the Unicode value of the character you want to submit. Again, allowing this might cause ambiguity, so it is best not to allow this unless you have a specific use for it.
Security Policy
Use the MaxRequestEntityAllowed and AspMaxRequestEntityAllowed metabase settings to limit the overall length of a request.
Use the MaxFieldLength, MaxRequestBytes, UrlSegmentMaxLength, and UrlSegmentMaxCount registry settings to limit the length of specific parts of a request.
Use the EnableNonUTF8 and PercentUAllowed registry keys to limit valid characters in a request.