The usage of sessions is the php developer’s most common use since we constantly need to transact data from step to step. An average programmer would say that using sessions is far more secure than letís say cookies since the session data is server side data, thing that is partially correct.
The fact that the attacker can’t have a clear look at what and where you store comes to your advantage but a more dedicated attacker can go a bit further than this presumption.
A must have for the attacker in a session hijack is the Session Identifier so he can impersonate the attack. Let’s presume for example that you have your website hosted on a shared hosting on which PHP is installed as an Apache module, thing that makes session files belong to the web user, in other words: accessible.
Some more elaborated attacks could be categorized as follows:
Prediction refers to guessing a session identifier, approach that can be rather irrelevant since the native php session identifier is far too random to be analyzed at a glance so the next one can be predicted, meaning the attacker’s focus is not usually here.
Capture on the other hand is the session hijacker’s best practice since it is rather versatile. Having the fact that the session id is being propagated by numerous resorts such as HTTP Headers, Cookies, E-mail Headers and so on, accessing it couldn’t be too hard for the attacker could it?
The worst of this is that each of these ways of session id propagation can be a door for attackers so which one is the best for us? Well, on a small scale, cookies are a bit less exposed than the $GET data for example, so if you have cookies enabled you can work with that as browsers are generally speaking secure – there were just a few miss-behaviors in Internet Explorer.
Fixation is not a very complex method but if you rely your session security on a mere sessionstart() you are in trouble. Since you only work with the default Session Identifier, reproducing a common user’s HTTP Header isn’t that difficult, so how do we work with this?
Let’s base an example on a simple HTTP Header such as:
5 6 7 8 9
GET / HTTP/1.1 Host: example.org User-Agent: Mozilla/5.0 Accept: text/xml, image/png, image/jpeg, image/gif, */* Cookie: PHPSESSID=1234
So we have the HTTP Header in its simplest form yet we have some data to work with. Taking for example that seconds after you get this another request from a different user agent.
As an educated developer one must assume the worst case scenario: this might come from an attacker and not from a user using two browsers. A common use in this case might be re-asking for the user’s credentials, thing that would not impose any issue on the user’s behalf but would disarm the attacker at this stage.
An easy approach to this would be generating a MD5 for the User Agent but than again, MD5 strings are quite easy to recognize so why not using a more elaborated approach and binding a passkey to the algorithm?
8 9 10 11
$token = $_SERVER['HTTP_USER_AGENT']; $token .= 'ABRACADABRA'; $securetoken = md5($token);
This approach can help you prevent some of the attacks but not all of them as you can imagine.
Another best practice to preventing the evil session hijack is using the session’s sessionregenerateid() once the user logs in so if his session identifier has been ‘sniffed’ somewhere along the way the chase ends there and so the attacker would have to go all over again.
So we know now how this works, some best practices but how can we make it full proof? Unfortunately, I do not have an answer for the 100% but I have some answers that will make your application safe to most attacks.
- Do not trust users.
Common users are not security educated users so they can easily fall for CSRF attacks and as long as the user is a victim, so are you. If you have any doubt whatsoever on a user’s action do not hesitate to ask for credentials. He wouldn’t mind as long as you tell him that it is for his own protection.
- If on a shared hosting make use of sessionsavepath()
This will allow you to set a new path for your session data storage, a more secure one that the default setting up. Make sure that the folder you store the data is secured and make use of your .htaccess file to limit access there.
- Wondered why there are both $COOKIE and $SESSION?
What you must take into consideration here is that cookies have a different purpose than storing session data so why not leave that as it is? XSS Faltering is quite common so your cookies are not safe.
- Do not pass your session identifier in URLs
By now you should be aware that the session identifier is the attacker’s must have and that your main task is to keep it well hidden so why just serving it to the attacker? As you can imagine this goes for $_GET as well.
- If skeptical on the entire HTTP Headers issue, use a security token at all time
If nothing in the world could determine you to filter every incoming message than the least you can do is to use a security token at all time. A light example of such a token could be:
$token = md5(uniqid(rand(), true));
Keeping all these in mind should make your applications far more safer so it is definitely worth your while.