Register globals
Contents |
[edit] Overview
Register globals is a deprecated feature of PHP. The feature causes data passed to a PHP script via cookies or GET and POST requests to be made available as global variables in the script.
Register globals is convenient but extremely dangerous, often allowing an attacker to overwrite variables in a script simply by adding parameters to requests. While the feature has been disabled by default since PHP 4.2.0 (which was released April 22, 2002), hosting providers often enable the feature to provide compatibility with old scripts.
[edit] Example
Here's a simple example of how register globals can present a security risk. The following PHP fragment is written with the expectation that $file will set by a user submitting an HTML form containing a <select name="file"><option>file1</option><option>file2</option><option>...</option></select> tag.
<?php # ... # display the file specified by the <select name="file">...</select> form element readfile( '/path/to/file/dir/' . $file ); # ...
Forcing the script to display a sensitive file containing passwords is simply a matter of making a GET request. For example, the following request could cause the script to display the contents of LocalSettings.php:
http://example.com/example.php?file=../../../../../var/www/mediawiki/LocalSettings.php
While this would seem to rely on detailed knowledge of the server's file system, it is fast and easy to write scripts that explore many different paths very quickly.
[edit] Disabling Register Globals
When possible, ensure that register globals is disabled by setting register_globals to off in your php.ini file.
In cases where you cannot edit your php.ini file (or cannot disable the feature globally), you may still be able to disable the feature via your web server's configuration files. Note that register_globals cannot be set at runtime using PHP's ini_set() function.
For the Apache Web Server, use the php_flag directive in a .htaccess file to disable register globals on a per-directory tree basis.
php_flag register_globals off
Then use phpinfo() to confirm that ini_get() is set to off.
A detailed tutorial on the use of .htaccess files is outside of the scope of this documentation. For further information, read Apache Tutorial: .htaccess files.
[edit] Protecting MediaWiki from Register Globals
[edit] Do not use global variables in script paths
It is best to avoid using global variables in script paths. You'll be happier because your code reviewers will be happier and your code will have fewer vulnerabilities.
<?php // Get common functions require( dirname(__FILE__).'/CommonFunctions.php' );
[edit] Make sure code is only executed in the right context
If for some reason it's absolutely necessary to use a global variable like this, you can protect it using some boilerplate code, present in many extensions:
<?php if ( !defined( 'MEDIAWIKI' ) ) { echo "Not a valid entry point"; exit( 1 ); } require( "$IP/extensions/MyExtension/CommonFunctions.php" ); ...
This ensures that the code can only be executed after MediaWiki is initialised. You can be sure that MediaWiki will set the $IP variable when it initialises.
[edit] Sanitize custom global variables before use
Ensuring that code is executed in the correct context will only protect MediaWiki's default variables from register globals. Custom global variables will not be protected. In the following example, if register globals is enabled an attacker could still overwrite $myExtPath.
<?php if ( !defined( 'MEDIAWIKI' ) ) exit; if ( !isset( $myExtPath ) ) { $myExtPath = "$IP/extensions/MyExtension"; } require( "$myExtPath/CommonFunctions.php" ); ...
If you must use a custom global variable (like $myExtPath in the example above), ensure that it is initialized with a default value and is not used across include() or require().
We could make the above example safer by:
- ensuring that the script always sets
$myExtPath; and - not using
$myExtPathin$myExtPath/CommonFunctions.phpunless we also set it in this file.
<?php if ( ! defined( 'MEDIAWIKI' ) ) exit; $myExtPath = "$IP/extensions/MyExtension"; require( "$myExtPath/CommonFunctions.php" ); ...
[edit] Configure extensions only after their setup file is included
Because MediaWiki uses global variables for its configuration namespace, this means that all extensions must be configured in LocalSettings.php after their setup file is included.
<?php $kittyCatName = 'Yoshi'; // set this here to avoid register_globals vulnerabilities function writeKittyName() { global $wgOut; global $kittyCatName; // definitely safe $wgOut->addHTML( htmlspecialchars( $kittyCatName ) ); }
In LocalSettings.php
require( "$IP/extensions/KittyCat/KittyCat.php" ); // sets default variables $kittyCatName = 'Puss'; // override the default
[edit] See Also
- Using Register Globals - The php.net page on why you shouldn't use register globals.