Encoding session variables
April 29, 2002
The way PHP stores session variables is in files on the server.
To see where these files are stored, you can use the function
session_save_path(), which returns the directory.
page14.php
<?php
session_start();
print session_save_path();
?>
On most systems this will output:
/tmp
If you have access to the /tmp directory (or whatever your
save_path is), take a look inside it, and you'll see the session
files stored with names such as:
sess_4725a759778d1be9bdb668a236f01e01
Examine one of these files if you can. The files contain all the
session data. You can also get to access them with the function
session_encode(). For example, the following script:
page15.php
<?php
session_start();
session_unset();
$_SESSION["product1"] = "Cocker Spaniels";
$_SESSION["product2"] = "Egyptian Geese";
print session_encode();
?>
will display:
product1|s:15:"Cocker Spaniels";product2|s:14:"Egyptian Geese";
which is the same way the file is stored in the session file.
You can see the name of the variable (product1), a
definition(s:15 for a 15 character string), and the value itself.
I called session_unset() upfront to clear any variables
you may have had lingering from previous pages.
session_encode() is particularly useful for debugging
sessions. It can also be useful for passing session data
across servers, as PHP sessions, since they often use cookies,
which are limited to one server only.
The reverse of session_encode() is session_decode().
You can use it to populate a set of session variables at once,
as follows:
page16.php
<?php
session_start();
session_unset();
session_decode
('product1|s:15:"Cocker Spaniels";product2|s:14:"Egyptian Geese";');
print "Decoded session variables: $product1 $product2 ";
?>
Note:Color coded lines have been split for display purposes
This displays:
Decoded session variables: Cocker Spaniels Egyptian Geese
Even though we have unset all session variables, and not
explicitly registered any, session_decode() has populated
them.
Security
I warned you about using session_register() to put
variables in the global namespace, and then accessing them as an
ordinary $var at the beginning of this tutorial. Now's we'll
see why. Until the release of PHP 4.2, session and HTTP variables
were by default in the global namespace, which allowed some
potential risks. Someone could pass a variable in via a GET and
get access to pages they shouldn't. Take a look at the following
example. Assume page17.php does some sort of authentication,
for example a user logs in and their access details are checked
from a database. They can only reach this portion of page17.php
if they are validly logged in.
page17.php
<?php
session_start();
$_SESSION["access"] = 1;
// even less secure is the following:
// session_register("access");
//$access=1;
print "You have been authenticated -
<a href='page18.php?".SID."'>click here</a>
to go to the secure page ";
?>
Note:Color coded lines have been split for display purposes
page18.php
<?php
session_start();
// this next line is the fatal line
// by not using $_SESSION["access"] it allows
// a potential GET variable to overide
// This also demonstrates why session_register is not good,
// as it allows no other way to access the variable,
// except through this insecure way!
// the correct line would read:
// if ($SESSION["access") == 1) {
if ($access == 1) {
print "Welcome in to the secure site";
}
else {
print "Access not allowed!";
}
?>
By logging in, they can successfully access page18.php. Now,
destroy the session, for example by running page13.php. Trying
to access page18.php will now result in failure. However, a
sneaky cracker has a simple override! By merely passing $access
as a GET variable, i.e. entering "page18?access=1" in the browser,
they are into the secure site! This is obviously a major security
flaw, and a problem with the PHP's liberal use of globals
(at least until version 4.2). To overcome this, always use
$_SESSION["varname"]. If you do happen to be using
session_register() (and there are a lot of legacy sites out
there using it, which is why I keep mentioning it!), you could use
the session_is_registered() function. By checking whether
$access is registered as a session variable, rather than just
set, you can see if they really got access through page17.php, or
are trying something sneaky. By changing page18.php to the
following, you will prevent unwanted access. Destroy the
session and try again, with page18_2.php?access=1:
page18_2.php
<?php
session_start();
if ((session_is_registered("access")) && ($access == 1)) {
print "Welcome in to the secure site";
}
else {
print "Access not allowed!";
}
?>
Good luck with your sessions! With some care, they are a simple
and powerful tool in building dynamic websites that track state.
Additional Resources:
All of the scripts from this tutorial
Web Database Applications with PHP & MySQL
PHP
Session Management and Authentication with PHPLIB
Destroying Sessions and Session Variables
Maintaining state with PHP4 sessions
|