Explain this PHP Please

Associate
Joined
26 Jun 2003
Posts
1,140
Location
North West
PHP:
// 'Register globals off' protection
if (is_array($_POST)) foreach($_POST as $key=>$value) unset($$key);
if (is_array($_GET))  foreach($_GET  as $key=>$value) unset($$key);

I know its useful protect against register global stuff, so I looked for ways to do it and came accross this method.

Can someone explain each section bit by bit. Im not understanding the $key=>$value bit and also the $$key. Why two $?

Thx
 
It helps to understand what register_globals does. You can effectively replicate register_globals's functionality by doing this:

Code:
foreach( $_REQUEST as $key => $val )
    $$key = $val;

That is, for every variable in the $_GET and $_POST arrays, create a variable with the respective name and value; so $_GET['foo'] would be accessible as $foo.

So in this instance, it's just doing the opposite; looping through the $_GET and $_POST arrays and unsetting global variables with the same name if they exist, the reverse of what register_globals does.

That said, it's perfectly fine to have register_globals turned on, just don't code like a retard; you should always initialise your variables manually, particularly ones you use for security purposes.
 
What it's doing is unsetting any variables which also exist in POST/GET.

So say you have this...

GET page.php?foo=bar

If you have register_globals on, you can write your script like this:

Code:
echo $foo;
And it'll print "bar" to the screen. If you have register_globals off, it'll print nothing, because you need to use $_GET['foo'].

The PHP in your post is useful if people can't use .htaccess files to turn off register_globals:
Code:
php_flag register_globals Off

The $key => $value method is a way of accessing parts of the array in a foreach() loop.

Say you set an array up like this....

Code:
$array = array("a" => "foo", "b" => "bar);
That's setting the key of the array to "a" and the value of that entry to "foo", and the same for the second part. So in the foreach() you can say:

Code:
foreach($array as $key => $value){
echo "I am at part $key of the array which has the value $value";
}
Which would print to the screen:
"I am at part a of the array which has the value foo" (and then do the same for part b as foreach() does what it says on the tin).

The double-dollar is the cool part. Variable variables! They take the value of the variable and use it as the name of the variable. In English, actually, the PHP manual explains it better than I could.

So after having read that, you'll see that it's taking the name of the variable's key as the name of a variable and un-setting it (ie giving it no value).

This is un-doing register_globals because register_globals creates variables and gives them the value sent through GET or POST.

So in a nutshell it's saying "for each variable which was passed by get or post, set its value to nothing" - so if you have register_globals on and[/i] run those two lines of code then you'll still need to use $_GET['foo'] to access the variable, because register_globals has been reversed :)

/sore fingers
 
Well register_globals by itself is not a security issue. What is, however, is code that is safe with register globals turned off, but vulnerable with it turned on (ie badly written code).

Consider the following:

Code:
<?php

session_start();

if( log_in($_POST['username'], $_POST['$password']) )
    $authorised = true;

if( $authorised ) {
    $_SESSION['loggedin'] = true;
    header('Location: loggedin.php');
    die;
}

?>

With register_globals turned off, this code is safe (although still badly written); $authorised will only be set when log_in() returns true.

However, with register_globals turned on, all a user needs to do is pass &authorised=1 in the query string and he will be granted full access.

To avoid this in this particular instance, all you need to do is presume the user isn't logged in to start of with, then check if he is:

Code:
<?php

session_start();

$authorised = false;

if( log_in($_POST['username'], $_POST['$password']) )
    $authorised = true;

if( $authorised ) {
    $_SESSION['loggedin'] = true;
    header('Location: loggedin.php');
    die;
}

?>

By explicitly setting $authorised to false at the start of the script, we guarantee that the user will not be logged in unless log_in() returns true.
 
Beansprout said:
The PHP in your post is useful if people can't use .htaccess files to turn off register_globals:
Code:
php_flag register_globals Off
It actually looks more like it's from a distributed app, and the developer has added this part of the code as a bodged failsafe for the app :)
 
Back
Top Bottom