8

I have been looking into creating secure php sessions for use in a login script for a week or so now. So far I have not found a concrete resource to base my work off, reading StackOverflow all I have seen is mixed views and opinions.

I decided to dive in and give writing a function to begin the session a go.

With extensive reading and watching Samy Kamkar's presentation from DEFCON on Youtube I am fairly confident and pleased with the first piece of this system I have written.

$session_name = 'sec_session_id'; // Set a custom session name
$secure = false; // Set to true if using https else leave as false
$httponly = true; // This stops javascript being able to access the session id 
ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies. 
ini_set('session.entropy_file', '/dev/urandom'); // better session id's
ini_set('session.entropy_length', '512'); // and going overkill with entropy length for maximum security

$cookieParams = session_get_cookie_params(); // Gets current cookies params.
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly); 
session_name($session_name); // Sets the session name to the one set above.
session_start(); // Start the php session

This will be used with SSL for the sake of development it's not...

So my question is where can I improve on this script, have I missed anything, what should I look into next...

TuKritical
  • 361
  • 1
  • 3
  • 5

3 Answers3

3

There's a lot of configuration, and not a lot of code.

There's not much point in using a really good random number generator if you don't set the secure flag (but I'll assume that you're going to change this for the live system).

However There are a few problems here.

First you don't say what context this is running in - on a shared server, the session data from the default handler will usually be accesible by all the vhosts. Even on a dedicated server, I'd recommend setting up the sesison handler to restrict access to sessions (e.g. using a database handler, with a stored procedure to set/get the session based on the id and no direct access to the underlying data).

Next, there's nothing here to deal with session fixation. Really you should force the session identifier to change when the session is created (i.e. when it is empty - but remember to put something in there after switching the session id) and when the user is authenticated.

A further caveat is that the default handler will re-use sessions which are past their TTL (if they've not been garbage collected yet).

Polynomiial's advice is good protection against sslstripping.

I would recommend trying to associate a session with a specific device - but unlike Manuel Faux, I'd suggest just using the first 16 bits of the IPV4 address. Similarly matching the user-agent to the session provides additional protection (but note that Google Chrome can update itself on the fly - even mid-session).

Why are you overriding the ini file settings in your code? These should be set in your php.ini file.

$cookieParams = session_get_cookie_params(); // Gets current cookies params.
session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly)

It doesn't make a lot of sense to change the cookie parameters to the values they already hold.

The other thing which is missing from your code is any sort of logging.

symcbean
  • 18,278
  • 39
  • 73
2

This looks pretty good. I can't see any glaring holes, except for the fact that SSL (https only) is switched off - though you mentioned that it'll be switched on in production.

You may also want to look into HTTP Strict Transport Security (HSTS) and Content Security Policy (CSP) (details / intro) for increased security.

Polynomial
  • 132,208
  • 43
  • 298
  • 379
2

You can additionally "lock" the session to a specific client IP address, which makes session stealing even harder, but it makes "roaming" of ISPs or locations for the users almost impossible (user has to relogin).

Manuel Faux
  • 407
  • 3
  • 9
  • I have been thinking about doing that, but it's going to cause issues under load splitters/handlers. – TuKritical Nov 19 '12 at 17:00
  • Which concrete scenario do you have in mind? If your infrastructure is behind a load balancer, every server still sees the same client IP address. – Manuel Faux Nov 19 '12 at 17:03
  • 1
    Keep in mind that this will only prevent session theft in situations where an attacker isn't communicating from the same public-facing IP as the legitimate user. So in a cafe wifi scenario, or when the attacker tunnels traffic through the victim's machine, they'll still get hit. – Polynomial Nov 30 '12 at 13:33