当前位置:首页 >> 网络通讯 >> 网络安全 >> 内容

php变量覆盖经验解说

时间:2015/5/19 18:40:47 作者:平凡之路 来源:xuhantao.com 浏览:

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

 

 

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

 涛涛电脑知识网

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

 

可以提交

 

updateinfo[amount]

这样的数组随意修改自己的余额、点数、会员组、VIP等一切存放在member表的信息.

 

修复:

 

$updateinfo = array();

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

 



 

里面说明了绕过程序的防御,这个是导致注入的一个因素. 更多因素是因为where变量没有初始化!

 

case 'list':

    $totalNum = $mysql->numTable("member", $where);

Where 没初始化 导致可执行任意sql语句

 

?action=list&where={sql}

修复:在类调用前加上

 

$where='';

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

 

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

 

 

// 这个地方获取用户注册信息,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)。

 

修复:像连接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);

?>

访问

 

?key=value

得到

 

array(1) { ["key"]=> string(5) "value" }

OK,看到这里应该明白了,$_GET就是个数组,我们用GET方法可以传一个数组。

 

再访问

 

?key[arr1]=value

得到

 

array(1) { ["key"]=> array(1) { ["arr1"]=> string(5) "value" } }

我们通过GET方法传入了一个嵌套数组。

 

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

 

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

 

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

 

提交一个嵌套数组:

 

/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!');

  • 徐汉涛(www.xuhantao.com) © 2024 版权所有 All Rights Reserved.
  • 部分内容来自网络,如有侵权请联系站长尽快处理 站长QQ:965898558(广告及站内业务受理) 网站备案号:蒙ICP备15000590号-1