通常将可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞。经常导致变量覆盖漏洞场景有:$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。

0×01 $$导致的变量覆盖问题

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,如以下的示例代码,使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。

<?php

//?name=test

//output:string(4) “name” string(4) “test” string(4) “test” test

$name=’thinking’;

foreach ($_GET as $key => $value)

    $$key = $value;

    var_dump($key);

    var_dump($value);

    var_dump($$key);

echo $name;

?>

CTF中$$导致的变量覆盖问题的例题1:

题目源码:

<?php

include “flag.php”;

$_403 = “Access Denied”;

$_200 = “Welcome Admin”;

if ($_SERVER["REQUEST_METHOD"] != “POST”)

    die(“BugsBunnyCTF is here :p…”);

if ( !isset($_POST["flag"]) )

    die($_403);

foreach ($_GET as $key => $value)

    $$key = $$value;

foreach ($_POST as $key => $value)

    $$key = $value;

if ( $_POST["flag"] !== $flag )

    die($_403);

echo “This is your flag : “. $flag . “\n”;

die($_200);

?>

题目分析:

源码包含了flag.php文件,并且需要满足3个if里的条件才能获取flag,题目中使用了两个foreach并且也使用了$$.两个foreach中对 $$key的处理是不一样的,满足条件后会将$flag里面的值打印出来,所以$flag是在flag.php文件文件中的。

但是由于第7,11-14行间的代码会将$flag的值给覆盖掉了,所以需要先将$flag的值赋给$_200或$_403变量,然后利用die($_200)或 die($_403)将flag打印出来。

解题方法:

由于第7,11-14行间的代码会将$flag的值给覆盖掉,所以只能利用第一个foreach先将$flag的值赋给$_200,然后利用die($_200)将原本的flag值打印出来。


最终PAYLOAD:

GET DATA:?_200=flag

POST DATA:flag=aaaaaaaaaaaaaaaaaaaaa

0×02 extract()函数导致的变量覆盖问题

extract() 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

extract()的用法参考:http://www.runoob.com/php/func-array-extract.html

语法: extract(array,extract_rules,prefix)

CTF中extract()导致的变量覆盖问题的例题1:

题目源码:

<?php

$flag = ‘xxx’;

extract($_GET);

if (isset($gift)) {

    $content = trim(file_get_contents($flag));

    if ($gift == $content) {

        echo ‘hctf{…}’;

    } else {

       echo ‘Oh..’;

    }

} 
 ?>

题目分析:

题目使用了extract($_GET)接收了GET请求中的数据,并将键名和键值转换为变量名和变量的值,然后再进行两个if 的条件判断,所以可以使用GET提交参数和值,利用extract()对变量进行覆盖,从而满足各个条件。

解题方法:

GET请求 ?flag=&gift=,extract()会将$flag和$gift的值覆盖了,将变量的值设置为空或者不存在的文件就满足$gift == $content。

最终PAYLOAD:

GET DATA: ?flag=&gift=

CTF中extract()导致的变量覆盖问题的例题2:

题目源码:

<?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提交数据,extract($_POST)会将POST的数据中的键名和键值转换为相应的变量名和变量值,利用这个覆盖$pass和$thepassword_123变量的值,从而满足$pass == $thepassword_123这个条件。

解题方法:

使用POST请求提交pass=&thepassword_123=, 然后extract()会将接收到的数据将$pass和$thepassword_123变量的值覆盖为空,便满足条件了。

最终PAYLOAD:

POST DATA:pass=&thepassword_123=

0×03 parse_str函数导致的变量覆盖问题

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

语法:parse_str(string,array)

parse_str() 用法参考:http://php.net/parse_str

CTF中parse_str()导致的变量覆盖问题的例题1:

题目源码:

<?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(‘其实很简单其实并不难!’);

    }

}

?> 

题目分析:

首先要求使用GET提交id参数,然后parse_str($id)对id参数的数据进行处理,再使用判断$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)的结果是否为真,为真就返回flag,md5(‘QNKCDZO’)的结果是0e830400451993494058024219903391由于此次要满足$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)所以要利用php弱语言特性,0e123会被当做科学计数法,0 * 10 x 123。所以需要找到一个字符串md5后的结果是0e开头后面都是数字的,如,240610708,s878926199a

PHP处理0e开头md5哈希字符串缺陷/bug

解题方法:

使用GET请求id=a[0]=240610708,这样会将a[0]的值覆盖为240610708,然后经过md5后得到0e462097431906509019562988736854与md5(‘QNKCDZO’)的结果0e830400451993494058024219903391比较都是0 所以相等,满足条件,得打flag。

最终PAYLOAD:

GET DATA:

?id=a[0]=s878926199a

or

?id=a[0]=240610708

0×04 小总结

变量覆盖漏洞在PHP代码审计中会以比较隐晦的方式存在,所以需要更加仔细的阅读源码找出漏洞的点,在CTF里面经常是以比较直接方式展示,所以可以先通过学习CTF各种变量覆盖的题目,然后掌握后再去审计cms,这样可以更加通透的理解掌握和挖掘变量覆盖漏洞。

最新文章

  1. json是个啥东东
  2. 面试问题2:给一个5G的大文件,保存的数据为32位的整型,找到所有出现次数超过两次的数字
  3. 一次APP测试的感悟
  4. Java-继承,多态-0922-04
  5. TO~亲爱的自己
  6. linux 重命名文件和文件夹
  7. 单元最短路径算法模板汇总(Dijkstra, BF,SPFA),附链式前向星模板
  8. Android软件开发之发送短信与系统短信库解析
  9. CodeForces 221(div 2)
  10. android官方侧滑菜单DrawerLayout详解
  11. MVC源码分析 - 路由匹配
  12. Solr 01 - 什么是Solr + Solr安装包目录结构说明
  13. Django系列之web应用与http协议
  14. php实现最简单的MVC框架实例教程
  15. C++ 内链接 外链接
  16. 几种RAID介绍(总结)
  17. Java中List详解
  18. 批处理文件(Batch Files )
  19. 【Android】6.0 第6章 对话框--本章示例主界面
  20. OCX组件

热门文章

  1. kafka对消费者分配分区规则(Java源码)
  2. android 百度地图入门01 (史上最详没有之一)
  3. apache ignite系列(二):配置
  4. C#加载前生成静态网页
  5. 树莓派3安装openwrt
  6. python正则表达式字符记录
  7. ASP.NET Core 3.0 gRPC 双向流
  8. lvm创建逻辑卷技巧
  9. Android Studio [相对布局RelativeLayout]
  10. intellij idea 2018 激活