Preventing Session Fixation through Session ID Regeneration in Java and ASP.NET


Dec 27, 2007

Let’s suppose I wanted to steal a car. One way I could do it is to buy a car, make a copy of the key, sell the car to a victim, tail them and then drive the car away with my copied key while the unsuspecting victim is off purchasing a Frappucino.

Maybe this wouldn’t work in the paper-and-ink real world, but it’s actually pretty easy in the virtual one. It is analogous to the web application attack called Session Fixation.

Session Fixation is a vulnerability caused by an attacker forcing a victim to use a known session ID. Once the victim has authenticated, the attacker can hijack the session using the known session ID. There are multiple ways an attacker could get a victim to use a known session ID. For example, the attacker could entice a user to respond to a phishing email by clicking the following link:

https://www.example.com/index.html?sessionid=[knownvalue]

Note that this link appears to come from the correct domain, and would not cause an SSL error message. The caveat is that the application must accept the session ID as a get argument.

Additionally, an attacker could access a shared terminal (in a library, or a cafe) and visit several vulnerable sites, collecting session IDs, without authenticating. They could then continue to attempt to access these sites and see if the session has been authenticated (while keeping the session from expiring) until a victim logs in to a site using the shared terminal.

The most efficient way to curtail this vulnerability is to regenerate the session ID when a user logs in. It renders the known session ID useless. Let’s take a look at how this applies (or doesn’t!) to Java and .NET.

Java

In Java, there is not well-supported programmatic access to the JSESSIONID cookie. You can’t change the name of the cookie or set cookie properties (such as HttpOnly) very easily. However, in Java, it is possible to invalidate and recreate the session (not the session ID, necessarily) using the following code:

session.invalidate();

session=request.getSession(true);

This is also the OWASP recommendation, although it isn’t explained in much detail on the site. Note I said that this does not regenerate the session ID necessarily. Looking at the comment thread for this blog, it appears JBoss doesn’t regenerate the JSESSIONID using this code. I haven’t confirmed this myself, but there is no guarantee in the Java specification that the session.invalidate will actually regenerate the session ID if it is recreated using request.getSession during the same request. So be careful and test if you use this method – I tried the code with Tomcat, and it worked, but I can’t vouch for the other Java application servers.

In addition, you have to manually copy over all of the current data in the session. This may be necessary when designing an experience like Amazon.com, where you can add things to your cart before you log in. You would have to make sure that this information is persisted in the new session after authentication. This is an inconvenience, but is certainly doable.

ASP.NET

ASP.NET may have less of a problem with session fixation if you are using the ASP.NET Forms Authentication mechanism. A separate Forms Authentication token will be used after authentication, and since the attacker cannot set this value before the victim authenticates, it prevents a full-scale session fixation attacker. However, while this makes the ASP_NETSESSIONID less useful, it doesn’t entirely negate the threat of session fixation.

For instance, depending on how the application is designed, an attacker could use his or her own Forms Authentication token along with the hijacked session to access data from the hijacked session.

ASP.NET does not directly support functionality to regenerate a session ID. See the documentation regarding the issue here. There is a not-so quick and dirty way to do it by setting the ASPNET_SessionID value to the empty string and redirecting so that the value is regenerated.

I think both platforms need to re-examine the fact that session ID regeneration is an important security feature, and implement simple APIs for regenerating the session ID without creating a new session. Perhaps they should even perform session regeneration on login and privilege escalation by default, creating a pit of success. I think this points to the fact that session mechanisms in web applications have a huge, but often underappreciated, security relevance.