PHP Programming/Configuration: Register Globals

What is Register Globals?

edit

A common security problem with PHP is the register_globals setting in PHP's configuration file (php.ini). This setting (that can be either On or Off) tells whether or not to register the contents of the EGPCS (Environment, GET, POST, Cookie, Server) variables as global variables. For example, if register_globals is On, the url http://www.example.com/test.php?id=3 will declare $id as a global variable with no code required. Similarly, $DOCUMENT_ROOT would also be defined, since it is part of the $_SERVER 'superglobal' array. These two examples are the equivalent of placing the following code at the beginning of a script:

$id = $_GET['id'];
$DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT'];

This feature is a great security risk, and you should ensure that register_globals is Off for all scripts (as of PHP 4.2.0 this is the default, and as of 5.4.0 the setting has been removed completely). It's preferred to go through PHP Predefined Variables instead, such as the superglobal $_REQUEST. Even more secure is to further specify by using: $_ENV, $_GET, $_POST, $_COOKIE, or $_SERVER instead of using the more general superglobal $_REQUEST.

Example

edit

Let's say that this PHP code is on the receiving end of a form. The user has just entered an incorrect password. The $_POST array variable handles it. The code will describe that if the password is correct ("correct password" being, let's say, "12345"), the variable $admin will be set to TRUE. The site's configuration says that if $admin is set to TRUE, that user will have administrative privileges. This code is PHP5 compatible.

if (isset($_POST['password']) && $_POST['password'] == "12345") {
    $admin = TRUE;
}

register_globals does not discriminate between $_POST variables and $_GET variables. So, suppose the user input the form and it took him or her to that above page. The user could decide that he or she deserves admin privileges even though they do not know the password. So, that user could append ?admin=1 to the URL of that page. What that would do, with register_globals On, would be to force the creation the variable $admin and automatically set the value to 1, making it equivalent to TRUE. So register_globals On allows the user to inject variables and values into the program! Here, whether or not they input the correct password, the user would now have administrative privileges just by doing something with the URL.

As you can see, this sort of situation can happen at anytime by someone who does enough thinking to figure out how the page was coded. It could happen in many other situations.

Another example is that of sessions. When register_globals = on, we could also use $username in our example below but again you must realize that $username could also come from other means, such as GET (through the URL).

 // We wouldn't know where $username came from but do know $_SESSION is
 // for session data
 if (isset($_SESSION['username'])) {
     echo "Hello <b>{$_SESSION['username']}</b>";
 } else {
     echo "Hello <b>Guest</b><br />";
     echo "Would you like to login?";
 }

Best Practices

edit

The best way to avoid it is to make sure that register_globals is set to Off in your php.ini. But as a general coding recommendation, always initialize your variables. The following code makes a small addition to the previous code example, but first sets $admin to FALSE so that the user cannot get administrative privileges except via the conditional statement:

 $admin = FALSE;
 if (isset($_POST["password"]) && $_POST["password"] == "12345") {
     $admin = TRUE;
 }

filter_input()

edit

As the superglobal array access is vulnerable to the code injection[1], for security reasons, it's better to use the syntax with filter_input()[2]:

<?php
echo filter_input(INPUT_GET, 'password'); // good
echo $_GET['password'];                   // not good
?>

References

edit

More Information

edit