介绍下 PHP 的变量覆盖
有几个 PHP 函数在不安全地使用时,极易引发变量覆盖漏洞
1. extract()
extract()
函数从一个数组中导入变量到当前的符号表。它会根据数组的键名创建同名的变量,并将键值赋给这些新变量
漏洞示例:
<?php $username = 'guest'; $password = '123456'; // 从 $_GET 中导入变量,但没有做任何过滤 extract($_GET); if ($username === 'admin' && $password === 'mypassword') { echo 'Login successful as admin!'; } else { echo 'Login failed.'; } ?>
在这个例子中,攻击者可以通过URL
?username=admin&password=mypassword
来覆盖$username
和$password
这两个变量,从而绕过身份验证安全建议: 使用
extract()
时,务必指定第二个参数$flags
为EXTR_SKIP
或EXTR_PREFIX_ALL
,以防止覆盖现有变量。例如:extract($_GET, EXTR_SKIP);
2. parse_str()
parse_str()
函数用于解析URL参数字符串,并将其作为变量导入到当前作用域
漏洞示例:
<?php $username = 'guest'; // 将请求的参数字符串解析为变量 parse_str($_SERVER['QUERY_STRING']); if ($username === 'admin') { echo 'Hello admin!'; } ?>
攻击者可以通过
?username=admin
来覆盖$username
变量安全建议: 始终将
parse_str()
的第二个参数设置为一个数组变量,这样解析的结果会存入该数组,而不是直接创建全局变量。例如:parse_str($_SERVER['QUERY_STRING'], $query_data);
3. import_request_variables()
这个函数在PHP 5.4.0 版本后被移除。它的功能是把 $_GET
、$_POST
或 $_COOKIE
中的变量导入到全局作用域。由于其固有的安全风险,不应再使用
4. $$
(双重美元符)
双重美元符是一种特殊的变量语法,它会将一个变量的值作为另一个变量的名称
漏洞示例:
<?php $name = 'default'; foreach ($_GET as $key => $value) { // 动态地创建变量名 $$key = $value; } echo "Hello, " . $name; ?>
如果URL为
?name=hacker
,$key
的值为name
,$value
的值为hacker
。那么$$key
实际上就是$name
,它的值被设置为hacker
。攻击者可以通过这种方式覆盖$name
变量安全建议: 避免在没有严格过滤的情况下使用双重美元符来动态创建变量