About the Author

Chris Shiflett

Hi, I’m Chris: entrepreneur, community leader, husband, and father. I live and work in Boulder, CO.

Session Fixation

  • Published in PHP Architect on 16 Feb 2004
  • Last Updated 16 Feb 2004

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.

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 peacefire.org/security/iecookies/ and 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:

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

Or a protocol-level redirect:

('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

if (!isset(
$_SESSION['count'] = 0;


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

if (!isset(
$_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['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.

About this article

Session Fixation was last updated on 16 Feb 2004. Follow me on Twitter.


1.Dharmesh Acharya wrote:


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


Tue, 14 Sep 2004 at 09:41:24 GMT Link

2.Dennis wrote:


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.

Tue, 14 Sep 2004 at 22:35:34 GMT Link

3.mariussk at epost dot no wrote:

this lines:


$_SESSION['logged_in'] = true;

Was the most useful on your article.

Wed, 02 Feb 2005 at 09:34:33 GMT Link

4.chris wrote:

niec tutorial, not sure how I'm going to use it though. I think I need a more indepth tutorial. If this happens please let me know

Tue, 08 Mar 2005 at 11:44:17 GMT Link

5.r^a wrote:

using adodb mcrypted sessions ..basically regenerates the id on every 3 page loads and verifys browser/ip on everyload.... works perfect... a little overhead but worth it...

public function check()


$last_session_id = session_id();

if(!empty($_SESSION['page_view_count']) && $_SESSION['page_view_count'] % 3 == 0)




$new_session_id = session_id();

$last_access = time();

if (empty($_SESSION['hash']) || empty($_SESSION['last_access']))


$_SESSION['last_access'] = $last_access;

$_SESSION['hash'] = md5($_SERVER['HTTP_USER_AGENT'] . ':' . $_SERVER['REMOTE_ADDR'] . ':' . $last_access . ':' . $new_session_id);

$_SESSION['page_view_count'] = 1;




if($_SESSION['hash'] == md5($_SERVER['HTTP_USER_AGENT'] . ':' . $_SERVER['REMOTE_ADDR'] . ':' . $_SESSION['last_access'] . ':' . $last_session_id))


$_SESSION['last_access'] = $last_access;

$_SESSION['hash'] = md5($_SERVER['HTTP_USER_AGENT'] . ':' . $_SERVER['REMOTE_ADDR'] . ':' . $last_access . ':' . $new_session_id) ;









Sat, 12 Mar 2005 at 21:56:13 GMT Link

6.maxx gass wrote:

you could also use challenge codes which get changed on every page load, just like recent versions of PEAR::Auth

Sun, 15 May 2005 at 09:57:29 GMT Link

7.ezee wrote:

Great article. I am an amateur to PHP and I was just wondering ... if the attack is launched via a url such as http://host/index.php?PHPSESSID=1234

... then, why can't we just check the $_SERVER["REQUEST_URI"] to see if it contains "PHPSESSID=".

Is there some other way that the attacker can launch the attack?


Fri, 01 Jul 2005 at 19:31:32 GMT Link

8.Greenwood wrote:

Thanks a lot for your articles, Chris

Sun, 11 Sep 2005 at 12:10:43 GMT Link

9.Gasper wrote:


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.

Mon, 12 Sep 2005 at 19:40:37 GMT Link

10.Richard wrote:

I didn't know about session_regenerate_id() so thanks for pointing this out and explaining it so clearly.

Sat, 08 Oct 2005 at 12:39:11 GMT Link

11.Buraque wrote:

I didn't even know that there is a security problem like this.

Thank you for this very useful info.

I have patched my pages already.

I am not an expert PHP coder. I am using a single index.php file, and include the content page according to the <i>index.php?page=somepage</I> directive in URL.

So every click, every move in my site loads index.php file.

My solution was, in the index.php I put:


$save_session = $_SESSION;


$_SESSION = $save_session;

I have tested it. It creates a new session_id everytime, and I am keeping the session variables intact.

Anyone have any comment on the way I am using? Any potential problems?

Thank you.

Sun, 23 Oct 2005 at 16:03:53 GMT Link

12.Web Development Company India wrote:

Hope In php5 problem are less

Thu, 27 Oct 2005 at 08:59:38 GMT Link

13.hallwhere wrote:

Does this apply to server only? If not, what can we do to increase security in our browser?

Tue, 01 Nov 2005 at 03:20:44 GMT Link

14.James wrote:

Greate site. Thank you :)

Tue, 01 Nov 2005 at 14:33:12 GMT Link

15.Richard wrote:

Buraque, you do not need the $save_session; this is done automatically for you.

Thu, 10 Nov 2005 at 22:36:33 GMT Link

16.Zinho wrote:


I've finished my research on session fixation attacks and way to prevent it. It covers the best techniques to follow to be safe from such attacks.

You can find it here:


Hope it helps

Thu, 22 Dec 2005 at 19:07:33 GMT Link

17.Abdul Majid wrote:

I've read the article and i feel blown away - there must be quite a large market for providing php security consultancy

Mon, 26 Dec 2005 at 19:34:51 GMT Link

18.Phil wrote:

When I process the login script I regenerate the session ID and store it in a variable in the session

$_SESSION['sess'] and then set $_SESSION['logged_in'] = true

At the beginning of each page that is restricted I check session_id() against $_SESSION['sess'] and I check $_SESSION['logged_in']

Is that enough, or am I just kidding myself?

Wed, 25 Jan 2006 at 21:28:50 GMT Link

19.sole wrote:

The URL to the PHP security page doesn't seem to be working, but this one does:


Keep up the good work! :D

Thu, 25 May 2006 at 14:32:56 GMT Link

20.James Nelson wrote:

Great article. I was the victim of an attack a few weeks ago and I suspect it was session hijacking. Thanks for the info - I have patched my apps!

Sat, 30 Sep 2006 at 18:18:24 GMT Link

21.Mat wrote:

Just to follow up on r^a's comment. I found an annoying problem today when using HTTP_USER_AGENT to avoid session fixation attacks.

When using the context menu's "Download Linked File" in Safari, it reports the user agent as CFNetwork/129.16

Fri, 20 Oct 2006 at 14:19:09 GMT Link

22.Dan wrote:

There is a good secure_session class located at


I've used this class and can vouch for it. It optionally regenerates the session id, checks the remote IP address, and check's the user's browser.

Only trouble I had was with AOL users. Since their requests come from all the place (different proxy servers) I had to shut off the IP address checking...

Fri, 10 Nov 2006 at 08:29:13 GMT Link

23.system wrote:

You could always set "session.use_only_cookies" to 1 in php.ini, much easier :p

Thu, 01 Feb 2007 at 18:50:22 GMT Link

24.Chris Shiflett wrote:

Yes, much easier, but it doesn't offer sufficient protection.

Fri, 02 Feb 2007 at 22:19:39 GMT Link

25.shg wrote:

How about:

if (isset($_COOKIE[session_name()]))

setcookie(session_name(), '', 0, '/');


insted of:


$_SESSION['logged_in'] = false;

when users loggs out? Is it more secure? I'm using this in my script, after destroying the session, comes the 'Location' header, which redirects user to the main page, and new session is started then (each page includes the login.php script, so session is started always when session data, i.e. cookie, is not present).

Great articles, thanks!

Sun, 04 Feb 2007 at 17:04:22 GMT Link

26.Joe wrote:

This article helped me a lot I was the loser of an attack a few weeks ago and I suspect it was session hijacking. Thanks for the info - I have patched my apps!

Thu, 15 Feb 2007 at 15:49:37 GMT Link

27.newbie wrote:

How about an in depth tutorial, as a PHP learner, all I seem to find are snippets of code that are not complete enough to understand or use. You are obviously very talented at this, us new to PHP would dearly relish a PROPER tutorial, not like some of the tutorials that are out there.

Sun, 25 Feb 2007 at 17:44:45 GMT Link

28.Brendan Falkowski wrote:

This is an excellent article. Session fixation attacks are starting to be discussed more in PHP security circles. There is a whitepaper from the PHP website that explains the topic as well. It may be of additional help to some.


Sat, 24 Mar 2007 at 20:04:24 GMT Link

29.Alex wrote:

For all those who asked for ready made secure session classes, i recommend learn how sessions work, and then writing your own secure session class, so that you are not blind to the operation of your website

Thu, 19 Apr 2007 at 22:35:20 GMT Link

30.Elan wrote:

Hello. Thankyou for this very usefull information.

I was just reading what other users had said and it is all good storing the session in a cookie, but what if the user doesnt have cookies enabled?


Wed, 11 Jul 2007 at 23:31:40 GMT Link

31.Hossein wrote:


Dear chris,

These sentences are in your book,From Chapter 4,

Please explain more about them:


To make propagation a bit easier to manage, you might consider keeping the entire query string in a variable. You can append this variable to all of your links, which makes it easy to refactor your code later, even if you don't implement this technique initially.

2-Keep in mind that a browser includes a Cookie header in all requests that satisfy the requirements set forth in a previous Set-Cookie header. Quite commonly, the session identifier is being exposed unnecessarily in requests for embedded resources, such as images. For example, to request a web page with 10 images, the session identifier is being sent by the browser in 11 different requests, but it is needed for only 1 of those. To avoid this unnecessary exposure, you might consider serving all embedded resources from a server with a different domain name.

May you give me example about this " different domain name"?

3-The Refresh header can also be usedprovided as an actual HTTP header or in the http-equiv attribute of a meta tag. The attacker's goal is to get the user to visit a URL that includes a session identifier of the attacker's choosing. This is the first step in a basic attack; the complete attack is illustrated in Figure 4-3.

Thanks in advance,

Tue, 17 Jul 2007 at 08:00:39 GMT Link

32.Alexander Waldmann wrote:

@Hossein: May you give me example about this " different domain name"?

He means: Your scripts are accessed on server domain1.com and the images referenced in the html code are coming from domain2.com - because the domain is differently, any cookies for domain1.com containing the session id will not be transmitted while requesting the images.

In general it is quite useful to use 2 different servers serving static resources (files that don't change, e.g. images, downloadable files, etc.) because this can also increase performance. Imagine one lightweight webserver (apache with almost no modules compiled in) for serving static resources and a heavyweight server with all necessary modules for script execution.

kind regards


Tue, 28 Aug 2007 at 13:00:14 GMT Link

33.Shade wrote:

I put in a check for "PHPSESSID" in the GET string (I could modify it to check for POST as well), no matter where on the site they're trying to go, and print out a special error message to raise their awareness of the attack. I might be going a bit too far in checking the entire GET string (not just variables), but I figure that paranoia is a better foundation to work from than gullibility; FIRST users become accustomed to the simple question of "Is there a PHPSESSID string in this link I was given?", THEN (when/if they ever feel up to it) they can move on to parsing the string, only looking for substrings following a ? or & symbol, etcetera.

Thu, 10 Apr 2008 at 05:17:16 GMT Link

34.Different Dennis wrote:

To remove another vulnerability, session_regenerate_id(); should be replaced with session_regenerate_id(true);

On this link:


Ilia Alshanetsky highlights that in the session_regenerate_id() function, when it renames the session id it does not remove the old session, leaving it active and potentially usable by a would be hacker.

I (Different Dennis) checked this and it's true. You can check for your self by storing your session data in a directory that you can access (using the session_save_path command) to see what session files are in it.

1. Using the following, each time a new id is created, the old session file is left behind, with the data still in the file. So each time the following is called, one more old session file is added to the session directory.



2. The following solves this. Each time a new id is created, the old session file is deleted.




Different Dennis

Sun, 13 Apr 2008 at 11:46:57 GMT Link

35.Shade wrote:


This is only a vulnerability if you don't have any checks in your code for which privileges a given session/ID has. Keeping the old session alive may be desirable so that, if an attacker got in ahead of the user, you can display a message upon a 2nd successful login attempt to the effect of "This system has already logged you in once, if this is your first time logging in you may click here to terminate both connections.", and if someone is attempting to log in after the first user successfully has, you can display a message to them reporting how many attempts and suggesting ways they can check their local security.

You can keep track of the new session ID with a variable in the old session, and vice versa.

Tue, 15 Apr 2008 at 17:54:07 GMT Link

36.yacahuma wrote:

I was not able to replicate your text. I copied the listing 1. open firefox and visit de link. Started from 0. click a couple of times

Then open explorer and visit the link and I started from 0 again

Could my php configuration cause this?

Sat, 03 May 2008 at 01:13:48 GMT Link

37.Sam Wilson wrote:

Anyone want to comment on the explanations and code about session fixation in the PHP wikibook? It could certainly do with some help I think...



Wed, 07 May 2008 at 06:26:36 GMT Link

38.James Magee wrote:

I have a method that I implemented into my Browser Based Rpg Login Script, along with the examples above I also generate a random string(8-12 characters-md5'd) upon logging in, then a login time is generated and stores a session variable(named after the login time) whose value = the random string. The string and login time are stored in a mysql database md5 encrypted as well. Upon entering pages which require you to be authenticated it will check the PHPSESSID and the login time session variable, if either or are incorrect..well relogin pursues... Let me know what you think and if there are vulnerabilities in this as I haven't opened it to the public yet.

Mon, 02 Jun 2008 at 04:19:05 GMT Link

39.Arran Schlosberg wrote:

After some quick experimenting I noticed that although the session data is moved to a new ID the old one is still available. If I am correct about this then it raises 2 important points:

1) Pass the parameter true to session_regenerate_id(true) as this will remove the old session.

2) Regenerate the ID prior to performing the changes to the session data as this will still render the original ID (assuming you failed to perform (1)) useless.

Sorry if I repeated anything Chris wrote here. I never read the article but have used his book extensively so thought I'd share something that I don't remember reading elsewhere.

Following the "defense in depth" strategy both (1) and (2) should be performed. A quick and dirty example:

// ... authenticate and set $authenticatedUser appropriately ...
  session_regenerate_id(true); //remove the old session
  $_SESSION['user'] = $authenticatedUser; //done after the regeneration

Wed, 10 Sep 2008 at 00:05:49 GMT Link

40.Jaymar wrote:

Hi, nice article..

I have one question though, if you turn off global variables on your php.ini, will the type of attack mentioned above (where the the session id was implied by the attcker by adding PHPSESSID to the URL) still be possible?

If you turn off global variables, $_SESSION variables will be different from $_GET variables, so I'm assuming that this will no longer be a problem..

Can anyone comment on this?

Mon, 26 Jan 2009 at 06:16:17 GMT Link

41.sean wrote:

Great article!!! I was wondering about the following code, which would seem open to a fixation attack, but is not...

This is the beginning of the private page...



if (!isset($_SESSION['user']))


header("Location: http://[address of login page]?requestedpage=[token for this page]");




If an attacker caused a known user to request the above page with ?PHPSESSID=1234, the session_start would then register 1234 as the current session

This is from the login page...


if($_POST['[a posted form var]'])


// check submitted credentials against known users

$status = authenticate(...);

// if user/pass combination is correct

if ($status == 1)


// initiate a session


// register some session variables

$_SESSION['XXXXXX] = filter($_POST['XX']);

// redirect to protected page

header("Location: ...[requested page]);




When the user logged in above, the session_start would use the session cookie from the first session_start above and have a validated session with an SID known to the attacker.

However, the top snippet does not cause an SID to be recorded in a cookie, but the bottom one does. Hence, the attack is prevented, but why?

Thanks, cheers!

- Sean

Mon, 16 Feb 2009 at 18:54:05 GMT Link

42.kurinchiblogger wrote:

Explanation with Depiction makes it easier for the readers to understand the concept

Thanks Chris!

Tue, 28 Jul 2009 at 03:43:03 GMT Link

43.Big Peanut Butter Cookie wrote:

Hello, and thanks for the article! All of the ones on this site are super helpful (although I'm very much a novice to PHP, there's a pretty steep learning curve).

Anyways, I was wondering if you thought that regenerating the session ID on every single page is good enough protection. Granted, I don't know how scalable this is, but I'm okay with it for now, since this is sort of a personal project. My login script checks for whether the user is logged in or not, and cuts everything off if they're not.

Also, this is probably the wrong place to put this question, but hopefully you won't mind. Could someone spoof the session variables? For example, the user is identified by this variable: $_SESSION['userid'], where its value is the ID of the player. For example, my ID would be 1. Could a player intercept something and change their own ID to 1?

I've used Paros Proxy and intercepted... things, but haven't been able to crack it yet, since I validate everything on the server side. Register_globals is off, so I'm guessing these things can't be spoofed, but I want to be absolutely sure.

Finally, does this offer some kind of protection against XSS/CSS attacks?

Just trying to cover all my bases security-wise, I'm kind of paranoid like that. Thanks, and hopefully someone can help me out here :)

Sun, 09 May 2010 at 22:26:15 GMT Link

44.Mario Arroyo wrote:

The article is really very good and the users comments and external links to another articles just complement it!

Thu, 02 Sep 2010 at 21:13:53 GMT Link

45.Daniel skoglund wrote:

Totally awsome session security series

Sun, 05 Dec 2010 at 00:07:25 GMT Link

46.Sheo Narayan wrote:

I have written an article on How to avoid session fixation vulnerability in ASP.NET application. Have a look at this at http://www.dotnetfunda.com/articles/article1395-how-to-avoid-the-session-fixation-vulnerability-in-aspnet-.aspx

Hope this helps.


Wed, 08 Jun 2011 at 18:54:33 GMT Link

Hello! What’s your name?

Want to comment? Please connect with Twitter to join the discussion.