PHP

How PHP Initializes Variables

As we have discussed throughout this section, variables are automatically initialized by PHP from the parameters passed in an HTTP request.

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:

  1. By default, environment variables are initialized first.

  2. Variables are initialized from query string parameters passed with the GET method.

  3. POST method parameters are initialized.

  4. Variables from cookies are initialized.

  5. 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.