Automatic initialization of variables is an excellent feature for simple scripts, but it has security and processing implications. If required, the automatic initialization can be turned off by setting register_globals=false
in the php.ini configuration file, usually found in the directory /usr/local/lib/. The php.ini file was copied to this location as part of the PHP installation instructions in Appendix A.
When the PHP script engine is invoked, the engine declares and initializes variables in a predefined order. The automatic initialization feature works in this order:
-
By default, environment variables are initialized first.
-
Variables are initialized from query string parameters passed with the
GET
method. -
POST
method parameters are initialized. -
Variables from cookies are initialized.
-
The Apache server internal variables are initialized.
The initialization order can be changed from the default by adjusting the variables_order
setting in php.ini. The security problem occurs when a user knowingly or inadvertently overrides a previously initialized variable. For example, the PATH
environment variable is one of the first initialized when the script engine is invoked. If a GET
request contains an attribute named PATH
, this overrides the environment variable of the same name, because GET
variables are initialized after environment variables. By understanding the initialization process, the user can override previously set variables by passing through parameters. This can change script behavior and possibly lead to a security problem.
If the register_globals
feature is turned off, a PHP script must use a different method to access user data. This method is more secure and requires that arrays be accessed to retrieve specific user parameters. For example, the GET
variables are stored in an associative array, $HTTP_GET_VARS
.
Consider the following URL that is requested by a user:
http://localhost/test.php?varname=value
The variable $varname
can be printed in a PHP script by accessing the associative array $HTTP_GET_VARS
using:
echo $HTTP_GET_VARS["varname"];
The only disadvantage of this approach is that the script is tailored for the GET
method. Changing the <form>
submission method from GET
to POST
requires modifying the script. All references to $HTTP_GET_VARS
must be replaced with references to $HTTP_POST_VARS
, because the array $HTTP_POST_VARS
stores all variables passed using the POST
method. However, the use of associative arrays is more secure because the script doesn't function if the user maliciously changes the <form>
submission method in an attempt to compromise the system.
We often initialize local variables at the beginning of a script from the contents of the $HTTP_GET_VARS
or $HTTP_POST_VARS
arrays. This emulates the register_globals
feature of PHP but without the security issues. Local variables make the code more attractive and readable. For example, the following code fragment initializes three variables from the contents of the $HTTP_GET_VARS
array:
$surname = $HTTP_GET_VARS["surname"]; $firstname = $HTTP_GET_VARS["firstname"]; $title = $HTTP_GET_VARS["title"];
The result is that the script behaves the same as if register_globals
is on. This also has the advantage that if the <form>
submission method is changed from GET
to POST
, the code need be modified only in one place.
Other external variables can be accessed similarly:
-
POST
variables can found in the array$HTTP_POST_VARS
. -
Cookie variables can be found in the array
$HTTP_COOKIE_VARS
. -
Environment variables can be found in the array
$HTTP_ENV_VARS
. -
Session variables can be found in the array
$HTTP_SESSION_VARS
. -
Server variables can be found in the array
$HTTP_SERVER_VARS
.
Cookies and sessions are discussed in Chapter 8.
We have set register_globals=true
in the online winestore application. However, the security implications of automatic initialization should be considered when designing any application.