AppSec Blog

AppSec Blog

Session Attacks and ASP.NET - Part 2

In Session Attacks and ASP.NET - Part 1, I introduced one type of attack against the session called Session Fixation as well as ASP.NET's session architecture and authentication architecture. In this post, I'll delve into a couple specific attack scenarios, cover risk reduction, and countermeasures.

Attack Scenario: ASP.NET Session with Forms Authentication


So understanding the decoupled nature of ASP.NET's session management from the authentication mechanisms outlined in the previous post, let's walk through two different session fixation attempts with Forms Authentication and session management.

Scenario 1: Attacker does not have a Forms Authentication Account

  1. Attacker browses target web site and fixates a session
  2. Attacker traps victim to use the fixated session
  3. Victim logs in using Forms Authentication and moves to areas of the site protected by forms authorization
  4. Attacker cannot pursue because he has not authenticated.
Not a big deal - UNLESS session reveals information or makes decisions outside of an authenticated area (within the same Application of course), which is very plausible. If the programmer happened to use Forms authentication and then strictly uses Session to make security decisions (no IPrincipal role authorization with Principal Permissions or authorization sections in the web.config), some real issues can result. Since session is decoupled from authentication, any area not controlled by authorization that shows session information can be exploited by the attacker.

Scenario 2: Attacker has their own Forms Authentication account

  1. Attacker browses to web site and fixates a session.
  2. Attacker Logs in to site using Forms Authentication.
  3. Attacker traps victim to use the fixated session.
  4. Victim logs in and moves to areas of the site protected by forms authorization.
  5. Attacker, still logged in under their own credentials, has the victim's session.
This was odd and even surprising to me at first when I actually pulled it off, but it works because Authentication is completely decoupled from the Session Management - they are tracked separately (different cookies, remember?).

Consider next that session fixation isn't the only problem - any session attack can take advantage of the decoupled nature of ASP.NET Session management and Authentication. If the attacker can fixate, hijack, or steal a Session from the victim, this type of attack will succeed no matter if the web site uses Forms Authentication, Windows Authentication, Client Certificates, etc. It doesn't matter. As long as the attacker also has an account in the system as well as the victim's Session ID, they can take over the session...that is unless the developer adds some additional checks - more on this later.

The take-away point is this - out of the box, authentication within ASP.NET does not provide protection from session attacks . This means that ASP.NET's session implementation is not concerned with the security of session as it relates to authentication. Session is a feature that developers can provide to any user, authenticated or not.

This means that developers must understand the implications of the asymmetrical relationship between session and authentication and protect against it or the ASP.NET sites will be vulnerable to various session attacks.

Countermeasures


The session infrastructure in ASP.NET is okay, but not as robust from a security perspective as it could (or should be, in my opinion). The ASP.NET session keyspace is decent - 120 bytes with good entropy, and a default 20 minute sliding window for expiration (30 minutes for Forms Authentication).

Comparing the configuration features APPLICABLE for securing the cookie for Forms Authentication vs Session - it's clear great care was taken to provide a broad range of options to protect the Forms Authentication Ticket cookie. The Session configuration options pale in comparison.












Web.Config OptionSession CookieForms Cookie
Cookieless++
Timeout++
Require SSL-+
Cookie Domain-+
Cookie Path-+
Disable Sliding Expiration-+

Table - 1: Forms vs. Session Options

While not an "apples to apples" comparison (since session and authentication are different animals), the point I want to illustrate is this is the Cookie Protection features for both should be similarly strong.


Cookieless - should be avoided for both Forms Authentication and Session at all costs. It's just too easy to hijack a session with the ID in the URL unless you really aren't concerned so much with security.

Timeout - This timeout is typically a sliding value - so as long as the user is active on the site, the cookie remains valid (session OR authentication).

Require SSL - This requires that SSL be enabled for the Cookie to be transmitted. Forms authentication allows this, Session does not (though you can certainly do this programmatically which is a good idea if your site security should requires a higher level of protection).

Cookie Domain - This allows you to override the default domain on the cookie.

Cookie Path - This allows the cookie to be used for certain paths. This is important, as it can limit the area of the site where the cookie is valid. Forms Authentication allows this, Session does not, but perhaps could be set programmatically (not sure what the side effects would be, since ASP.NET may attempt to create a new cookie if the session object is used outside the set path). This could potentially help add protection to the session if this cookie path is to set to only authorized areas of the site.

Sliding Expiration - By setting this to false, Forms Authentication allows an absolute expiration of the cookie. For example, you can force expiration every 10 minutes, whether the user is active or not. With session, there's no way to force expiration.


While none of the above features are a slam-dunk 100% mitigation, they all certainly reduce risk. If ASP.NET was able to allow the Authentication Modules to collaborate with the Session module internally in certain situations through configuration, that would go a long way to add some protections in ASP.NET against session attacks.

So then the BEST solution, would be for ASP.NET to issue a NEW session ID after any successful authentication, and then transfer the session over to the new Session ID. That way if the attacker has a victim's session, once they log in, it will vaporize from the attackers perspective. Or better yet, NEVER deliver session until the user logs in. There's some code that looks like it may allow a new session ID to be distributed on login in KB899918 [4], but it's not presented in any useful or reusable way for the masses. The code is incredibly long and difficult to follow due to the nuances of setting cookies, allowing redirects, etc. The language of the KB article is also not very clear.

A way to mitigate (and even detect) this attack now for Forms Authentication or any other authentication mechanism, is to simply store something related to the Authentication in Session. Then on each subsequent request, make sure they match. This couples the authentication mechanism to session management - if they don't match - then a session attack occurred (or something's out of sync programmatically). So for Forms Authentication, you would store the Forms Authentication Ticket Name in Session. This value is stored in the forms cookie which is encrypted and persisted to the client after authentication and can be configured to be transmitted only over SSL/TLS.

Once you couple session and the authentication mechanism together and than configure Forms authentication properly, you can provide adequate session protection. Another important point - don't use Session anywhere outside of the authenticated areas of your site.

What Should Be Done?


As noted in Part 1, Microsoft closed a Bug submitted for this issue. To be fair, Microsoft has worked hard to improve the security of their code through the Security Development Lifecycle. To me, adding this feature in future versions of .NET is a no-brainer and right in step with their current security approach.

So back to the original question:

Should ASP.NET improve the session management module in ASP.NET to allow for more secure configuration by coupling it with Authentication mechanisms in ASP.NET?

I guess it depends on your perspective. The fundamental question is should Session be coupled to an authentication mechanism? This will depend on what the web site is doing and the level of acceptable risk, etc. If so, the session HTTP Module would need to be aware of the other Authentication HTTP Modules (which sort of breaks the pattern). Another option would be for each HTTP Module to implement its' own or share a common session manager...of course there are situations when you might want to use session without requiring authentication - should SSL, Path and Domain be configurable in the web.config for <sessionState>? Or should things remain as they are, and should those concerned with the issue just fix it in code as described above?

Should the onus be on the developer to know about this and mitigate it in code? Without having the feature in the framework and in the MSDN documentation, most developers will remain in the dark about these issue. Remember, we're still dealing heavily with SQL Injection and XSS issues in web sites...issues that we have known about how to protect against for years.

The INFOSEC community will almost always recommend you move a session after Authentication, meaning they have to be tied together (if the risk profile is such that you need that level of protection) - ASP.NET's is decoupled - there-in lies the issue...

Love to hear your thoughts as well!

References


Here's what a somewhat brief Google turned up for me on Session Fixation and ASP.NET - nothing quite seemed to address the issues described above:

[1] Threats and Countermeasures for Web Services
http://msdn.microsoft.com/en-us/library/cc949001.aspx
[2] MSDN Magazine March 2009 Security Briefs
Reveals the perspective from MS that the only attack is via cookieless Sessions (inaccurate):
http://msdn.microsoft.com/en-us/magazine/dd458793.aspx
[3] MS Employee Blog
Reveals assumption that cookie-less session is where the problems is (inaccurate):
http://blogs.msdn.com/paraga/archive/2005/12/10/502345.aspx
[4] How and Why SessionID's are reused in ASP.NET (.NET 1.1)
http://support.microsoft.com/kb/899918
[5] JoelOnSoftware Forum Discussion on Session Fixation:
http://discuss.joelonsoftware.com/default.asp?dotnet.12.484800.5

18 Comments

Posted June 24, 2009 at 2:29 PM | Permalink | Reply

Dave Hull

Thanks for the posts. Good reading. Your link to part 1 is 404ing. Should be 2009/06/14 rather than 2009/06/10, I think.

Posted June 25, 2009 at 12:53 PM | Permalink | Reply

Jason Montgomery

Dave - glad you enjoyed the article. Thanks for the heads-up on the 404's. Turns out the permalink wasn't so permanent...not sure what happened there, but we've worked around it.

Posted June 25, 2009 at 6:13 PM | Permalink | Reply

Louie

Rather than issuing a new session ID on authentication I feel like what we need is an implementation of what we call session today built into ASP.NET authentication; call it secure session. Keep unsecure session as it is today for sites that don't authenticate to store harmless data during an anonymous user's visit but then build secure session into authentication. Any access to items tied to the secure session should require a (specific) valid (IsAuthenticated) Identity. Possibly for flexibility you might allow through a configuration in either web.config or per page the ability for an authenticated session to read from the unsafe session but never the other way around. I would probably lock the door between the two by default but give developers the ability to read insecure session data from an authenticated session if they really need to. Honestly if it were me I wouldn't allow access between them at all but if you don't there will be people who wine and cry about it. :)

Posted June 26, 2009 at 3:37 PM | Permalink | Reply

Richard Reddy

The sad truth from my experience is that there are much easier ways to hijack sites than session attacks.

Although it's so easy to stop, SQL Injection remains a large hole in a lot of websites. Incorrect/lazy permissions on folders and/or databases also give the hackers an easy time of it.

Thanks for your pointers though. Nice to see someone else taking security a bit more seriously :)

Rich

Posted June 26, 2009 at 7:05 PM | Permalink | Reply

Anonymous Coward

Though it does not address the decoupled nature of authentication and session management, best practice is to have your forms authentication login page clear out the session id cookie when it is being rendered, Then, the next (login) request without the cookie will cause the framework to generate a new sessionid that the attacker does not know.

Posted June 27, 2009 at 1:27 PM | Permalink | Reply

Jason Montgomery

Louie - thanks for the comment. That's certainly an approach that could work - and tying access to secured session to IsAuthenticated is definitely a good idea!

Posted June 27, 2009 at 1:33 PM | Permalink | Reply

Jason Montgomery

Richard, True indeed - SQL Injection is still one of the hottest issues. The priority most certainly should be to fix SQL Injection and XSS issues first - they have the potential to cause much more immediate damage to all the sites' users.

Posted June 29, 2009 at 10:18 PM | Permalink | Reply

sacha

You can enforce the SSL cookie on the session by forcing it at the http cookie configuration.



will set the secure attribute on the ASP.NET_SessionId cookie.

Posted July 01, 2009 at 2:12 AM | Permalink | Reply

Jason Montgomery

sacha - I always assumed it was there, but when you go read the docs or actually try and add the requireSSL attribute to the sessionState element in the web.config, you realize that it's not there. RequireSSL is on the Forms Auth cookie, not the session cookie:
sessionState Element docs @MSDN:
http://msdn.microsoft.com/en-us/library/h6bb9cz9.aspx
vs. the forms element:
http://msdn.microsoft.com/en-us/library/1d3t3c61.aspx

Posted July 01, 2009 at 5:45 PM | Permalink | Reply

Me

What about the httpCookies requireSSL attribute?

Posted July 02, 2009 at 4:52 PM | Permalink | Reply

Jason Montgomery

&gt; What about the httpCookies requireSSL attribute?

The MSDN documentation seems to indicate this would help add security to any cookie set by ASP.NET. However, it does not affect the Session Cookie at all.

I just setup a quick test using Fiddler and verified that the session cookie does in fact get set even with &lt;httpCookies requireSSL="true" /&gt; and the connection is NOT SSL/TLS. This means &lt;httpCookies requireSSL="true" /&gt; has no affect on Session Cookies...the only way to set requireSSL on the session cookie, is to do it programatically.

Posted July 02, 2009 at 6:00 PM | Permalink | Reply

Jason Montgomery

Clarification -&gt; requireSSL doesn't enforce SSL when setting the cookie from what I can tell. It only affects client behavior (per RFC?). So the inital set will happen in the clear and the client then will only submit the cookie from then on over SSL. Need to verify.

Posted July 08, 2009 at 2:54 PM | Permalink | Reply

Jason Montgomery

Clarification on requireSSL in the &lt;httpCookies&gt; node of the web.config:

Forms authentication checks on the Server side to make sure the cookie is only retrieved or pushed to the browser via SSL/TLS. The browser also will obey the requierSSL. So in Forms Authentication, if you turn requireSSL on, it will throw an exception if the cookie is transmitted in the clear (without SSL/TLS) in either direction.

Session, on the other hand, does add the proper notation to the cookie to require SSL, however, ASP.NET does not check to make sure it's enforced on the server side. So it's possible to send the cookie to the client in the clear, then it's up to the client (browser) to provide the cookie securely.

Posted July 10, 2009 at 6:10 AM | Permalink | Reply

sacha

The way I see it, regardless if ASP.NET throws an exception if the auth cookie is sent over non SSL the cookie was still sent in the clear from the browser to the server. The only benefit you make a mistake deploying the application transmit the cookie over HTTP.

I do agree that the sessionState config section should have the same requireSSL and httpOnly attributes that the form authentication section has. Has the ASP.NET pushed back on this request?

Posted July 11, 2009 at 8:36 PM | Permalink | Reply

Jason Montgomery

sacha, I completely agree - exception or not, the cookie was transmitted in the clear. The exception just provides an alert mechanism when things aren't configured correctly.

The push back has been against regenerating session ID's on login....i'm not quite sure where the best place would be to make requests to the ASP.NET team about these sorts of issues. thoughts?

Posted October 03, 2009 at 5:21 AM | Permalink | Reply

ds r4

Thanx for the information. You have written that SSL can be created through program. I would appreciate if you could provide a way to do it through C#. Please provide more information over it. provide links to related topics if possible.

Posted March 24, 2010 at 12:05 AM | Permalink | Reply

r4 card

My one and only concern is that with every hole plugged by microsoft, several others are revealed... or so seems the trend. I suppose this is the case with almost anything, and power to the support staff that cover and fix these bugs and holes... but it can be rather frustrating as an end user.

Posted May 17, 2010 at 7:46 PM | Permalink | Reply

Michael

Hi Jason - hope you are still monitoring this blog :) Do you have any suggestions about implementing this type of binding (session to auth) when doing Windows Integrated Auth? I am not sure of the issues of adding something to the negotiate blob (or even if you can), and then - assuming it is possible to add to the negotiate blob - is it persisted in a way that the comparison between it and session can be done on subsequent requests? Any input is appreciated...

Post a Comment






Captcha

* Indicates a required field.