From a security standpoint, ASP.NET represents a big improvement over previous incarnations of ASP. With the new platform, developers have easy methods to programmatically validate user input and access to built-in features that lock down an application. Additionally, the .NET runtime’s support of garbage collection and safe strings largely negates the success of traditional attacks. A properly secured .NET application is not only hardened against an attack, but it also limits the amount of damage that an occasional breech can create.
But despite these significant gains, ASP.NET is certainly no security panacea. Security analyst H.D. Moore, who presented three fairly major security holes in ASP.NET at the CanSecWest conference in April, says all these wonderful new features don’t amount to a hill of beans unless developers use them. Moore recommends the following simple security tips for bulletproofing your ASP.NET applications.
Exercise a little configuration control
As a general rule, never place anything in the Web root that you aren’t absolutely comfortable letting a hacker see. The exception here is any file extension that’s mapped to an ISAPI handler, which restricts access to files with extensions like .aspx, .cs, and .vb. On the other hand, files ending in .txt, .csv, and .xml are not automatically protected and can be accessed by anyone browsing the site.
Before placing any new application in production, be sure to disable tracing and debugging support, and make sure the customErrors tag in the web.config file is not set to “off.” These safeguards will help to prevent possible leaks of information such as filenames and paths, and possibly even source code, to the outside world when an error occurs in the application.
Also, clean up your project directories before putting an application in production. When deploying a new application, make sure you remove all of the Visual Studio project and temporary files in the application directory. The .sln and .slo files are not mapped to the ISAPI access filter and can consequently be accessed from the Internet if someone can guess the name of your project, which is usually a trivial task.
Avoid cookieless session management
One of the glaring problems that Moore uncovered during his evaluation of ASP.NET involved a “hijack” vulnerability in applications using the “cookie-less session management” scheme. This scheme embeds a session identifier into every URL to let the server identify a particular client. The trouble is that when a server using this feature receives a previously unknown but otherwise valid session identifier, it creates a new session to go along with it. A clever attacker can take advantage of this by “feeding” a legitimate user a URL containing a known, valid session identifier, which the attacker can use to access the system after it authenticates the duped user.
This is an insidious attack, says Moore, because the URL fed to the user would never look suspicious because only the session ID would be bogus. He recommends that developers simply avoid using cookieless session management until Microsoft removes this vulnerability.
Stay in the sandbox
While the .NET runtime’s managed environment would seem to make traditional attacks like a buffer overrun impossible to pull off, Moore points to the overflow problem he found in the StateServer class as an example of the impossible becoming possible. It appears that there’s a call to unmanaged code somewhere in StateServer with input that isn’t being correctly bounds-checked.
Moore says that developers should stick with .NET’s managed “sandbox” API whenever possible, since any call to unmanaged code could carry similar risks. However, sometimes you need that native code functionality, which brings us to our next tip.
Validate, validate, validate
Despite all the fancy new plumbing, the same old rules regarding validation of user input still apply. Developers should take full advantage of the powerful Validator controls, created by extending the System.Web.UI.Validator interface, to sanitize user input before using it internally. If you’ve never heard of .NET’s validators, you owe it to yourself to read up on them.
Use a cast
When using numeric fields in a database-driven application, make sure you actually cast those variables to an appropriate numeric type before using them. Doing so will prevent SQL insertion attacks by throwing an exception if a user places something nonnumeric into that field. With a little more work, the error handler could be configured to fire off an alert, or write to a log file, almost like a mini application-level intrusion detection system.
Less than trustworthy?
If you must install a Web application on your system that may not be entirely trustworthy, take advantage of the settings available in web.config to run that application under a different user account and then restrict what that account can access. Additionally, you can use the Internet Services Manager to configure the trust level for an application to provide a bit more security. Selecting Low Trust will run an application in its own process space, so that it theoretically will not be able to adversely affect the rest of the system or other Web apps if it is compromised or were to crash for some reason.
Share your tips
Share your favorite ASP.NET security tip by e-mailing it to the editors or posting it to our discussion below.