2

It is pretty apparent that most of us PHP programmers don't want our published work to be hacked or exploited in ways we did not intend. I am therefore extra careful when asking about ways to counter session hijacking. I know there is the session_regenerate_id() function to partly counter session hijacking but I was more curious about another method I came across:

As a user logs in to the website you take their user_id (or another even more secret, predefined encrypted string) (which is unknown for common users) as a string and you salt it with random predefined symbols, md5() the string and set it as a $_SESSION['user_code'] = $that_string; and anytime this user goes to a page you salt repeat the procedure and match it with $_SESSION['user_code'], if they do not match; destroy the session.

So in code it would look something like this (for example):

 //user credentials are correct, user data is fetched from db   

$_SESSION['username'] = $row[3]; //username
$_SESSION['password'] = $row[2]; //password
$_SESSION['user_id'] = $row[4]; //user_id
$salt1 = 'uNs819';
$salt2 = 'J2i';
$user_code = $salt1 . $row[4] . $salt2;
$user_code = md5($user_code);
$_SESSION['user_code'] = $user_code;

And then you check if this is correct in the beginning of every available page with:

//fetch user credentials from db again
//$row4 is the user_id
if($_SESSION['user_code'] != md5($salt1 . $row[4] . $salt2){
    session_destroy();
}

I do not think using the user_id as part of the encryption is optimal but it is only an example. Preferably I will use an md5 string of the timestamp of when the user was created. But if I was being unclear my main question is that is this method solid against session hijacking, why/why not?

Joshua
  • 40,822
  • 8
  • 72
  • 132
Alien13
  • 558
  • 3
  • 8
  • 30

3 Answers3

1

You don't need a fancy scheme with multiple salts.

Also, if I can steal a user's session cookie, your scheme won't work at all.

  1. Change the session id after login to avoid session fixation

  2. Use HTTPS everywhere

  3. Use httpOnly session cookie so JavaScript cannot read it

  4. Validate and reject XSS input and escape user-generated data on output

  5. Use a long, random session id

  6. Reauthenticate user for important operations

Neil McGuigan
  • 46,580
  • 12
  • 123
  • 152
0

Always check any forms against a cross-site forgery tokens, for example, on login create them a token:

Session:set('token', md5(uniqid());

Then on each form place a hidden form input with the said token

<input type="hidden" name="crsf" value="<?php echo System::escape(Session::get('token'));">

Then you can check them to make sure:

if(Request::post('crsf') == Session::get('token'):
   //do what you gotta do

Make sure you regenerate a new token on each form submit whether it was successful or not

I apologise for using methods for this, but you get the gist how to handle forms and what not.

  • 1
    Alien13 did not ask about CSRF, and what you describe will break if the user opens a second window – symcbean Aug 07 '15 at 01:31
0

"Another method I came across" - please cite your sources.

What you describe here does precisely nothing to influence session hijacking. It doesn't matter how many session values, how many salts and how many rounds of encryption you use, the result will always match. If the session is compromised you cannot rely on it to verify the session. The session_regenerate_id() function does add a little value but only reduces the window for an existing vulnerability to be exploited. Spend your time preventing session compromise - use https, HSTS, http-only+secure cookie flags, a strict CSP, session destruction on expiry.

If you really feel the need to further enhance the security then use a token out with the normal exchange, e.g. a challenge response using local storage or device fingerprinting.

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • I am not very familiar with session hijacking and this might be a weird question, but this method might work since the $user_code is only generated and stored as a session value on a successful, legitimate login ($user_code is generated combined with data stored on a db which is only fetched upon a legitimate login). An outside session hijacker would never be able to guess the secret string (which is unique for all users) fetched from the db, and therefore have an invalid/empty $user_code and destroy the session? – Alien13 Aug 07 '15 at 01:51
  • Both are still facts held serverside and linked to the session. – symcbean Aug 07 '15 at 01:58
  • Does this still apply even if the user_code only is generated and linked to a session only upon a legitimate, successful login? – Alien13 Aug 07 '15 at 02:15