note 72856 added to ref.session
| From: | nihato at notrashplease dot taakc dot org | Date: | Sat, 03 Feb 2007 08:49:04 +0000 |
| Subject: | note 72856 added to ref.session | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-122656@lists.php.net to get a copy of this message | ||
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
----
Server IP: 69.147.83.197
Probable Submitter: 69.81.20.97
----
Manual Page -- http://www.php.net/manual/en/ref.session.php
Edit -- https://master.php.net/note/edit/72856
Del: integrated -- https://master.php.net/note/delete/72856/integrated
Del: useless -- https://master.php.net/note/delete/72856/useless
Del: bad code -- https://master.php.net/note/delete/72856/bad+code
Del: spam -- https://master.php.net/note/delete/72856/spam
Del: non-english -- https://master.php.net/note/delete/72856/non-english
Del: in docs -- https://master.php.net/note/delete/72856/in+docs
Del: other reasons-- https://master.php.net/note/delete/72856
Reject -- https://master.php.net/note/reject/72856
Search -- https://master.php.net/manage/user-notes.php