某友PHP代码审计+下版本漏洞预测
2023-8-25 07:51:41 Author: 白帽子(查看原文) 阅读量:76 收藏

前言:前段时间热度挺高的一个系统存在SQL注入漏洞,升级后漏洞被修复了。

开始前先对比了一下两个版本的PHP代码,关键代码没进行修改,没有对单引号进行转义,也没有使用自动转义函数,但是GET、POST、REQUEST传参还是被转译了。

下面请允许我水一篇。

0x01 问题描述

测试环境如下:

172.28.113.153(2)

192.168.100.130(3)

测试代码 <?php echo $_GET[1];

在2中未对传入参数值做任何处理。

在3中的传入参数值,未进行手动转义、未加入自动转义函数,但是,参数值还是自动被传译了。

查看了7.0.3.1的PHP版本是5.3.5,想到magic_quotes_gpc还没被移除(从PHP5.4开始就已经被移除了),使用phpinfo查看发现是果然是开启状态。

然鹅7.0.2.1的PHP版本为5.6.40,升级到7.0.3.1后,PHP版本却降到了5.3.5🤣

其他猜测:如果代码中没有对单引号进行转义,也没有使用自动转义函数,magic_quotes_gpc等选项也已经关闭,GET、POST等传参还是被转译。

还有可能是其他扩展或模块(如:Suhosin扩展、mbstring模块)引起的,如果该环境的PHP程序是自己编译的,也可能是编译选项导致了单引号被转义。

0x02 magic_quotes_gpc

先确定一下magic_quotes_gpc的影响范围。

测试一手,毕竟要以实物为准嘛。

SESSION(无意义),SERVER、php://input($HTTP_RAW_POST_DATA)不受影响。

0x03 $HTTP_RAW_POST_DATA

上面做的事情是为了解决,升级后增加了magic_quotes_gpc限制,寻找有没有什么方法可以绕过转译。

找到了$HTTP_RAW_POST_DATA,发现Exxxxxxxx.XGI文件中出现过多次。

选择一个最近的137行,发现刚好下方有拼接的SQL语句,且语句中的可控点在$HTTP_RAW_POST_DATA中。

那么我们先让cmd等于"createUser"好通过if ($cmd == "createUser")判断,往上找发现103行$cmd通过$requestObj['command']赋值。

辣么,就是说。。。我们只需要让$requestObj['command'] == "createUser",继续往上看,89-95行是处理$requestObj的代码,可以看到其实$requestObj的键值是从$paramArr中得到的。

分析一下这段代码的逻辑,其实就是循环取$paramArr的键值,然后使用explode函数把$value通过"_"分割打散为数组,并赋值给$keyValue,然后把$keyValue[0]赋值给$requestObj当作键名,$keyValue[1]作为值赋给$requestObj[$keyValue[0]]。

explode函数实例:

回头看条件,其实只需要让$requestObj['command'] == "createUser"成立

就等于让$paramArr的value等于"command_createUser"就好了。(key在循环中没参与处理不需要管)

然后explode函数把"command_createUser"通过"_"分割打散为数组,就成了$keyValue = array('command' => 'createUser'),$keyValue[0]就等于"command",$keyValue[1]就等于"createUser",$requestObj[$keyValue[0]]就等于"createUser"了。

继续往上看$paramArr,在83行进行处理并赋值,通过$initparams处理后得到,与上方$requestObj同理。

继续往上看$initparams,在21行通过initParams传入。

条件都可控,尝试构造请求,提示参数非法。

原因是59行存在参数是否为空的判断。

加上参数,继续构造请求,还是提示参数非法。

往下看发现71行对$keyVal有限制,但是可以通过$key控制,就是需要$key == "wusuokey" || $key == "inner",这里就不看getfarminfo方法了(悄悄说一下这里上个版本可以getshell噢),这里直接给$key赋值为"inner",让$keyVal = "Realor"。

还有78行对sign的值有限制,就是需要让$sign == md5($initparams . $keyVal)

很简单,把传入的$initparams和$keyVal拼接起来进行md5加密就好了。

构造请求包,让$cmd等于createUser,通过了if判断,离注入就剩几行了。

这时$account还没传值所以上一步报错,接着看json_decode($HTTP_RAW_POST_DATA, true);给$account传值。

PHP json_decode() 函数用于对 JSON 格式的字符串进行解码,并转换为 PHP 变量。 

好了直接构造数据包,记得把Content-Type改一下。

成功通过mysql_query,因为是通过$HTTP_RAW_POST_DATA传进来的,所以不会被magic_quotes_gpc限制,后面的话dddd,这里就不演示了(小提示:有32个字段;这里写shell是可以用相对路径的../../WebRoot/shell.xgi😅)。

0x04 下版本漏洞预测

毕竟json_decode($HTTP_RAW_POST_DATA, true);的地方不多,刚好又看到一个有意思的函数utf8ToGbk😅,注入经验丰富的师傅看到这可能就猜到下文了

就随便找个了利用点,让 $cmd=getUserDetailByAccount,与上方前半段手法一样不赘述了。

开个上帝模式先。

构造数据包,确认注入点。

单引号肯定不行啊,直接转译。

那咋办么,utf8ToGbk嚒,直接運一下,结束。

!提示:注意一下上面的md5加密,这里单引号传进入已经被转译了,所以要加密的是\'

说明:由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,及文章作者不为此承担任何责任。拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMDQwNTE5MA==&mid=2650246939&idx=1&sn=a8bd476bbc94237efaefd47727b423ad&chksm=82ea54b2b59ddda4e189102d8b8094168ce12915018132a3a259f0b16a007417ea1b76f2e7e2&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh