Saturday, 11 February 2012

PHP session security: Part 5 - Session fixation

Edit 14/01/2013
I've updated the "Secure your server against session fixation," section of this post as I felt I'd missed parts out and it wasn't complete enough.

This is another post in my securing PHP session series, this time I'll be covering session fixation.  This is a method used by attackers to set the session id of a legitimate user of your site to what they want it to be so they can impersonate your users.

Brief recap on how PHP sessions work
As explained in a previous post about how PHP session work when a session is made an ID is generated by the server and a file created with the generated id as the name on the server which stores all the session data (such as session variables).  This ID is also set as a cookie value (although there are other methods) with the default name of PHPSESSID (this can be changed) and every time the client makes a request to the server it sends the cookie too.  When the server detects this cookie it checks the session files it has already created and if there is a matching one it'll use the session data from that, if there isn't one it will create a cookie with that ID passed to it and not generate a new ID.

This is all default and most common behaviour for PHP sessions, there are many ways of changing this but this series of articles is concentrating on the default behaviour and how to make it more secure.  I'm also only covering securing PHP session based on using cookies for storage on the client browser because it is the most common and secure method currently in use.

How does session fixation fit into this?
Session fixation is when a hacker some how gains access to some part of the process and manually sets the session ID to one they've generated.  This could be by altering the session ID generation on your server or changing ID stored in the users cookies or a verity of other methods.  How this attack will be performed will depend on your set up and the what they are trying to attack (website, web app etc) and how it works but I'll go into what I consider to be the most common use of PHP session which is a website.  In this scenario it's unlikely your server will have anything altered and far more likely that the cookie on the client is changed or the cookie gets changed while being sent from the client to the server, or vice versa.  This isn't just true for websites but many web applications too.

Now that the hacker has successfully changed the users session ID to one they know, they can set the cookie in their own browser to the one they've changed the clients to and log into your website / web service passing that cookie to your server and in doing so your server will think the hacker is the legitimate user.

This is different to session hijacking (I'll be writing my next post about this) in that session fixation is where the hacker sets the session id to one they'd like but hijacking is when a hacker obtains the session id that's already been set.  The end result is the same, the hacker can impersonate your users but the general thinking / methods behind the attacks are different.

How can this happen?
I can't truly answer this question as I'm no hacker but I can give a very simple example of what can be done, I am sure that there are many other methods of session fixation that I cannot think of, it'd be worth doing a Google search for "How to perform a session fixation attack."

The basic example I can think of is if your server will accept session IDs to be set using any method and not just secure cookies which are set by your server then it's possible that a hacker could send the user to your site via a normal link which also sets the session ID.  When the user clicks the link and is taken to your site, your server will pick up the session ID in the URL and create a session file storing all the session data on the server with the ID set in the link.  This might not be the clearest explanation of what I mean but I can't think of a better way to describe it, I've put an example of the link I've just described below to hopefully make this clearer.

<a href="">Click me!</a>

I hope this helps you understand a little about how these attack take place but do search around for more information as I'm no hacker but I know these vulnerabilities exist.

Secure your server against session fixation
There are probably many methods of securing your server against session fixation and in every application you make it's worth looking into as it'll vary but I suspect for most websites, my upcoming secure PHP login project included, regenerating the session ID should be enough.

Regenerating the session ID is basically exactly what it says, when the user access your site the ID that's passed from their browser to your server is then changed (regenerated) and a new one made which is then sent back to the client browser and stored as a cookie.  This means that even if a hacker changed the session ID cookie on the client browser soon as it's passed to the server it gets changed and the hacker no longer knows what the session ID is.  If there isn't a session ID passed to the server then a new one will have to be generated anyway and as long as the connection is secure it should still prevent session fixation attacks.

I would point out though that this isn't a foul proof method as the client computer could be compromised and as soon as a new cookie is set the attacker gets informed of it but there isn't a huge amount you can do about it because it comes down to the browser manufactures and users themselves to keep their end secure.

There are a couple of methods to try and combat this though, one is the slightly unreliable method which is to hold information about the users machine such as their user-agent and their IP address (others can be included too) and detect changes to them and every time a session ID is used and see if they are the same as previous. If they're not the same then forcing them to re-enter their password should help prevent this, the problem with this of course is that IP address change, are shared between multiple computers and can be spoofed and the browser in use can change which could cause users to have to enter their password in a lot.

Another, probably more useful method is to only allow the user access to parts of the site which don't have any sensitive data on it and making them enter in their password in again every time they try to go to part of the site with more sensitive information in. This in my opinion is the best method in general to be using.

Of course you can always force the user to enter their password every time they enter the website but if you want a 'remember me' kind of link this method wouldn't allow it.

It does depend on how secure you need to make your site / application on what you'd need to do and these are just some options, you'll need to evaluate what will be best for your situation & users each time.

A quite simple method of regenerating the session ID is to use the built in PHP function for this task called session_regenerate_id() which creates a new session ID and keeps all the data from the previous session.  Make sure you set it's parameter to true (it defaults to false) as this will delete the old session file on your server which will stop the old session id from being used again.  I've put an example of the code below:


How often to regenerate the session ID?
This is a bit of a tough question and it does depend on what you're application is using the session data for, but lets say you're using it for a login system (I pick this as I'm currently building one myself).  The consensus seems to be it should regenerated every time the user enters their login details.  They should be entering their login details when they login and every time they try to access more sensitive areas of the site such as a page allowing them to change their password or other personal / sensitive details.

Personally in my secure PHP login project I have been trying to decide between the above or if it should be regenerated on every page load.  I'm not sure but I think regenerating it on every page load would be quite intensive if there were a lot of users (not sure if that's accurate or not) I may add an option in that will allow either method to be used.  I might even have it capable of using both and deciding which to use depending on if a secure connection is in use.  What do you guys think?  Leave a comment with you opinions.

What else can you do?
It's worth doing more research into this as I said before it will depend on your site / application on the best method of securing against this kind of attack, I'm just giving my opinions on the most secure method for what I think are the most common scenarios. Just being aware of this vulnerability while building the site though is a large step towards preventing it as you'll actually start giving it some thought (hopefully).

The only other things I can think of is to make sure your server is set up securely, to only accept session IDs from the client in a secure cookie and to always use a secure connection between the client and server.

Other parts in this series:
Further reading

No comments:

Post a Comment