Understanding the Life of a Session
One of the most vast misconceptions in the PHP world is how sessions really do work. I'm fairly confident most of us know how to start sessions, terminate sessions, regenerate session IDs and easily pass data from 1 page to another. But do you really know how they work inside out?
A common question I get asked is:
Where are Sessions stored?
This is the question that will quash all those questions on are sessions safe. Anything can be unsafe in PHP if the programming is not up to par. Generally speaking, however, sessions are 1 section of the PHP language that is difficult to mess up.
Core of a Session File
Remember the times when you used to crack open the cereal boxes to retrieve the free plastic toy from inside? Well, sessions are not quite as exciting as that. In fact, sessions are pretty uneventful on the inside. Let's take the following PHP code and execute it normally:
That's all there really is to a session file. Remember that the session file is stored server-side so there is absolutely no need to transfer any information you do not publish in the HTML over the insecure medium we like to call the Internet.
Point of the Session ID
Now, this is where our delivery method comes in. Cookies are the most frequently used due to the extra security they add (not much, but just enough to be the favoured method). The other possible methods are GET (which is sometimes used) and POST (which I've never seen used but essentially it could be used with a little difficulty). Unlike GET and POST which can be used in such attacks as CSRF (see our article on CSRF for further information) and passed around to potential victims with far too much ease, cookies are just that little more difficult to install on a victim's computer.
I could quite easily send a link to you and have you either hijack a session on my behalf, or the most common reason would be to fixate your session ID (see the following post for more information about session fixation). Although, if I am unable to pass you the session ID easily then it's going to be more difficult for me to breach the target website's security and assume your identity. Consider the following link and how easily it can be passed around:
So where has this all been leading? Well, there is an important setting that is set to 1 by default (and should always be set to 1 unless you wish to also support users who do not have cookies enabled - which is not recommended) that prevents the session IDs from being transferred via a GET and to use only cookies - the safest delivery method. That setting is:
Upon loading the website where my session ID was created, the cookie is sent to the website and parsed by PHP. The session ID is correctly linked to the session file stored server-side and is then unserialized and placed into the pre-populated PHP array, $_SESSION. Once I have issued the session_start() command to begin my session I am able to access all the information - even crucial and highly sensitive information, from the $_SESSION array.
Note: Although you may store highly insensitive information in sessions, be aware that displaying it on your website will mean that crucial information is being sent over the pipes of the Internet. Without using SSL this would be a very insecure method of delivery which would be crying out to be intercepted by Harry the hacker.
Basic Session Security Example
Assume that our banking system has absolutely no extra security implemented. This is exceedingly unlikely so don't be frightened!. You have logged in and been issued a cookie containing your session ID, our banking system also erroneously accepts the GET method of delivery though to ensure everybody can use their system. Remember, all Harry the hacker (not Harry the hamster) needs to assume your role is your session ID. Nothing more, in this example.
Harry decides to go down the route of session fixation and thus sends you the following crafty link:
5aff2, clicks on the link himself and is able to withdraw your entire life savings of 67 pence.
As sessions do absolutely no extra security checks on your behalf, the system simply thinks it is you because the session ID is correct. It is up to YOU to implement the extra security to prevent such instances from occurring.
Locks up your Daughters
Some mean looking guy approaches your door after trampling on all your pretty flowers without a care in the world, loudly knocks on the door and demands to see your daughter. He may well know your daughter's name but who is he? The who is he part is crucial - it's as crucial as not assuming that because someone has the correct session ID that you should let them in. Until the mean looking guy can answer some of your questions, you're not letting him see your daughter. Oh no, no!
To give a simple question of what you can ask the end user when it comes to sessions is:
Which point, 1 or 2, would you rather assume was true? Surely assuming the former and allowing a user to carry on their session seamlessly would be less likely than the latter? Assuming the latter will also save any embarrassing security hiccups. By destroying the user's session and asking them to re-login has to be the better option just in case. Any legitimate user will not mind this slight inconvenience if they know their 67 pence is safe. After all, once the security has been breached, it is difficult to return that level of trust back to its normal levels.
Nonetheless, the browser name, version, language, etc. are all sent by the end user's browser during the HTTP call. This means that this data may not even be sent at all. It is optional. As long as you know it is optional you can check for if the intended array even exists before using it. This is important because a blank string will always produce the same MD5 or SHA1 (etcetera...) hash. A null string MD5'd will always be d41d8cd98f00b204e9800998ecf8427e no matter how many times you use MD5. Whilst SHA1 will be different to the MD5 string, it will still be the same for every single time you hash the null string using SHA1.
Shared Hosts can be Little Buggers
Now that you fully understand the following:
[Session File] (Server) -> [Cookie File] (Client)
You may think your session file, because it is server side, is safe. That simply isn't the case, I'm afraid. A session file can simply be opened by anybody who has access to your file system. For instance, my sessions are stored in the following directory as plain files:
Luckily the directory can be moved elsewhere or you can even use a table inside a database to store all your session data. The latter is best saved for another article to keep this 1 short and sweet (ok, shortish and sweetish). The following setting can be changed to alter the destination of our session files:
The next time somebody asks you if sessions are really the way to go, that if storing crucial information in session data is insecure, chuckle in their face and refer them to TalkPHP!
Great article Wildhoney, it should help alot of people grasp the fundamentals of PHP sessions.
Thanks a lot. I do really get asked the question a lot so it made sense to turn it into an informative article. Any further elaboration on my article would be appreciated!
Hi Wildhoney, I must praise you for writing such a brilliant tutorial, this helped me understand sessions alot more. This is the only detailed, understandable sessions tutorial I have read so far. There is only one thing which confuses me, and its about hijacking sessions.
This is how I setup a website im making:
Upon logging in, a session starts and defines $_SESSION['users_id'] = $users_id
($users_id being set after all the SQL queries etc)
This is then passed around the pages to confirm the current user.
Now, upon checking my local cookies - I do not see any text stating "users_id" therefore it would be hard to find the id in the text.
Due to being hard to find could it help with security?
I have the feeling it really doesn't help with security - and now have thought up the more standard sessions method which is:
Create a table in a database of choice,
I'm sure you can see where i'm going with this.
The user now logs in, and the session id is stored in the table, then to check which user is logged in, I check the $_SESSION['session_id'] against the database and get the users_id to gather the correct data from the users table.
Is it just as easy for them to hijack the session id as it is to hijack the users id? I know this would avoid them hijacking someone elses session WITHOUT getting the session id from them, but if someone passed their session ID onto them - then it defeats the point of adding more functionality.
To be honest, the whole security criteria of PHP worries me as I don't have mass amounts of knowledge to do with sessions and cookies.
What could you suggest?
Once again - thanks for the brilliant tutorial,
Thank you, Adam! I'm glad you enjoyed the article. I'm tired of seeing all these clichés people throw out concerning PHP. We've heard it all before. It just cries out for some originality.
As for your question, I'd definitely go down the storing the session ID route. That way if anybody is wishing to hijack a session, they'd have to either fixate the ID (which we can protect against), or be lucky enough to get a ~32-bit hexadecimal string.
The dilemma of users passing a link, unintentionally or otherwise, to another user, can be prevented by only allowing the session to come from a cookie. This way, the only real way that a session can be hijacked in that sense, is by transferring a cookie to a user and telling them to put it in their cookie folder - and who's silly enough to do that? Sound too much like hard-work to me!
Of course, if you go down the route of preventing the session ID coming from a URL parameter (
Other security methods can include things like:
Ip checking - Ensuring the same IP address is used throughout
Brilliant, thanks for the speedy response, I will definately be using my stronger session ID from now on, thanks for the update!
Alos Bluesaga, that info has helped me alot, I will now check the session id against the original IP, this will definately avoid any well known ways of session hijacking. Brilliant - I can now make my decision, now to implement it.
Thanks for the help guys!
|All times are GMT. The time now is 09:50 PM.|
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0