register_globals
register_globals is no longer a security threat for MediaWiki (1.24+ required that it was disabled), and the functionality has been removed from all PHP versions supported by current MediaWiki versions. |
This page is obsolete. It is being retained for archival purposes. It may document extensions or features that are obsolete and/or no longer supported. Do not rely on the information here being up-to-date. |
Overview
[edit]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.
Example
[edit]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.
Disabling Register Globals
[edit]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.
Protecting MediaWiki from Register Globals
[edit]Do not use global variables in script paths
[edit]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' );
Make sure code is only executed in the right context
[edit]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' ) ) {
die( 'Not a valid entry point.' );
}
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. This boilerplate is unnecessary for files that only contain classes.
Sanitize custom global variables before use
[edit]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
$myExtPath
in$myExtPath/CommonFunctions.php
unless we also set it in this file.
<?php
if ( !defined( 'MEDIAWIKI' ) ) exit;
$myExtPath = "$IP/extensions/MyExtension";
require( "$myExtPath/CommonFunctions.php" );
...
Configure extensions only after their setup file is included
[edit]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
See also
[edit]- Using Register Globals - The php.net page on why you shouldn't use register globals.