变量覆盖

0x01 变量覆盖

变量覆盖是指可以用我们自定义的参数值替换程序原有的变量值。变量覆盖漏洞通常需要结合程序的其他功能来实现完整的攻击。
变量覆盖漏洞大多由于函数使用不当造成的,经常引发变量覆盖漏洞的函数有extract()函数,parse_str()、import_request_variables()函数在没有开启全局变量注册的时候,调用了这个函数相当于开启了全局变量注册。

0x02 变量覆盖函数

2.1、全局变量覆盖

$GLOBALS, 所有全局变量数组
$_SERVER, 服务器环境变量数组
$_GET,通过GET方法传递给脚本的变量数组
$_POST, 通过POST方法传递给脚本的变量数组
$_COOKIE,cookie变量数组
$_REQUEST,所有用户输入的变量数组,包括$_GET, $_POST和$_COOKIE所包含的输入内容
$_FILES,与文件上传相关得变量数组
$_ENV,环境变量数组
$_SESSION,会话变量数组

2.1、遍历初始化变量

<?php
    $a='hello';
    foreach($_GET as $key => $value{
        $$key = $value;
    }
 print $a;
 ?>


在代码审计时需要注意类似“$$k”的变量赋值方式有可能覆盖已有的变量,从而导致一些不可控制的结果。

2.2、parse_str()变量覆盖

<?php
$var='Hello';
parse_str($_SERVER['QUERY_STRING']);
print $var;
?>


与parse_str()类似的函数还有mb_parse_str(),parse_str — 将字符串解析成多个变量,如果参数str是URL传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域。

2.3、import_request_variables()变量覆盖

<?php  
$a = '0';  
import_request_variables('G');  

if($a == 1){  
  echo "true!";  
}else{  
  echo "false!";  
}  
?> 


import_request_variables(),将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。

2.4、extract()变量覆盖

<?php  

$a = '0';  
extract($_GET);  

if($a==1){  
echo "true!";  
}else{  
echo "false!";  
}  
?> 

假设构造以下链接:http://www.a.com/1.php?a=1时,界面上会打印出true!
安全的做法是确定register_globals=OFF后,在调用extract()时使用EXTR_SKIP保证已有变量不会被覆盖。
PHP extract() 函数从数组中把变量导入到当前的符号表中。对于数组中的每个元素,键名用于变量名,键值用于变量值。

0x03 挖掘经验

只要搜索敏感函数,然后回溯函数是否可控,当然也可以通过搜索”$$”关键字去挖掘。

0x04 漏洞防范

1、使用原始变量
最直接方法就是不进行变量注册,直接使用原生的$_GET、$_POST等数组变量进行操作;
2、验证变量存在
注册变量前判断变量是否存在。最重要的一点,自行申明的变量一定要初始化,不然即使注册变量代码在执行流程最前面也能覆盖掉这些未初始化的变量。