CWE-473, PHP External Variable Modification, describes a PHP application that does not protect its variables from modification by external sources such as query parameters or cookies. That opens the door to many weaknesses that would not otherwise exist.
The history matters here. Older PHP setups had a feature called register_globals, which turned request values into ordinary variables. A variable the developer meant to set internally could be set by anyone who added it to a URL. MITRE's mitigation guidance still names it directly.
How it happens
A script checks a variable that it believes it initialized, but a code path leaves it unset. If globals can be filled from the request, the attacker supplies it.
<?php
// Vulnerable when request values can become variables
if (check_password($user, $pass)) {
$authorized = true;
}
if ($authorized) {
show_admin_panel();
}
If $authorized is never initialized and a request can set it, then ?authorized=1 skips the login. Even without register_globals, code that copies request data into the variable scope through custom extraction can bring the same hole back.
MITRE lists four observed cases. CVE-2000-0860: a file upload allows arbitrary file read by setting hidden form variables that match internal variable names. CVE-2001-0854: the script trusts the PHP_SELF variable to decide whether an include was called by its parent. CVE-2002-0764: PHP remote file inclusion through a modified assumed-immutable variable. CVE-2001-1025: modifying a key variable when calling scripts that do not load the library that initializes it.
What an attacker gains
The record lists the ability to modify application data. In the cases above that grew into file reads, remote file inclusion and bypassed checks, because one overwritten variable fed a more dangerous operation.
How to find it
MITRE does not list detection methods for this entry. Practical checks: look at your PHP configuration for register_globals style behavior, search for code that extracts request arrays into local variables, and read every security decision to confirm the variable was assigned on every path before it is tested.
How to fix it
MITRE's guidance has four points.
- Identify which variables can be controlled or influenced by an external user. Consider a naming convention that makes externally modifiable variables obvious.
- Be reluctant to trust any variable initialized outside your trust boundary, and check inputs thoroughly.
- Do not run with register_globals enabled.
- If you write an emulator for register_globals, take great care with variable extraction and dynamic evaluation. Flaws there allow the same modification even with the setting off.
Add one habit of your own: initialize every security relevant variable at the top of its scope, with the safe value.
<?php
$authorized = false; // safe default, set before any logic
if (check_password($user, $pass)) {
$authorized = true;
}
Quick check
Does turning off register_globals fully fix this?
It removes the main route, but custom code that extracts request data into variables can recreate it. Initialize variables and read input from the explicit request arrays.