Hudzilla.org - the homepage of Paul Hudson
Contents > Security concerns > Programming secure PHP Wish List | Report Bug | About Me ]

17.1.11     Be wary of session fixation

This is NOT the latest copy of this book; click here for the latest version.

Also commonly referred to as "permissive sessions", session fixation is a cracking technique that gets around the problem of predicting session IDs. You see, by default every session in PHP gets an ID that looks something like this: psu31m28jovm95mmo19a267fg4. It's a very long, complicated alphanumeric value that is generated randomly. What's more, the methods used to generate it - unless the cracker has physical access to your system - are above prediction. Therefore, there is no way a cracker can break into others' sessions.

However, an interesting feature of PHP is that it lets users tell it what session ID they are using. If PHP cannot find session data for that ID, it just creates session data afresh for it. Take a look at this link: <A HREF="http://www.yoursite.com?PHPSESSID=abc123">Click here!</A>

What that does is let people click through to a given site, passing in a specific PHPSESSID. PHP will then use this for the session ID for that user, and, what's more, the person who created that link doesn't have to bother trying to predict what the session ID is, because they already know: abc123.

This is the nature of session fixation: users being handed non-random session IDs that can be hijacked by others. Once a cracker knows a user's session ID, they can go in and view potentially private data: passwords, credit card information, etc. This is - as you can imagine - a bad thing.

How to solve session fixation? There are several ways:

  • When a real session is created, set a value in there such as IS_SAFE.

  • Change session IDs on privilege elevation

  • Store user-specific data in sessions that can be checked

The first option sounds like it might work, but ends up being no better. Yes, it does stop hackers plucking session IDs such as abc123 out of thin air, but it doesn't stop them going to your site, getting a real session ID, and using that . Essentially they create the session themselves, and use the valid session ID given back to them by your site to ensnare others.

The second option requires a little explanation. "Privilege elevation" is where users change from being an Internet visitor indistinguishable from anyone else to being someone with some sort of rights. The most common example of this is when people log-in to your website: they now have privileges, and so should have their session changed. Changing session ID isn't hard; in fact, it's just one call to session_regenerate_id(). Note that session_regenerate_id() takes no parameters and returns no meaningful value, it simply changes the session ID to a new, random one. In order to do this, it must send a cookie back to the client: this means you must use the function before any HTML content is sent, or enable output buffering.

Regenerating the session ID on privilege elevation works just fine: PHP automatically copies all the data from the old session to the new session, and leaves the old one intact too. This means that the legitimate, privilege-elevated user, gets to access all their data safely, while the cracker is looking at the stale file. Changing the session ID with session_regenerate_id() is very fast; I don't see any reason why you couldn't call it every page if you were really paranoid.

Moving on, storing user-specific data in the sessions so that you can see quite easily whether the current session user is the same as the user that created it is actually quite easy to do. It turns out the only data you can be sure to get from clients is a user agent (the browser name), but this is actually enough. Sure, 90%+ of people use Internet Explorer, but there are quite a few major versions of IE out there and many, many sub-versions. The IE installed on my Windows box gives the user agent "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)", and yours probably gives something very different. So, we can store this in our session as a known identifier of our user. If someone comes along with the same session ID, we can check their user agent against our stored value, and take immediate action if they differ.

Author's Note: It is not advised to use the IP address of visitors as their unique identifier, because proxying ISPs such as AOL group IPs together: one IP address could be used for a million people, whereas one person might appear to have several IP addresses as they go through different proxies.

In action, there's no harm storing user-specific data and using session regeneration: the speed hit is very minimal, and you get a healthy boost in security.





<< 17.1.10 Pre-initialise important variables to safe values   17.2 Hosting PHP >>
Table of Contents
Want to see this stuff in print? PHP in a Nutshell takes the core topics covered here, adds in thousands of edits from the editorial team and myself, and combines them to make an unbeatable reference for PHP programmers at all levels.



My latest book has hundreds more tips on how to use PHP, Apache, and MySQL, plus Perl, Python, shell scripts, performance tuning, and more!



Top-right shadow
 
Bottom-left shadow Bottom shadow

Comments from other readers
Kileak - 06 Sep 2008

@ shajan

Use session_regenerate_id(true), this will remove the original session, read more about it here:

http://php.net/manual/en/function.session-regenerate-id.php

Cheers, Kileak.

shajan4@yahoo.com - 06 Sep 2008

I used session_regenerate_id() for session fixing. But it keeps on creating session files on the server whenever one access that file. The previous files are active also. Means if one get first session id and pass it thru the header it can be hacked.
Can anyone help me?
thanks,
shajan

qazimarus@yahoo.com.sg - 06 Sep 2008

Hmmmm... it's just crossed on my mind...
Seems like we also need validate the UA before save it in database. WhY ?? If there is a browser which can be cuzstomizabled on its identity (I use Snoopy.class.php and other simulated browsers).
For example users can set the UA value, then use it to do SQL Injection



Add comment
Please note that by posting a comment here you are committing it to the public domain. This is important so that others can make use of your code themselves, and also so that I can incorporate helpful notes directly into the main text. Comments are limited to 2000 characters in length.

If you are reporting an error in the content, please tell me directly.

Your name/email address:
Your comment:
 
Now, in order to verify that you're a real person, please answer this simple question: what is zero plus two?
The answer is:
(please write in
numbers, eg 19)


Top-right shadow
 
Bottom-left shadow Bottom shadow