If you’re a PHP developer you know all about the register_globals directive and all the evilness that comes with it. You can probably skip this post, because I’d just like to explain to the rest of the people what it is about.

In PHP you have superglobal arrays, which stores information that is being passed to you either by the browser or the server. These arrays are:

  • $_COOKIE – stores information about cookies from the browser
  • $_GET – stores form information
  • $_FILES – stores information on files a user wants to upload to your server
  • $_POST – stores form information
  • $_SERVER – stores various information about the server
  • $_SESSION – stores session data

What register_globals does when it is on is create a variable for each of the items in those arrays. I.e. if you have $_GET['var'] it will create $var automatically.

Look at the following examples.

HTML Form:

<form method="post" action="script.php">
  <input type="text" name="var">
  <input type="submit">
</form>

If register_globals is on, you can access it like this:

echo "The value of the "var" control is $var";

With register_globals off, you need to access it like this:

echo "The value of the "var" control is ".$_POST['var'];

Here is example of how someone can exploit a script when register_globals is enabled, courtesy of Dreamhost:

$admin['user'] = 'foo';
$admin['pass'] = 'bar';
if($admin['user'] == $_GET['username'] AND $admin['pass'] == $_GET['password']) {
  /* Give administrator access */
}

When you first look at this, it all looks fine. It’s check for the username and the password, so it must be fine? Wrong.

Let’s say you access the page as page.php?admin=asdf

  • Because register_globals is on, $admin = ‘asdf’, because $_GET['admin'] = ‘adsf’
  • $admin['user'] = ‘foo’; sets the first char of ‘asdf’ to ‘f’
  • $admin['pass'] = ‘bar’; sets the first char of ‘fsdf’ to ‘b’
  • $admin['user'] == $_GET['username'] tests if ‘b’ == $_GET['username']
  • $admin['pass'] == $_GET['password'] tests if ‘b’ == $_GET['password']

To get administrator access to this page, you simply access it as page.php?admin=asdf&username=b&password=b. See how that can affect you badly? So repeat after me, register_globals are evil.

Another example:

session_start();
if ($logged_in) {
  /* give access to things */
}

In the above example, you can make use of the $_SESSION['logged_in'] variable that automatically makes $logged_in available. Now if you call that page as page.php?logged_in=1 $_GET['logged_in'] will also register $logged_in and over write it with value of 1. Note that this is dependent on the variable_order directive which dictates which value will overwrite which one, but I hope you can see that register_globals can be very evil.

Another reason to start avoiding to use register_globals is that in PHP6 there is no support for register_globals. You cannot turn it on, because it is not there.