Here's the code. It's a simple operation to check that a session ID isn't being spoofed by verifying the IP address:
session_start();
$session_ip_address = $_SERVER['REMOTE_ADDR'];
if((!isset($_SESSION['SESSION_IP_ADDRESS'])) || !$_SESSION['SESSION_IP_ADDRESS']) {
$_SESSION['SESSION_IP_ADDRESS'] = $session_ip_address;
}
if($_SESSION['SESSION_IP_ADDRESS'] != $_SERVER['REMOTE_ADDR']) {
session_destroy();
$_SESSION['security_error'] = true;
}
If I insert var_dump($_SESSION)
right after session_start()
and again at the end of the script, then the very first time I run the code (without a session cookie set) I see that at first the array is empty, then it has my IP address assigned to the key 'SESSION_IP_ADDRESS'. So far, so good. But when I run the code again, now it shows that 'SESSION_IP_ADDRESS' is stored as a reference immediately after the session starts (I can tell by the ampersand prepended to the string). When I run it a third time, I see that 'SESSION_IP_ADDRESS' is now a null reference ('SESSION_IP_ADDRESS' => &null
) immediately after the session starts. What is going on?!
To reiterate, this is the output the first time:
array(0) {
}
array(1) {
["SESSION_IP_ADDRESS"]=>
string(11) "xx.xx.xxx.x"
}
This is the output the second time:
array(1) {
["SESSION_IP_ADDRESS"]=>
&string(11) "xx.xx.xxx.x"
}
array(1) {
["SESSION_IP_ADDRESS"]=>
&string(11) "xx.xx.xxx.x"
}
And the third time and every time from then on:
array(1) {
["SESSION_IP_ADDRESS"]=>
&NULL
}
array(1) {
["SESSION_IP_ADDRESS"]=>
&string(11) "xx.xx.xxx.x"
}
If I have:
<?php
$x = 'blah';
$_SESSION['blah'] = $x;
var_dump($_SESSION);
I get:
array(1) {
["blah"]=>
string(4) "blah"
}
No references in sight. PHP 5.3.2 on Ubuntu 10.04.1
it does assign by value, the reference &
next to $_SESSION
has nothing to do with your expression $_SESSION['x'] = $x;
The only time your session variables are going to be references, is when you reference a session variable to another session variable (or if the original reference is still in scope).
Per example:
session_start();
$x = 'foo';
$_SESSION['x'] = &$x;
This will give you:
array(1) {
["x"]=>
string(3) "foo"
}
While this:
$x = 'foo';
$_SESSION['x'] = $x;
$_SESSION['y'] = &$_SESSION['x']; // reference to another $_SESSION var
Or this:
session_start();
$x = 'foo';
$_SESSION['x'] = $x;
$_SESSION['y'] = &$x;
var_dump($_SESSION); // reference still in scope
Would give you:
array(2) {
["x"]=>
string(3) "foo"
["y"]=>
&string(3) "foo"
}
Either way, doing this:
session_start();
$y = $_SESSION['y'];
$y = 'bar';
Will not modify the y
session variable. In order to do that, you'd have to do:
session_start();
$y = &$_SESSION['y'];
$y = 'bar';
One of my customers had a very similar problem.
Make sure your PHP configuration (PHP.ini) has register_globals Off
otherwise regular variables overwrite superglobals including PHP sessions.