PHP Session Security

There are a couple of things to do in order to keep your session secure:

  1. Use SSL when authenticating users or performing sensitive operations.
  2. Regenerate the session id whenever the security level changes (such as logging in). You can even regenerate the session id every request if you wish.
  3. Have sessions time out
  4. Don't use register globals
  5. Store authentication details on the server. That is, don't send details such as username in the cookie.
  6. Check the $_SERVER['HTTP_USER_AGENT']. This adds a small barrier to session hijacking. You can also check the IP address. But this causes problems for users that have changing IP address due to load balancing on multiple internet connections etc (which is the case in our environment here).
  7. Lock down access to the sessions on the file system or use custom session handling
  8. For sensitive operations consider requiring logged in users to provide their authenication details again

One guideline is to call session_regenerate_id every time a session's security level changes. This helps prevent session hijacking.


My two (or more) cents:

  • Trust no one
  • Filter input, escape output (cookie, session data are your input too)
  • Avoid XSS (keep your HTML well formed, take a look at PHPTAL or HTMLPurifier)
  • Defense in depth
  • Do not expose data

There is a tiny but good book on this topic: Essential PHP Security by Chris Shiflett.

Essential PHP Security http://shiflett.org/images/essential-php-security-small.png

On the home page of the book you will find some interesting code examples and sample chapters.

You may use technique mentioned above (IP & UserAgent), described here: How to avoid identity theft


I think one of the major problems (which is being addressed in PHP 6) is register_globals. Right now one of the standard methods used to avoid register_globals is to use the $_REQUEST, $_GET or $_POST arrays.

The "correct" way to do it (as of 5.2, although it's a little buggy there, but stable as of 6, which is coming soon) is through filters.

So instead of:

$username = $_POST["username"];

you would do:

$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);

or even just:

$username = filter_input(INPUT_POST, 'username');