变量覆盖漏洞学习


变量覆盖

定义

  • 可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞

主要情形

  • $$使用不当
  • extract()函数使用不当
  • parse_str()函数使用不当
  • import_request_variables()使用不当
  • 开启全局变量注册
  • ……

$$使用不当

1. 定义

  • 一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。

2. 漏洞产生

  • 使用foreach遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。
<?php
foreach ($_GET as $key => $value) {
${$key} = $value;
}
echo $a;
?>

如上代码,把GET得到的$key作为新变量的变量名把GET得到的$value赋值给它

GET ?a=1 第3行回解析为$a=1。就造成了变量覆盖

//例题
<!--foreach($_GET as $key => $value){  
        $$key = $value;  
}  
if($name == "meizijiu233"){
    echo $flag;
}-->

poc:
?name = meizijiu233


extract()使用不当

1. 定义

  • extract() 函数从数组中将变量导入到当前的符号表。
  • 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。该函数返回成功设置的变量数目

2. 语法

extract(array,extract_rules,prefix)
参数 描述
array 必需。规定要使用的数组。
extract_rules 可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。
prefix 可选。如果 extract_rules 参数的值是 EXTR_PREFIX_SAME、EXTR_PREFIX_ALL、 EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS,则 prefix 是必需的。
  • 从以上说明我们可以看到第一个参数是必须的,会不会导致变量覆盖漏洞由第二个参数决定

3. 例子

    <?php if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
        <?php
        extract($_POST);
        if ($pass == $thepassword_123) { ?>
            <div class="alert alert-success">
                <code><?php echo $theflag; ?></code>
            </div>
        <?php } ?>
    <?php } ?>

题目意思是要POST一个pass数据,extract($_POST)会将POST的数据中的键名和键值转换为相应的变量名和变量值,利用这个覆盖$pass和$thepassword_123变量的值,从而满足$pass == $thepassword_123这个条件。

POC:

pass=&thepassword_123=   //用POST传入

parse_str()使用不当

1. 定义

  • parse_str() 函数用于把查询字符串解析到变量中,如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量。

2. 语法

parse_str(string,array)
参数 描述
strings 必需。规定要解析的字符串
array 可选。规定储存变量的数组名称。该参数指示变量将被存储到数组中。

3. 例子

<?php

error_reporting(0);

if (empty($_GET['id'])) {

    show_source(__FILE__);

    die();

} else {

    include (‘flag.php’);

    $a = “www.OPENCTF.com”;

    $id = $_GET['id'];

    @parse_str($id);

    if ($a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)) {

        echo $flag;

    } else {

        exit(‘其实很简单其实并不难!’);

    }

}

?>

分析:

  1. 首先要求使用GET提交id参数,然后parse_str($id)对id参数的数据进行处理

  2. 再使用判断$a[0] != ‘QNKCDZO’&&md5($a[0]) == md5(‘QNKCDZO’)的结果是否为真,为真就返回flag

  3. md5(‘QNKCDZO’)的结果是0e830400451993494058024219903391由于此次要满足$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)

  4. 所以要利用php弱语言特性,0e123会被当做科学计数法,0*10x123。所以需要找到一个字符串md5后的结果是0e开头后面都是数字的,如,240610708,s878926199a

POC:

?id=a[0]=s878926199a //?id=a[0]=240610708

文章作者: Doublenine
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Doublenine !
 上一篇
代码审计学习(一) 代码审计学习(一)
代码审计学习(一)PHP核心配置首先需了解 PHP_INI_* 常量的定义 常量 含义 PHP_INI_USER 可在用户的php脚本或者windows注册表中设置 PHP_INI_PERDIR 可在php.ini .h
下一篇 
PHP数组绕过 PHP数组绕过
PHP数组绕过绕过strops()函数1. strops()定义: strpos() 函数查找字符串在另一字符串中第一次出现的位置。 strpos() 函数对大小写敏感。 2. strops()语法: strpos(string,f
  目录