faqts : Computers : Programming : Languages : PHP : Common Problems

+ Search
Add Entry AlertManage Folder Edit Entry Add page to http://del.icio.us/
Did You Find This Entry Useful?

24 of 27 people (89%) answered Yes
Recently 9 of 10 people (90%) answered Yes

Entry

Why are variables not passing from one web page to another? Even tho' PHP functions seem to work...

Jul 24th, 2003 20:26
Marek Moehling, Jens Clasen, Markus Smet,


With version 4.1.0 a new way of dealing with external variables was
introduced to PHP, the so called "autoglobals" or sometimes
"superglobals". From then on you could access every variable not 
defined
by your own script using the following arrays:
$_GET
$_POST
$_FILES
$_COOKIE
$_SESSION
$_SERVER
$_ENV
Those arrays are defined to be autoglobal, meaning them to be 
accessible
in every part of the script (e.g. functions, methods,...) without 
having
to be declared "global" as it formerly was the case. 
By now you can determine a variables origin directly be the array where
the corresponding value can be found in. If you for example want to 
read
information being stored in a cookie you'll find that in
$_COOKIE['cookie_name'].
The possibility to access variable directly by their name, not using 
the
autoglobals, can be given by activating the flag "register_globals"
in your php.ini and it was granted by default upto version 4.1.2.
Afterwards "register_globals" is turned off by default and you have to
use autoglobals instead.
You might now think about permanently re-activating "register_globals",
but be advised that this is not recommended for security reasons. If 
you
don't really know what you do, it's pretty likely to produce highly 
vulnerable script in case register_globals is turned on.
Let me give a short example, why register_globals might be a very bad
thing. Imagine you had a script to restrict access to certain users:
<?php
    // first_check.php
    // ---------------
    // NOTE: This example is NOT intended to be used if you 
    //       want your pages to be safe from beig seen by 
    //       possible aggressors.
    $login_name='MyName';
    $login_pass='MyPass';
    session_start();
    if(!isset($sess_login)){
        if(!(isset($action) && $action=='login')){
            // show login form:
            ?>
            <form action="<?php echo $PHP_SELF; ?>" method="post">
                Name:<input type="text" name="name" /><br />
                Pass:<input type="password" name="pass" /><br />
                <input type="hidden" name="<?php echo session_name();
?>" value="<?php echo session_id(); ?>" />
                <input type="submit" name="action" value="login" /> 
            </form>
            <?php
            exit;
        }else{
            if($login_name==$name && $login_pass==$pass){
                $sess_login=1;
                session_register('sess_login');
            }else
                die('Access denied!!');
        }
    }
?>
Require the script above on every page to be guarded, for example
like that one:
<?php
    // secure_page.php
    require('first_check.php');
    echo 'This content is intended to be safe from foreign sight!';
?>
Now try to access the second script using an URL like that:
http://www.domain.tld/secure_page.php?sess_login=1 and you'll see that
everybody guessing the right variable can access your secured content.
Now let's do the same assuming register_globals is turned off:
<?php
    // second_check.php
    // ---------------
    // NOTE: This is by no means a perfect login, but it's much
    //       safer than the one mentioned above!
    $login_name='MyName';
    $login_pass='MyPass';
    session_start();
    if(!isset($_SESSION['login'])){
        if(!(isset($_POST['action']) && $_POST['action']=='login')){
            // show login form:
            ?>
            <form action="<?php echo $_SERVER['PHP_SELF']; ?>"
method="post">
                Name:<input type="text" name="name" /><br />
                Pass:<input type="password" name="pass" /><br />
                <input type="hidden" name="<?php echo session_name();
?>" value="<?php echo session_id(); ?>" />
                <input type="submit" name="action" value="login" /> 
            </form>
            <?php
            exit;
        }else{
            if((isset($_POST['name']) &&
isset($_POST['pass']))&&($login_name==$_POST['name'] &&
$login_pass==$_POST['pass'])){
                $_SESSION['login']=1;
            }else
                die('Access denied!!');
        }
    }
?>
Again require the script above on every page to be guarded, for
example like that one:
<?php
    // secure_page2.php
    require('second_check.php');
    echo 'This content is intended to be safe from foreign sight!';
?>
Now try the same thing again:
http://www.domain.tld/secure_page2.php?sess_login=1 and the only thing
you'll see is a login form. For sure even the first example could 
easily
be changed into a much more secure login (e.g. using
session_is_registered()) but there are in fact too many login-systems
having this inbuilt vulnerability to disregard the security improvement
introduced by using autoglobals and therefore a direct link between a
value and its origin.
Agreeably there are situations where you might want to enable
register_globals, e.g. to use older scripts with a more up to date PHP
version. So if you need to do so anyway, there are two practicable
solutions available:
o import_request_variables()
  This function is thought to import GET, POST and COOKIE variables 
  into global scope, meaning making them availlable as if 
  "register_globals" was active.
  See http://www.php.net/import_request_variables for more information.
o .htaccess
  Another way is activating "register_globals" per directory in a
  .htaccess file. Simply place one off the following lines in your
  .htaccess file and "register_globals" will be active for the current
  directory and for all subdirectories.
  1. php_flag register_globals on
  2. php_value register_globals 1
But as already mentioned, it's much better to leave "register_globals"
untouched, since it is thought to prevent inexperienced programmers 
from
doing silly (or even unsafe) thing in their scripts. Additionally must
be mentioned, that it is not very likely, that there will always be a
switch to reactivate register_globals (though there was no final
decision made about that one, at least AFAIK)
P.S.: Please excuse my bad english - I'm no native speaker - and feel
free to correct any error or mispelling you might find.