Session Attacks and PHP – Part 2

Yes, I will talk in this article about why it is not good to leave your session files in /tmp.  But first, allow me to follow Jason’s lead and talk about the session attacks he discussed in Part 2 of his ASP.NET article.  I will keep it short :)

Session fixation isn’t really that much of a problem as long as you stick with a few simple principles.  Remember we called this blog “App Sec Streetfighter“? It’s about simple and reproducible techniques that work while under attack.  So lets keep it simple:

  1. Use only cookies to transport the session token.  This considerably raises the bar on session fixation.  The attacker now has to set a cookie which isn’t easy at all.
  2. Change the session ID whenever the users state changes (logged in vs. logged out).
  3. Change the session ID every so often. (every X pageviews, every X minutes).

In order to change the session id, PHP offers a simple comand, session_regenerate_id, just add it to your header and you will get a new session ID on every page.  If that works for you: great!.   If it causes performance issues, then add some logic to limit the life time of sessions or add the session_regenerate_id whenever the user logs in and out.

One important caveat for session_regenerate_id:  It uses one parameter.  Set it to “true.”  The default is “false,” which will leave the old session intact.

Now to the part everybody appears to be waiting for: Why not /tmp ?

/tmp is a convenient location for session data.  Every Unix system I have seen has a /tmp directory that is globally readable and writable.  But this is just the problem for session data.  The file name itself gives away the session ID.  A listing of all session files will give an attacker a list of all valid sessions. In most dedicated web server scenarios, the risk of leaking /tmp file names is low.  But the defense is simple enough to “just do it” ™:

  • Create a directory which will only hold session data (let’s call it /tmp/phpsessions).
  • This directory should NOT be owned by the apache user, but by root and the apache user’s group.
  • Set permissions to 770.  Sadly, 760 is not possible.  Theoretically, it should work.  PHP (the web server) doesn’t really need to be able to get a list of valid sessions.  But sessions will fail if you set the permissions to 760.

I typically prefer to keep my sessions in a database, less for security reasons but more for scalability.  Memcached sessions is an other great way to get sessions to scale.

Related Articles:

Session Attacks and PHP – Part 1

Session Attacks and ASP.NET – Part 1

Session Attacks and ASP.NET – Part 2

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 Option Session Cookie Forms 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

Session Attacks and PHP

This blog is of course inspired by Jason’s ASP .Net blog. I figured as the PHP guy in the group, I may as well cover what he did for .Net from the PHP side.

PHP’s default session mechanism is rather simple and effective. The php.ini file configures how sessions work. Many of the parameters can be overridden within your PHP code, or .htaccess files can be used to create more fine grained configurations for particular directories. The session module is part of PHP by default, but can be disabled at compile time. By default, the session data is saved in files. The directory the session data is stored in is again configured in php.ini and defaults to /tmp (not the best choice, but more about that in a later blog).

Much of the session module can be adjusted, or custom code can be used to store session data in a database.

Like Jason noted for .Net, sessions and authentication are two different things in PHP as well. It is up to the developer to use sessions to store the user’s identifier.

Let’s follow Jason’s outline, and talk about session fixation first!

Session Fixation

PHP provides a number of defenses to prevent session fixation. First of all, the lifetime of a session can be limited in php.ini, or by simply using runtime configuration directives. The one “gotcha” here is that some developers mistake the cookie lifetime for the session lifetime. The session lifetime is the part that counts. It is adjusted via gc_maxlifetime parameters. The “gc” (Garbage Collection) parameters are a bit hard to grasp for someone new to PHP. First of all, it is important to understand that nothing happens in PHP unless a page is rendered. Session data will survive indefinetly if the server is idle. Whenever a page is displayed and a session is initiated, the garbage collection functions run and clean up old session data. There are a total of three parameters that determine how this is done:

gc_probability and gc_divisor: How likely is it that the garbage collection is performed. The probability is calculated as gc_probability/gc_divisor. The default is 1/100, which may be a bit a lot probablility if you only have 100 page views per hour. But if you have 100 page views per second, this is perfectly fine.

gc_maxlifetime: This parameter defaults to 1440 seconds (15 minutes). After 15 minutes of inactivity, the session is considered for garbage collection.

So in short: Using default parameters, the session is deleted within 100 page views after the 15 minute time out expired, assuming that each page view initiates a session.

What does this mean for session fixation and reusing session data: The time window is about 15 minutes by default, which is appropriate for most applications.

PHP does allow for a “referrer check”. Sessions will only be considered if the referrer contains the string defined using the “referer_check” configuration parameter. By default, this parameter is empty. This is a very powerful way to block many session fixation attacks.

It is also rather simple to change the session ID in PHP. session_regenerate_id will create the new session and move the data. Take care to set the optional parameter to “true”. Otherwise, the old session will not be deleted. For the paranoid, it is as easy as adding “session_regenerate_id(true)” to your header file. (and wait for entropy starvation to set in 😉 ).

Now what about the attacker obtaining a valid session id? PHP allows for sessions to be delivered via the URL, or cookies. URL based sessions are disabled by default via the “use_only_cookies” parameter. The cookie itself is configured via php.ini.

Cookies can simply be configured as http_only and secure via php.ini. No need for extra code on this one.

Another item not discussed (yet?) by Jason is the session ID generation. PHP’s session ID generation is reasonably secure by default. It is possible to define the source of the entropy used to create sessions (/dev/random or /dev/urandom), how many bytes of entropy are used and which hash function is used. Plenty of ways to mix it up!

There is a lot more to talk about when it comes to PHP sessions. Let’s see what Jason is up to next! Also note that the facts above are valid for later versions of PHP (5 and later). Maybe I should also write about suhosin one of these days, an excelent PHP hardening module.

Session Attacks and ASP.NET – Part 1

I’ve spent some time recently looking for updated information regarding session attacks as they apply to ASP.NET and am still not completely satisfied with how Microsoft has decided to implement session management  in ASP.NET 2.0+ (haven’t looked at 4.0 beta yet).

Before illustrating how a specific attack works with some specific countermeasures for ASP.NET (in Part 2), it’s important to understand the Session and Authentication architectures in ASP.NET.

ASP.NET Session Architecture

Session state is setup and maintained through an HTTP Module. If the ASP.NET web.config file is setup to enable session stae, the this HTTP Module kicks into gear and the first time the web application uses the session object and the user doesn’t already have a session, the ASP.NET Session module will drop a cookie on the client or do some URL rewriting to put the Session ID in the URL. All authentication and authorization mechanisms in ASP.NET are also handled through HTTP Modules (Windows, Forms, Passport). The figure below illustrates the ASP.NET HTTP pipeline functions – a request is processed by every installed module and finally processed by a handler.

httpmodule

ASP.NET HTTP Pipeline – HTTP Modules and Handlers

What’s interesting about this architecture is that the session management and the authentication modules are completely decoupled and have no awareness of each other. This allows Sessions to function with or without any type of authentication – functionally, this can be useful. However, from a security perspective (depending on what you’re trying to accomplish) this can be somewhat of a problem.

So, for example, consider next Forms Authentication. If enabled,it uses a completely different cookie than the session cookie (or different URL parameters if using cookieless). Likewise, with Windows Authentication (integrated), Client Certificates, or Basic Authentication – even though there is no need for the second cookie, it still is decoupled from the authentication mechanism and will function completely independent of each other.

So before moving on, the take-away point about ASP.NET is this – ASP.NET Session is decoupled from any type of authentication. They are completely unaware of each other.

Next let’s look at a specific session attack…

Session Fixation

Session Fixation is a specific attack against the session that allows an attacker to gain access to a victim’s session. The attack starts with the attacker visiting the targeted web site and establishing a valid session – a session is normally established in one of two ways – when the application delivers a cookie containing the Session ID or when a user is given a URL containing the Session ID (normally for cookieless). In this step, the attacker has fixed, or locked in, a known good session.

The attacker, having fixated on this session, will then entice/trick the victim into using this Session ID. At this point the attacker and victim share the same Session ID. Now anytime the information stored in this fixated session is used to either make decisions for the victim or display information only the victim should see – these can be potentially used and/or viewed by the attacker.

This does imply that the victim must do something to affect session before the attacker can take advantage of them. For example, if a flag is stored in session that is used to indicates if a user is authenticated as well as the database key used to extract information for that user – then the attacker will wait for the victim to authenticate and then visit portions of the site they wouldn’t normally be allowed to visit, seeing anything that the victim sees – as long as they have the same authorization level, since the decisions to allow access and view user information were controlled by information stored in session.

See http://www.acrossecurity.com/papers/session_fixation.pdf for a nice writeup on Session Fixation.

The Countermeasures to session fixation are as follows (as described in the paper above):

  1. Prevent Logon to chosen sessions
  2. Prevent Attackers from obtaining valid session ID (if possible)
  3. Restricting Session ID usage (prevention techniques that also apply for stolen/hijacked session ID’s as well as session fixation)

Does ASP.NET Pass?

Does ASP.NET OUT OF THE BOX get a passing grade for protecting Session, considering the three countermeasures above? I’ll address each countermeasure and how ASP.NET stacks up below.

Prevent Logon to chosen sessions:

Some attempt to use the regenerateExpiredSessionId property of the <sessionState> element in web.config in hopes it will help.

The MDSN documentation states:

regenerateExpiredSessionId – Specifies whether the session ID will be reissued when an expired session ID is specified by the client. By default, session IDs are reissued only for the cookieless mode when regenerateExpiredSessionId is enabled. For more information, see IsCookieless. ”

So this is only for EXPIRED (or non-existent) sessions, and old cookie expired Session ID’s will be thrown out.  So if the attacker retrieves a good session from the ASP.NET web application, and sends it to the victim – well, it’s not expired yet (unless the victim doesn’t fall for the attack in the allotted session timeout). This is a good thing, however, Session Fixation already requires an active session, not an expired one…so this particular attribute will not help.

Prevent Attackers from obtaining valid session ID (if possible):

SSL/TLS cannot be enforced in the web.config for Session ID delivery, this is only an option for the Forms Authentication cookie.

Restricting Session ID usage:

The ability to tie a session the authentication is not automatic – it requires custom code. Considering session management and authentication modules are out-of-the-box, ASP.NET could potentially couple them.

Comparing ASP.NET session management implementation to the recommended countermeasures for session fixation doesn’t look so good…ASP.NET however, does mark the cookie HTTPOnly, which does helps prevent XSS attacks against the session on *most* of the latest browser versions – this certainly reduces risk, but it is not foolproof.

There have been bug submissions to MS asking for a bug fix for their session management implementation [1] and others asking that Microsoft fix the way ASP.NET handles sessions [2] to address issues described in this two part post. The recommendation to fix these issues aren’t necessarily unreasonable; however, the way ASP.NET session management is implemented, ‘fixing’ the issues might not be so straightforward and might even be simply a side-effect of how session management was implemented and not necessarily just an oversight or vulnerability.  The down-side of the chosen implementation is that developers need to be educated on this specific nuance of ASP.NET session management and know when and how to protect their web applications accordingly.

Next, Part 2 will explore specific attack vectors, countermeasures and some thoughts that will hopefully spur on some additional discussion.

References

[1] MS Connect Denied Bug Submission on Session Fixation
https://connect.microsoft.com/feedback/viewfeedback.aspx?FeedbackID=143361&wa=wsignin1.0&siteid=210

[2] Preventing Session Fixation through Session ID Regeneration in Java and ASP.NET
http://keepitlocked.net/archive/2007/12/27/preventing-session-fixation-through-session-id-regeneration-in-java-and-asp-net.aspx