Friday, 20 January 2012

PHP session security: Part 3 - Session ID storage on the client

Introduction
This is my third post in a series about securing PHP sessions and focuses on how to securely store the session ID stored on the client.  For more information on why you have to store the session ID on the client see my post about how PHP sessions work.

Methods of client side id storage
There are three main methods of storing the session id on the client browser which are, as a cookie, in the URL as a string parameter or in a form as POST data.

Of these three passing it in the URL is the least secure for a number of reasons.  Two main ones are that the session id is visible to anyone who can see that URL.  This doesn't just mean people looking at their screen but also if the user were to copy the URL and send it to someone and anyone who has access to their browsers history.

Passing the session id in POST data is more secure as long as a secure connection is used but can be a bit more awkward as you'll have to make every server request from the client a form submission.  This isn't the most secure method though because as I'm sure you know that when a user makes a page request to the server a page is sent back and this page is stored on the users computer.  This means that the session id that's been set in the page form (generally as a hidden field) is clearly visible in that file, although it does seem unlikely to me that anyone would actually look at this file it is still possible, more so if they are on a public computer.

The most common and secure method is to set a cookie on the clients browser as it can be easily set to only send its value over a secure connection and to the correct domain (there are many other settings too).  What makes this more secure than sending it via POST submissions is that the cookie stored on the client browser should be kept restricted by the browser so not everyone can see and read them other than the user (with the correct tools) and the site that set them.

Using only cookies
I'm going to concentrate mainly on how to secure the session id stored on the client using cookies as this is the most secure and common method using the default PHP session handler.

In PHP version 4.3.0 a setting was introduced, session.use_only_cookieswhich allows you to tell PHP to only use cookies for setting the session id and also only accept session ids sent from the browser in a cookie.  One thing to note however is that up until version 5.3.0 this defaulted to 0, meaning it would set and accept session ids using any method, but since version 5.3.0 defaults to 1 meaning it only sets and accepts session ids from cookies.

There are a few ways of setting this option so cookies are the only method the session id can be sent in, one is to set it directly in the php.ini file but if you don't have access to that you can set it in your PHP script using ini_set() (i.e. ini_set('session.use_only_cookies', 1);).

Securing the cookies
Once your application is set to only set and accept session ids via cookies you'll then need to secure the cookies, which is again not to complicated and just involves changing some settings.

You'll need to make sure the cookie is only available to the correct domain (session.cookie_domain), make sure it's only sent over a secure HTTPS connection (session.cookie_secure) and secure against any hacks that involve getting the cookie values from JavaScript injections, cross-site scripting or various other methods (session.cookie_httponly).  Conveniently there is one setting that will do all of this and a couple more (session.cookie_lifetime) which is session_set_cookie_params (i.e. session_set_cookie_params(0, '/', my-domain.com, true, true);).

Something to note about using cookies is that you are relying on the browser keeping them secure but there have been exploits in browsers before which compromise this (Internet Explorer being the main one but not the only).  As this will almost always be out of your control (possible exception being if you're building an intranet site) you shouldn't ever store any sensitive information such as the usernames, passwords or personal details in a session variable.  I'd recommend encrypting or hashing and information stored in a session variable if it's possible, although I'm aware that in a lot of cases that just wouldn't be practical or even possible.

Hopefully that's been helpful, if so let me know (also if you think I missed anything or just got something plain wrong)!

Other parts in this series:
Further reading

    Thursday, 19 January 2012

    Down temporarily

    I thought I'd just let anyone who reads this know that my blog was down for a short while earlier today because I was setting it up so it uses my own sub-domain rather than the Blogger assigned one.  You may have noticed the URL to this blog is now blog.neilnand.co.uk rather than neilanand.blogspot.com.

    I had been trying to decide if I should do this or just setup a Wordpress blog on the sub-domain then transfer all the posts from here, in the end I decided to stay with Blogger as it's a very good platform (although I do really like Wordpress and use it a lot).  The main thing that convinced me to stay with Blogger was looking around at templates people have made for Blogger and being quite impressed with what you can do.

    Update on the project

    Hello,

    It's been a little while since I wrote anything about this project but I am still working on it but mainly on the documentation side for the moment while everything is fresh in my mind then I'll be back on coding it.  You may have noticed that I'm posting quite a bit here about PHP stuff that's not directly related to this project, that's because I'm intending on linking to these posts from the documentation as an explanation of how some parts of PHP work rather than putting it all in the documentation and making it incredibly long.

    I'll be putting a lot more time into the development of it soon but I'm also reading up lots on HTML5 and CSS3 to make some really cool working examples of what can be done that will be posted on this blog.

    PHP session security: Part 2 - Session storage on your server

    Introduction
    This post continues on from my previous post with an overview of all the PHP session security issues, this one will be the first in the series to start going into more specific detail about each point I made previously.

    Session storage directory
    This is the directory storing the files the session data is saved in, by default this is in the /tmp directory of your server.  The main problem with this comes on a shared server where all session data for all sites hosted on that server are stored in the /tmp directory and everyone using that server has access to it, as mentioned in my previous post the data stored in this file is serialised but is in no way encrypted or secured.

    This isn't quite as bad as it sounds because anyone who looks at this won't be able to figure out which domain on that server each session relates to but they will be able to see all the session ids and data stored within them.  Hopefully you haven't been storing sensitive data in session variables so any information they do find won't be of any use but knowing all those session ids is one of the first steps to hijacking a session, more on that in a separate post.

    This is quite an easy one to fix as there are a few ways of getting around it such as storing all session data in a database, creating your own session handler or easiest of all changing the location of where your session files are stored. I'll be covering the last of these here as this series of posts is about the default PHP session handler but you can Google around and find more information about the other two pretty easily. I'll hopefully get around to writing a post at some point about them myself though.

    To change the location of where sessions are stored you'll need to use the session_save_path() function and make sure that the directory you save to is secured so that people outside the server cannot list or open files in the directory. There are two ways of doing this that I can think of, the first would be to use directory and file permissions (here is a good summary) and the second would be to use .htaccess settings (here is a good article on it).

    I hope this has been helpful, the next post will be about storing the session id on the client.

    Other parts in this series:
    Further reading

    Thursday, 12 January 2012

    PHP session security: Part 1 - Considerations


    I thought I'd make a post about the main security considerations around PHP session security, this will be the first in a few posts about this subject; the others will go more in-depth and give you practical information.

    The first thing to remember is that PHP sessions are not secure by default as many may think.  I've listed all the ones I can think of below and will expand on them in my next post, I'll probably separate some of the points into their own posts too as I'm trying to keep these at a reasonable length.  If you can think of any that I've missed here please leave a comment.
    • Session storage location by default PHP stores its sessions in the /tmp directory of your web server which can be an issue in a shared server because everyones sessions are stored in the same place and you all have access to that directory and its files.
    • Session ID storage on the client can be insecure if passed in the URL rather than in a cookie, POST data can be fairly secure as long as the connection between the client and server is secure (same is true for using cookies) but can often be more awkward to use.
    • Session fixation which is a method of a hacker setting the users session id to something they want so they'll know what the session id is and can impersonate them.
    • Session hijacking is when a hacker finds out what the users session id is and uses it to impersonate them, different to fixation because the hacker in this case is finding out what the session id is rather than setting it themselves.
    • Using a secure connection for all sensitive data sent between the client and server, such as their login credentials and the cookie data.
    • Securing cookie data so it cannot be accessed by anyone else or by any JavaScript used by a hacker on the clients browser.
    • Making the session id non-guessable (if that's even a word), this one is fairly easy as PHP has a pretty random method of generating the ids that would be next to impossible to guess anyway (as far as I'm aware) by default, but you can write your own if you liked.
    • Not storing sensitive data in the session or the cookie held on the client, even if you do everything possible to keep it all secure you're still reliant on the client browser being secure so it doesn't just give the information out to anyone.  Unfortunately this isn't always the case, notably in internet explorer, although as far as I'm aware there isn't currently any security holes in any major up-to-date browsers but I could be wrong but even if I'm right by the time you read this things could have changed.
    Other parts in this series: