note 72856 deleted from ref.session by didou
| From: | didou@php.net | Date: | Sat, 03 Feb 2007 15:00:52 +0000 |
| Subject: | note 72856 deleted from ref.session by didou | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-122667@lists.php.net to get a copy of this message | ||
Note Submitter: nihato at notrashplease dot taakc dot org
----
I am truly sorry for asking a question here. I tried the newgroups that the support page points to;
the last date of activity there appears to be sometime in 2004. Another excuse: in the case my
problem is a stupid one with a trivial solution, then this post can potentially belong in here. So,
here it goes.
I am new to PHP, but not a novice programmer. What I want is a simple, textbook defense against
session fixation/hijacking threat. I am looking at Marc Wandschneider's book (Web App
Development /w PHP & MySQL, pgs. 647+). The code in simplified form is as follows (/w comments):
<?php
session_start();
// Ensure that you created the session. I.e.,
if ( !isset($_SESSION['created']) )
{ session_regenerate_id();
$_SESSION['created'] = TRUE;
$_SESSION['page_i_Cnt'] = 0; // see below; i = 1, 2, ...
}
// If compromised, make the attacker's life more difficult. I.e.,
if ( !isset($_SESSION['userAgent']) )
{ $_SESSION['userAgent'] = md5("SomeSalt" .
$_SERVER['HTTP_USER_AGENT']);
// Added some salt and hashed it. Hashing alone is not good enough since
// the attacker can guess and inject typical user agents.
}
else
{ if ( $_SESSION['userAgent'] != md5("SomeSalt" .
$_SERVER['HTTP_USER_AGENT']) )
$_SESSION['compromised'] = TRUE;
// So, the attacker is caught red-handed although he has captured the session id.
// Do something appropriate: refuse to continue.
}
?>
Now, this didn't work for me. I tried this using IE6 and FF browsers. I am not showing the test
pages for brevity, but they are trivial; a couple of pages linking to one another, each counting how
many times they are visited. The counters are initialized in the first if block as shown above, and
each test page increments its counter after "requiring once" the above prelude. That is,
their very first line is like:
<?php require_once('session.inc'); ++$_SESSION['page_1_Cnt']; ?>
The outcome of the above code is, the counts are not properly maintained: the present page shows a
count of 1, the others 0, always, consistently.
Upon closer examination, I found that the first "regenerate_id" block was entered on each
page visit. So, instead of two data storage files per session, I was getting one file per click
(page visit): no passing of session data from one page to the next as intended.
I tweaked the code quite a bit (built it up piece by piece from nothing, and stripped it down to
bare bones), and found that it would work properly only if the reference to HTTP_USER_AGENT in the
_SERVER array was eliminated. To be sure, I tried this most innocent version:
<?php
$str = $_SERVER['HTTP_USER_AGENT']; // Just a meaningless reference to _SERVER array
session_start();
if ( !isset($_SESSION['created']) )
{ session_regenerate_id();
$_SESSION['created'] = TRUE;
$_SESSION['page_i_Cnt'] = 0; // see below; i = 1, 2, ...
}
?>
Even that didn't work. Take out that reference, it works.
I am totally mystified. Any clue/input will be appreciated. I am willing to edit and repost this as
usable snippet if I can find a solution. Thanks in advance.
Nihat