Chris Shiflett: Security Corner: Session Fixation
Author, Consultant, Programmer, Speaker, Trainer


18 Oct 2004 - Training
Securing PHP Code

with Zend Online Training

26 Oct 2004 - Talk
Testing PHP with Perl: Two Great Tastes that Taste Great Together

at NYPHP (New York, NY)

14 Nov 2004 - Talk
PHP Security

at ApacheCon (Las Vegas, NV)

16 Nov 2004 - Talk
Testing PHP with Perl: Two Great Tastes that Taste Great Together

at ApacheCon (Las Vegas, NV)


23 Sep 2004 - Talk
PHP Session Security

at php|works (Toronto, Canada)

20 Sep 2004 - Column
Security Corner: Secure Design

in php|architect

26 Aug 2004 - Column
Security Corner: Session Hijacking

in php|architect

30 Jul 2004 - Talk
Securing PHP Sessions

at O'Reilly Open Source Convention (Portland, OR)

29 Jul 2004 - Talk
Foiling Cross-Site Attacks

at O'Reilly Open Source Convention (Portland, OR)

26 Jul 2004 - Talk
PHP Security

at O'Reilly Open Source Convention (Portland, OR)


Aaron Wormus

Adam Trachtenberg

Andrei Zmievski

Ben Ramsey

Casey West

David Sklar

Derick Rethans

Geoff Young

George Schlossnagle

Harry Fuecks

Ilia Alshanetsky

James Duncan

Jeremy Zawodny

Jim Winstead

John Coggeshall

Joyce Park

Marco Tabini

Michael Radwin

Nathan Torkington

Paul Reinheimer

Rich Bowen

Sterling Hughes

Steve Mallet

Theo Schlossnagle

Wez Furlong

Zak Greant

Security Corner: Session Fixation

by Chris Shiflett
php|architect
16 Feb 2004

Security Corner: Session Fixation

Security is gaining more and more attention among PHP professionals. As PHP continues to be a key component of the Web's future, malicious attackers will begin to target weaknesses in PHP applications more frequently, and developers need to be ready.

I am very pleased to introduce Security Corner, a new monthly column that is focused completely on PHP security. Each month, I will discuss an important topic in great detail that can help you improve the security of your PHP applications and defend against various types of attacks. These topics will not be vague, general overviews, so if you are looking for an introduction to PHP application security, you will be better served by other sources of information such as the PHP manual's chapter on security (http://www.php.net/manual/security.index.php).

This month's topic is session fixation, a method of obtaining a valid session identifier without the need for predicting or capturing one. The name for this type of attack originates from a publication by Acros Security entitled Session Fixation Vulnerability in Web-based Applications, although the method itself predates the publication. I will expand on the basic idea of session fixation and demonstrate some methods of prevention, all in a PHP-specific context.

Session Fixation

Session security is a vast and complex topic. One of the fundamental principles of Web application security is to never trust data from the client. However, in order to achieve statefulness, the client must identify itself by sending a unique identifier. This fundamental conflict creates significant complexities for developers wanting to build secure, stateful applications. In fact, the session mechanism in any Web application is likely to be that application's most vulnerable feature, and session security is one of the most complex topics of Web application security on any platform.

There are numerous types of session-based attacks. Many of these fit into a category called impersonation (session hijacking), where a malicious user attempts to access another user's session by posing as that user. At the very least, these types of attacks require that the malicious user obtain a valid session identifier, because this is the minimum amount of information that must be used for identification.

There are at least three ways that a valid session identifier can be obtained by an attacker:

  1. Prediction
  2. Capture
  3. Fixation

Prediction only involves guessing a valid session identifier. This guess can range from a wild guess to an educated one, depending upon the sophistication of the attack being used. With PHP's native session mechanism, valid session identifiers are extremely difficult to predict, so this is unlikely to be the weakest point in your implementation.

Capturing a valid session identifier is much more common, and there are numerous types of attacks that use this approach. When a cookie is used to store the session identifier, a browser vulnerability might be exploited in order to obtain the session identifier. When a URL variable is used, the session identifier is more exposed, and there are many more potential methods of capture. For this reason, cookies are generally considered to be more secure than URL variables for session identifier propagation, although user preferences must be honored, and browser vulnerabilities exist in all versions of the most popular browser, Internet Explorer (see http://www.peacefire.org/security/iecookies/ and http://shiflett.org/articles/passport-hacking-revisited for more information).

Session fixation is a method that tricks a victim into using a session identifier chosen by the attacker. If successful, it represents the simplest method with which a valid session identifier can be obtained.

A Simple Attack

In the simplest case, a session fixation attack can use a link:

<pre class="code"> 
<a href="http://host/index.php?PHPSESSID=1234">
Click here
</a>

Or a protocol-level redirect:

<?php 
header
('Location: http://host/index.php?PHPSESSID=1234');
?>

Other methods include the Refresh header, whether passed as a legitimate HTTP header or by using a meta tag's http-equiv attribute. The point is to get the user to visit a remote URL that includes a session identifier of the attacker's choosing. This is the first step in a basic attack, and the full-circle attack is illustrated in Figure 1.


Figure 1: A typical session fixation attack

If successful, the attacker is able to bypass the necessity of capturing or predicting a valid session identifier, and it is subsequently possible to launch additional and more dangerous types of attacks.

Think you're not vulnerable? Consider the code in Listing 1. Save this code as session.php somewhere where you can test it. After you ensure that you have no existing cookies from the same host (clear all cookies if you're not certain), use a URL ending in session.php?PHPSESSID=1234 to visit the page. For example, http://host/session.php?PHPSESSID=1234. The script should output 0 on your screen upon your first visit. Reload the page a few times, and you should notice the number incrementing each time, indicating the number of previous visits.

Listing 1
<?php 
session_start
();

if (!isset(
$_SESSION['count']))
{
   
$_SESSION['count'] = 0;
}
else
{
   
$_SESSION['count']++;
}

echo
$_SESSION['count'];
?>

With a different browser, or even an entirely different computer, go through the exact same initial steps. Upon visiting the URL for the first time, you will notice that you do not see 0. Rather, it recalls your previous session. Thus, you have impersonated the previous user. Now, if you consider that this all began with a session identifier being passed in the URL, you should see the basic danger that session fixation presents. Unlike a typical scenario, PHP did not generate the session identifier.

There are a few shortcomings to this simplistic type of attack. The most important shortcoming is that the target application must use the session identifier passed to it, otherwise this attack will fail. If your session mechanism is nothing more than session_start(), your applications are vulnerable, as the previous demonstration illustrates. In order to prevent this specific vulnerability, you should always ensure that a new session identifier is used whenever you are starting a session for the first time. There are many ways this can be achieved, and one example is given in Listing 2 (this approach, too, has at least one weakness, so wait until you finish this article before deciding on the solution that best fits your needs).

Listing 2
<?php 
session_start
();

if (!isset(
$_SESSION['initiated']))
{
   
session_regenerate_id();
   
$_SESSION['initiated'] = true;
}
?>

If the code in Listing 2 is used to start all sessions, any existing session will always have a session variable named initiated that is already set. If this is not the case, the session is new. The call to session_regenerate_id() replaces the current session identifier with a new one, although it retains the old session information. So, if the attacker coerced a user into using an external link to your application that contains the session identifier, this approach will prevent the attacker from knowing the new session identifier, unless the session has already been initiated.

A Sophisticated Attack

A more sophisticated session fixation attack is one that first initiates a session on the target site, optionally keeps the session from timing out, and then executes the steps mentioned previously.

An alternative to the approach used in Listing 2 is to call session_regenerate_id() whenever a user successfully logs in, since this is the moment the session data becomes sensitive for most applications. For example, whenever you validate a user's username and password, you might set a session variable that indicates success:

$_SESSION['logged_in'] = true;

Just prior to setting such a session variable, a call to session_regenerate_id() can help to protect against a session fixation attack:

session_regenerate_id(); 
$_SESSION['logged_in'] = true;

In fact, a good approach is to always regenerate the session identifier whenever the user's privilege level changes at all, including situations where the user must re-authenticate due to a timeout. By doing this, you can be sure that a session fixation vulnerability is not the weakest aspect of your access control mechanism.

This approach is more secure than the previous example, because it adds another significant obstacle for an attacker to overcome, and it prevents sophisticated attacks where a valid session is first created and maintained. Unfortunately, it still may have at least one weakness, although your application design should already prevent it.

An Advanced Attack

In the most advanced type of session fixation attack, the attacker first obtains a valid account on the target application — and this is typically only appealing when the attacker can do so anonymously. On some PHP applications, the login page is a separate script, such as login.php, and this script may not check the user's state, because it seems safer to assume that the user has not been authenticated.

On the contrary, this approach can allow an attacker to create a session, log into the application with that session, optionally keep the session from timing out, and use the URL to the login page to launch the attack. If the login page accepts the new user's login but fails to regenerate the session identifier (because the privilege level has not changed), a vulnerability exists.

This scenario may seem unlikely, but a thorough examination of your code with this situation in mind is well worth your time. There are two easy ways to prevent this particular issue:

  1. Have the login page recognize the user's state.
  2. Always regenerate the session identifier on the receiving script, regardless of the user's state.

Until Next Time...

A good generic recommendation for preventing session fixation attacks is to regenerate the session identifier anytime the user provides authentication information of any kind. Be wary of passing along such a simplistic catch-all suggestion, however, because misinterpretations are likely when someone is unfamiliar with the type of attack being prevented. There is no substitute for a good understanding of session fixation, and it is possible that the best prevention for your applications is not even mentioned in this article.

Hopefully, you can now eliminate session fixation from your list of serious security risks with which to be concerned. If you develop a particularly creative method of prevention, I would love to hear it. Until next month, be safe.

Comments

Dharmesh Acharya writes:

Hi,

Can you suggest some ready made class or library for easy and secure session handling..

Dharmesh

Posted on Tue, 14 Sep 2004 at 09:41:24 GMT

Dennis writes:

Hi,
Thank you for the valuable information!
Yes, I would like to see a sample secure session library/class myself. Through I have a lot of information to do it myself.

Posted on Tue, 14 Sep 2004 at 22:35:34 GMT

Add a Comment

If you would like to make a comment, please use the form below.

Note: No HTML is allowed. Your comment appears exactly as you enter it, including HTML, line breaks, and code. However, URLs are converted to links for you.

Name
Home Page (URL)
Comment
Remember Info?