Application Security Testing: An Integral Part of DevOps
It's known that the .NET Framework version 1.1 is a minor upgrade with a relatively limited set of changes and updates. The stars in the what's-new list of version 1.1 are technologies that were already available as separate downloads such as the Oracle and ODBC .NET data providers and the ASP.NET mobile controls. In addition, the documentation has been revised and enriched with more examples and more clear explanations. If you look at the .NET Framework 1.1 from a technical point of view, you will not find many new features, but a lot of bug fixes and performance optimizations still make the new platform a recommended upgrade.
In this article, I focus on ASP.NET 1.1 and review a few programming related aspects that mark the difference between ASP.NET 1.0 and ASP.NET 1.1. You shouldn't look at them as a sort of top-five list of hot changes; rather you should take them as the gist of the changes that you find in the newest version of the ASP.NET platform.
This said, let's go with five examples of improvements in ASP.NET 1.1.
#5—Reading Values from List Controls
The ASP.NET framework provides a few list controls such as DropDownList, ListBox, CheckBoxList, and RadioButtonList. All these controls inherit from a common parent class named ListControl. The ListControl control class provides ad hoc properties to handle data binding and to manage item selection—in particular, SelectedIndex and SelectedItem. The former returns the 0-based index of the currently selected item (if any), whereas the latter returns the selected element as an object of type ListItem.
As you can see, there's no direct way to access the currently selected value. Of course, since you have access to the object that represents the selected item, you can obtain the current value using the Value property.
string theValue = list.SelectedItem.Value;
In ASP.NET 1.1, there's a more direct property—the SelectedValue property.
string theValue = list.SelectedValue;
In terms of implementation, the two solutions are nearly identical.
#4—The ValidateRequest Property
The @Page directive features a new boolean attribute named ValidateRequest. The attribute helps in the prevention of cross-site, one-click attacks and indicates whether request validation should occur. If ValidateRequest is set to true, ASP.NET checks all input data against a hard-coded list of potentially dangerous values. For example, if the page contains an input field with some HTML text embedded, the attribute causes ASP.NET to throw an exception during the postback processing. ValidateRequest is enabled for all pages but can be disabled both at the application level (in the <pages> section of the web.config file) and for the individual page. ValidateRequest is built to block script injection attacks but it should be clear that it is anyway a small line of defense. Much better than leaving ValidateRequest on it would be to carefully validate any input your application receives from clients.
#3—The Server.Transfer ViewState Bug
As mentioned, ASP.NET 1.1 comes with a full bag of bug fixes. I'd like to mention a couple of them here that affected 1.0 applications and magically disappeared in the newest version.
The Server.Transfer method has a couple of overloads. The first one takes the URL to transfer control to; the second one claims an additional boolean argument indicating whether or not the QueryString and Form collections are to be preserved. The default is false and the collections are emptied before the control is transferred.
When the Transfer method is used to execute a new page, for performance reasons the current HTTP handler is recycled and the context is shared. In doing so, the new page happens to work with the viewstate of the previous page (the __VIEWSTATE hidden field) still stored in the Form or QueryString collection. Subsequently, a viewstate corruption is detected and an exception is fired. This bug is fully described in KB 316920 and also affects the Server.Execute method.
#2—The HttpSessionState Vulnerability
Another bug that has been fixed regards the storage of the session state when the session state is administered in the default mode. When the HttpSessionState object is held in memory—the default case—it is stored in the Cache object. The Cache object is a global component visible to all sessions within a given application. For this reason, each active session occupies a slot in the Cache object. The name of the slot is a string that contains the session ID; the content of the slot is an internal object of type SessionStateItem. This object contains all the name/value pairs that form the state of a particular session. So far so good.
In ASP.NET 1.0, though, these internal cache items were enumerable and programmatically accessible. By simply looping on the contents of the Cache object, you can count the sessions active and access another session's state! The SessionStateItem class is not documented but, you know, this has never been a high obstacle to attackers!
The content of the Cache object is made of private and public slots and only public slots can be, in theory, enumerated and accessed. In version 1.0, a bug makes enumerable also private items. This potential vulnerability has been cleared in version 1.1.
#1—Impersonating a Fixed Identity
In ASP.NET, impersonating a fixed identity is certainly possible but, under certain conditions, a bit risky. In particular, the critical scenario is when you run ASP.NET 1.0 on a Windows 2000 server machine. For the impersonation to take place, the Windows 2000 operating system requires the code to have the SE_TCB_NAME administrative privilege. To actually impersonate an identity, the LogonUser Win32 API must be called which determines the above requirement. The ASPNET account—the default account used to run the ASP.NET worker process—doesn't have that privilege. As a result, either you change the default account to a more powerful one or you give up with impersonation of a particular user.
In Windows XP and Windows 2003 Server, a system level change occurred to make that administrative privilege no longer needed to call the API function. So what's the situation with ASP.NET 1.1 on Windows 2000? In version 1.1 you can impersonate a fixed identity without changing the account of the worker process. This is obtained by performing a trick. The trick consists in revectoring the call back to IIS. IIS—in particular, the aspnet_isapi ISAPI extension—gets the token for the specified user and copies it back to the memory of the worker process. Simple and effective.
All in all, ASP.NET 1.1 is a minor change and even disappears in comparison to the changes expected with the next major release (codenamed Whidbey). However, this doesn't mean that ASP.NET 1.1 is a useless intermediate release and that you could blissfully ignore it. ASP.NET 1.1 contains a long list of fixes and optimizations that really qualify it as ASP.NET 1.0 as it should have been done originally. Just for this, if you're using ASP.NET 1.0, there's no reason for you to skip version 1.1.
About the Author
Dino Esposito is Wintellect's ADO.NET expert and a trainer and consultant based in Rome, Italy. Dino is a full-time author, a full-time consultant and a full-time trainer. Prior to this, Dino was a full-time employee and worked day and night for Andersen Consulting focusing on the very first real-world implementations of DNA systems. Dino also has extensive experience developing commercial Windows-based software, especially for the photography world, and was part of the team who designed and realized one of the first European image online databanks. You can also check out Dino's newest book, Building Web Solutions with ASP.NET and ADO.NET.
# # #