Session Security with PHP

Two popular forms of session attacks are session fixation and session hijacking. Whereas most of the other attacks described in this chapter can be prevented by filtering input and escaping output, session attacks cannot. Instead, it is necessary to plan for them and identify potential problemareas of your application.

When a user first encounters a page in your application that calls session_start(), a session is created for the user. PHP generates a random session identifier to identify the user, and then it sends a Set-Cookie header to the client. By default, the name of this cookie is PHPSESSID, but it is possible to change the cookie name in php.ini or by using the session_name() function. On subsequent visits, the client identifies the user with the cookie, and this is how the application maintains state.

It is possible, however, to set the session identifier manually through the query string, forcing the use of a particular session. This simple attack is called session fixation because the attacker fixes the session. This is most commonly achieved by creating a link to your application and appending the session identifier that the attacker wishes to give any user clicking the link.

<a href="http://example.org/index.php?PHPSESSID=1234">Click here</a>

While the user accesses your site through this session, they may provide sensitive information or even login credentials. If the user logs in while using the provided session identifier, the attacker may be able to “ride” on the same session and gain access to the user’s account. This is why session fixation is sometimes referred to as “session riding.” Since the purpose of the attack is to gain a higher level of privilege, the points at which the attack should be blocked are clear: every time a user’s access level changes, it is necessary to regenerate the session identifier. PHP makes this a simple task with session_regenerate_id().

<?php
session_start();
// If the user login is successful, regenerate the session ID
if(authenticate()){
   session_regenerate_id();
}
?>

While this will protect users from having their session fixed and offering easy access to any would-be attacker, it won’t help much against another common session attack known as session hijacking. This is a rather generic termused to describe any means by which an attacker gains a user’s valid session identifier (rather than providing one of his own).

For example, suppose that a user logs in. If the session identifier is regenerated, they have a new session ID. What if an attacker discovers this new ID and attempts to use it to gain access through that user’s session? It is then necessary to use other means to identify the user.

One way to identify the user in addition to the session identifier is to check various request headers sent by the client. One request header that is particularly helpful and does not change between requests is the User-Agent header. Since it is unlikely (at least in most legitimate cases) that a user will change from one browser to another while using the same session, this header can be used to determine a possible session hijacking attempt.

After a successful login attempt, store the User-Agent into the session:

<?php
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
?>

Then, on subsequent page loads, check to ensure that the User-Agent has not changed. If it has changed, then that is cause for concern, and the user should log in again.

<?php
if($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']){
   // Force user to log in again
   exit;
}
?>

Next Topic | Previous Topic

Post to Twitter Post to Digg Post to Facebook Post to Google Buzz Send Gmail

Leave a Comment

Your email address will not be published. Required fields are marked *