Avoiding frustration with PHP Sessions

PHP’s support for sessions make adding "state" to your web application super easy.  Bus because the illusion of state is maintained by storing a Session ID via a user’s cookies, you might find yourself losing potentially productive hours chasing down bizarre client side bugs or opening up a potential security hole.  Here are 4 tips to help you avoid wasting your time and securing your site.

1. Don’t use underscores in host names

Unless you’ve memorized the RFC for allowed characters in a host name, you may not be aware that underscores are not allowed in host names.  Some browsers, like Firefox, don’t enforce this prohibition, but Internet Explorer enforces it and will refuse to set a cookie belonging to a host name with an underscore in it.  IE will instead cause php to generate a new session id for the visitor on each page load, since, the user never accepts a session id. Source: set_cookie documentation.

2. Commit your sessions before redirects

You should call session_write_close (or its alias session_commit) to write session data before issuing an HTTP Location redirects.  This also "frees" the user’s session so that they can do other activities in your web app.  See the comments by cenaculo and bkatz.

3. Prevent session fixation

Session fixation allows an attacker to get a valid session id without predicting it or reading it from a user’s cookies or $_GET array.  Instead, a victim ends up using a session id generated by the attacker not your web server.  You can prevent this by calling session_regenerate_id(), particularly after storing sensitive information such as a login name or flag.  This should render the attacker’s defined sessin id useless.   Chris Shifflet has a more thorough discussion of Session Fixation.

4. Don’t expose session_id’s

Cookies are, relatively, a more secure place to store your session ids compared to embedding them as a parameter in the query string. There are two ini setting to control this behavior, and which one is appropriate is hard to tell, so you should set them both.  You should set session.use_trans_sid to 0 (off) and if you’re using 4.3.0 or higher you can set session.use_only_cookies to "1".