4

I am developing a web application with PHP where a user will be able to have his or her own account, and the session that keeps track of the user is stored in a MySQL database. Now, after searching for an answer on how to implement this, I find that many people like to both use session_destroy() and unset the cookie. Why - wouldn't session_destroy() be enough on its own? Even the PHP manual says "In order to kill the session altogether, like to log the user out, the session id must also be unset."

My reasoning: After the user has logged out, and happens to visit just one more page on your site before leaving, the PHP script checking if the user is logged in or not will call session_start(), setting a new session cookie for the user anyway. Here's how it might look like:

// here we include some scripts and make some instances we'll need
require_once("database.php");
require_once("session.php");
$database_connection = new DB_Connection();
$session = new Session($database_connection);

// here a session cookie is sent to a user, even if he or she isn't logged in
session_start();

// finally we check if the user is logged in
$log_isLogged = false;
if(isset($_SESSION['member_id'], $_SESSION['username'])){
    $log_member_id = $_SESSION['member_id'];
    $log_username = $_SESSION['username'];
    $log_isLogged = true;
}

Sure, it is nice for when the user knows about this fact, and leaves the site before a new cookie might be set. But some sites even redirect you to a new page directly after a logout, resulting in a new session cookie - undoing what you just did.

Is my reasoning flawed in some way, or does it not really matter if you unset a session cookie or not? Maybe most developers just think along the lines that it at least can't hurt to unset it?

I am not a native speaker, so I apologize in advance for any typos and grammatical errors.

Chris Hepner
  • 1,552
  • 9
  • 16
Muuse
  • 177
  • 1
  • 1
  • 9

1 Answers1

9

The (poorly named) session_destroy() function only deletes data out of the session. It does not remove the session cookie from the browser and leaves the session_id associated with the session. session_start() only issues a new session_id to the client if one was not already supplied in the client's request. Your code is vulnerable to an attack known as session fixation, where a malicious attacker will start a session on your site to obtain a valid session_id, and then trick unsuspecting users of your site to login with the attacker's known session_id. This can be accomplished by either sending the victim a link with the session_id in the URL (if your site will accept it that way) or various other methods. Once the victim logs in, the attacker is effectively logged in as that same user as well.

In order to prevent session fixation attacks you should:

  1. On successful login, issue a brand new session_id to the client by calling session_regenerate_id().

  2. On logout, completely destroy every artifact of the session on both server and client. This means calling session_destroy() and unsetting the client cookie with setcookie().

  3. Make sure your site does not ever expose session_id in the URL or accept a session_id supplied in the URL.

  4. Make sure your session_ids are long and random enough that they cannot practically be guessed by a would be attacker.

  5. Make sure your site is not vulnerable to cross site scripting attacks, which would allow attackers to steal valid session_ids from already logged-in users.

  6. Make sure your login occurs over https and the session cookie is marked secure. All communication related to sessions should occur over https. The client's session_id must never be sent over http because that would expose it during transit.

Further reference: OWASP Top Ten page on session management

Asaph
  • 159,146
  • 25
  • 197
  • 199
  • All right, thanks, I'll look into that - do you know how I would go about preventing this from happening? Maybe changing the SID at every pageview, or at least directly after logging in? – Muuse Aug 03 '11 at 15:30
  • I understand 1, 3, 4 and 5. Now after I've read them they seem obvious. However I still do not get how unsetting the cookie would do any much difference - in 2 - as long as all the data is deleted on the server side. I mean, when NOT unsetting the cookie, all the data would still be destroyed on the server side because of session_destroy(). The user would be left with a SID as a cookie in the browser, sure, but one that the server doesn't recognize as logged in. What's the harm in that? I'll take a look at the link you provided me with. Thanks a lot!! – Muuse Aug 03 '11 at 15:42
  • @laph: think of #2 as buying a used cell phone. even if you put in your own SIM, the phone's IMEI stays constant, and your cell traffic can be captured by someone who knows the IMEI (e.g. the person who sold you the phone). To guarantee your session cannot be hijacked, you have to change EVERYTHING related to a session, including its ID. – Marc B Aug 03 '11 at 15:47
  • Nice explanation! But I like session_destroy() function name :) – armandomiani Aug 03 '11 at 23:04