Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles
This article presents an overview of the motivation behind new techniques that decompose problems into independent pieces for optimal use of parallel programming.

By David Callahan (October 2008)
We take a look at planned support for parallel programming for both managed and native code in the next version of Visual Studio.

By Stephen Toub and Hazim Shafi (October 2008)
Here we describe some of the more common challenges to concurrent programming and present advice for coping with them in your software.

By Joe Duffy (October 2008)
Here is an ASP.NET AJAX data-driven Web application that takes the best features from server- and client-side programming to deliver an efficient, user-friendly experience.

By Bertrand Le Roy (October 2008)
More ...
Articles by this Author
If you're unfamiliar with Windows Presentation Foundation (WPF), building that first Silverlight custom control can be a daunting experience. This article walks through the process.

By Jeff Prosise (August 2008)
As we'll show, with just a few lines of JavaScript you can build a general-purpose framework for incorporating page turns into Silverlight 1.0 apps.

By Jeff Prosise (May 2008)
: Jeff Prosise presents great tips for Silverlight development, which while it's gaining wide adoption, still needs more documentation and best practices so developers can make the most of the dazzling new features.

By Jeff Prosise (Launch 2008)
Jeff Prosise shows how you can implement drag-and-drop functionality in your Web app with ASP.NET AJAX.

By Jeff Prosise (January 2008)
Jeff Prosise explains when it's better to use UpdatePanel and when it's better to use asynchronous calls to WebMethods or page methods instead.

By Jeff Prosise (June 2007)


By Jeff Prosise (March 2007)
Jeff Prosise describes performance problems in an ASMX Web service that relied on legacy COM and Visual Basic 6.0 to perform key processing tasks and the approach he took to find a fix.

By Jeff Prosise (October 2006)


By Jeff Prosise (July 2006)
More ...
Popular Articles
See how routed events and routed commands in Windows Presentation Foundation form the basis for communication between the parts of your UI.

By Brian Noyes (September 2008)
We build a Silverlight 2.0 application using the InkPresenter to let users annotate a pre-defined collection of images, perform handwriting recognition, and save the annotations and recognized text into a server-side database.

By Julia Lerman (August 2008)
In this article we introduce you to BizTalk Services, new technology that offers the Enterprise Service Bus features of BizTalk Server as a hosted service.

By Jon Flanders and Aaron Skonnard (June 2008)
We introduce you to the benefits of building composite applications with the Composite Application Guidance for WPF from Microsoft patterns & practices.

By Glenn Block (September 2008)
More ...
Read the Blog
Multicore systems are becoming increasingly prevalent, but the majority of software today will not automatically take advantage of this additional processing ability. And multithreaded programming, for anything but the most trivial of systems, is incredibly difficult and error prone today. In the October 2008 issue of MSDN ...
Read more!
Concurrent programming is notoriously difficult, even for experts. You have all of the correctness and security challenges of sequential programs plus all of the difficulties of parallelism and concurrent access to shared resources. In the October 2008 issue of MSDN Magazine, David Callahan describes ...
Read more!
A major advantage of AJAX and Silverlight applications is that they can transparently and continuously interact with a back-end service. The problem is that they run over HTTP, which wasn't designed with security in mind. In the September 2008 issue of MSDN Magazine, Dino Esposito shows you ...
Read more!
Unhandled exception processing shouldn't be a mystery. It's actually quite useful since it gives a crashing application an opportunity to perform last-minute diagnostic logging about what went wrong. In the September 2008 issue of MSDN Magazine, Gaurav Khanna discusses how ...
Read more!
Silverlight 2 data-binding features are simple to implement and let your apps communicate via WCF services with line-of-business applications, databases, and other services in your organization. In the September 2008 issue of MSDN Magazine, John Papa demonstrate how to build a ...
Read more!
The Security Development Lifecycle (SDL) team recently released details of the SDL process at microsoft.com/sdl. What you won't find in the publicly available SDL documentation is guidance specific to securing Web applications or online services. In the September 2008 issue of MSDN ...
Read more!
More ...
New information has been added to this article since publication.
Refer to the Editor's Update below.

Wicked Code
Foiling Session Hijacking Attempts
Jeff Prosise

Code download available at: WickedCode0408.exe (118 KB)
Browse the Code Online
Let's face it: every minute of every day, someone, somewhere, is patrolling the Web looking for sites to hack. ASP.NET developers must constantly be on their guard to ensure attempted hacks can't be successful. That means constraining and validating user input, accessing databases securely, storing sensitive data securely, and generally writing secure code that repels rather than accommodates these malevolent hackers.
A classic form of hack attack that ASP.NET sites must defend against is session hijacking. Simply put, session hijacking entails connecting to a Web site and accessing someone else's session state. The severity of the damage incurred depends on what's stored in session state. If sessions hold shopping cart information and users are required to verify their identities before checking out, session hijacking might not be very damaging. If sessions contain credit card numbers or similarly sensitive data that can be presented back to the user, you really have to watch out.
Session hijacking attacks are typically perpetrated in one of two ways: session ID guessing and stolen session ID cookies. Session ID guessing involves gathering a sample of session IDs and "guessing" a valid session ID assigned to someone else. ASP.NET apps tend to be much less susceptible to this form of session hijacking because ASP.NET uses highly random 120-bit numbers for its session IDs. Unless you replace ASP.NET session IDs with IDs of your own (last summer I met one developer who had done just that and used sequential session IDs, which are an open door to hackers), you have nothing to fear from session ID guessing.
Stolen session cookies are another matter. Secure Sockets Layer (SSL) can be used to protect session ID cookies on the wire, but few sites restrict session ID cookies to encrypted connections. Even if you use SSL, session ID cookies can be stolen in other ways, notably through cross-site scripting attacks, man-in-the-middle attacks, and gaining physical access to the cookie stores on victims' PCs. Furthermore, executing a successful session hijacking attack with a stolen session ID cookie requires little skill on the part of the attacker. The reason is simple: ASP.NET encodes no information in a session ID cookie other than the session ID. If it receives a cookie containing a valid session ID, ASP.NET connects to the corresponding session, no questions asked.
It's virtually impossible to build a foolproof defense against attacks that rely on stolen session ID cookies, but you can take steps to make it harder. Some Web sites, for example, encode heuristic information such as IP addresses in their session IDs. That doesn't prevent session hijacking altogether—after all, some hackers possess the means to spoof IP addresses, and IP addresses are not a reliable means for identifying callers anyway—but it does raise the bar. Security is all about raising the bar. The harder you make it for a hacker to execute a successful attack, the less likely it is that successful attacks will occur.

Introducing SecureSessionModule
[ Editor's Update - 7/20/2004: Figure 1 has been updated so as not to provide too much information to an attacker.]
Figure 2 shows how SecureSessionModule works. First, it checks every outgoing response for a session ID cookie issued by ASP.NET's SessionStateModule. When it sees such a cookie, SecureSessionModule modifies it by appending a hashed message authentication code (MAC) to the session ID. The MAC is generated from the session ID, the network address portion of the requestor's IP address (for example, the 192.16 in 192.16.0.14), the User-Agent header received in the request, and a secret key stored on the server. The Framework's System.Security.Cryptography.HMACSHA1 class makes the task of generating the MAC really quite easy.Why use the network address instead of the full IP address? The node address of users that access the Internet through public proxy servers such as AOL's can change in every request, but the network address should not.
Figure 2 SecureSessionModule 
Second, SecureSessionModule examines every incoming request for an ASP.NET session ID cookie. Before allowing a request containing a session ID cookie to continue through the pipeline, SecureSessionModule validates the cookie by regenerating the MAC from the requestor's IP address, the User-Agent header, and the secret key. If the freshly computed MAC matches the one in the cookie, the MAC is stripped from the cookie and the request is allowed to proceed. If the MACs don't match, SecureSessionModule throws an InvalidSessionException, as shown in Figure 3.
The net result is that once a session ID cookie is issued, it's only considered valid if it's submitted from the same network address and with the same User-Agent header. An attacker who steals a session ID cookie can only use it if she can spoof IP addresses and HTTP headers. Both are certainly possible, but spoofing of this sort requires a higher skill level on the part of the attacker. In addition, getting a response back from a request with a spoofed IP address is much harder than simply submitting the request in the first place and can be defeated with proper egress filtering. It's impossible for the attacker to simply replace the hash in the cookie with one generated from her own IP address and User-Agent header without the secret key used to generate the MAC. To the extent that the key can be secured, casual hackers will find it difficult indeed to use stolen session IDs for nefarious purposes.

Deploying SecureSessionModule
Deploying SecureSessionModule is as simple as copying SecureSessionModule.dll into the application root's bin subdirectory and registering it in Web.config, like so:
<configuration>
  <appSettings>
    <add key="SessionValidationKey"
      value="DAD4D476F80E0148BCD134D7AA5C61D7" />
  </appSettings>
  <system.web>
    <httpModules>
      <add name="SecureSession"
        type="SecureSessionModule, 
          SecureSessionModule" />
    </httpModules>
  </system.web>
</configuration>
The SessionValidationKey value in the <appSettings> section of Web.config is required. This is the "secret key" used to generate the MAC; SecureSessionModule looks for it at load time and throws an exception if it's not there. The key should be unique for every application, and it should be long and random. I used a simple tool built around the .NET Framework RNGCryptoServiceProvider class to generate the one in Figure 3. You should use a similar tool to maximize randomness. In addition, if deployed on a Web farm, SessionValidationKey should be the same on every server. Of course, storing plaintext security keys in configuration files poses risks of its own. For an added measure of security, consider encrypting the secret key. The article at Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication describes how to use the Windows® Data Protection API (DPAPI) from ASP.NET. DPAPI is ideal for encrypting secrets in configuration files because it offloads the problem of key management—specifically, storing decryption keys—to the operating system itself.
Ideally, SecureSessionModule would use the same secret key that ASP.NET uses for hashing: the value of the validationKey attribute in Machine.config's <machineKey> element. However, there is no public API for retrieving this key, and after inspecting what the Framework does to retrieve validationKey, I elected not to duplicate the logic in the Framework to avoid potential incompatibilities with future versions of .NET. The new configuration API coming in version 2.0 of the .NET Framework will correct this omission and provide a documented means for reading the ASP.NET validation key.
Once deployed, SecureSessionModule works passively—no intervention is required. If you'd like, include an Application_Error method in Global.asax to log InvalidSessionExceptions in the Windows event log or elsewhere. That way you can check the log every morning over your first cup of coffee and find out if someone has been trying to spoof your server with stolen session IDs. Such a method might look like this:
<%@ Import Namespace="System.Diagnostics" %>

<script language="C#" runat="server">
void Application_Error(Object sender, EventArgs e)
{
    // Write an entry to the event log
    EventLog log = new EventLog ();
    log.Source = "My ASP.NET Application";
    log.WriteEntry (Server.GetLastError().ToString(),
        EventLogEntryType.Error);
}
</script>

Caveats
Before deploying SecureSessionModule on a production Web server, you should consider several potential issues.
First, SecureSessionModule is not 100 percent effective in detecting illicit session ID cookies. If the attacker has the same network address as the victim (if both, for example, use the same proxy server) or can spoof the victim's network address, then User-Agent headers are the last line of defense. And User-Agent headers are easily spoofed by someone aware that User-Agent headers are being used to validate session IDs.
Second, if for some reason a user's network address or User-Agent headers vary from request to request, that user will lose access to her session state. Third, SecureSessionModule doesn't work with cookieless session state. It assumes session IDs are passed in cookies, not URLs.
Finally, SecureSessionModule hasn't been tested in a production environment. If you use it, I'd love to hear from you—especially about any glitches that arise. Note that Microsoft has considered building similar protections into ASP.NET, but has always shied away from it for backward compatibility concerns.

Conclusion
Session hijacking remains a serious threat to security. SecureSessionModule raises the bar for hackers who hijack sessions using stolen session IDs by factoring evidence about the session owner into the session ID cookie. That evidence isn't conclusive because neither network addresses nor User-Agent headers can be used reliably to distinguish one user from another, but it nonetheless places an additional hurdle in the path of hackers who are actively seeking to compromise your Web servers by connecting to other users' sessions and grabbing their data.

Send your questions and comments to Jeff at  wicked@microsoft.com.


Jeff Prosise is a contributing editor to MSDN Magazine and the author of several books, including Programming Microsoft .NET (Microsoft Press, 2002). He's also a cofounder of Wintellect, a software consulting and education firm that specializes in Microsoft .NET. Contact Jeff at wicked@microsoft.com.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker