6月2日DiscuzX 1.5 最新0day注入漏洞的排查原则

这个是老漏洞的新代码
注入者需要访问一次“/api/manyou/my.php” 可以根据这个特征进行查找

[bash]cat OOXX.access.log |grep '/api/manyou/my.php' |grep -v "myop/1.0"[/bash]

123.119.143.232 - - [03/Jun/2011:08:44:53 +0800] "POST /api/manyou/my.php HTTP/1.0" 200 150 "-" "-" "-"
180.126.47.28 - - [03/Jun/2011:12:30:12 +0800] "POST //api/manyou/my.php HTTP/1.0" 200 150 "-" "-" "-"
183.8.131.193 - - [03/Jun/2011:12:59:53 +0800] "POST /api/manyou/my.php HTTP/1.0" 200 150 "-" "-" "-"
113.90.0.27 - - [03/Jun/2011:13:20:56 +0800] "POST //api/manyou/my.php HTTP/1.0" 200 150 "-" "-" "-"
203.171.224.45 - - [03/Jun/2011:14:34:35 +0800] "POST /api/manyou/my.php HTTP/1.0" 200 150 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:47:26 +0800] "POST //api/manyou/my.php HTTP/1.0" 200 150 "-" "-" "-"

这些都是可疑IP记录 当然 对方也可能修改自己的UA,所以grep -v "myop/1.0"这个选项慎用

根据这些IP的访问记录进行筛选排查

比如我选择IP 180.126.47.28

[bash]cat OOXX.access.log |grep 202.104.248.100|grep php |more
[/bash]

..................................
202.104.248.100 - - [03/Jun/2011:14:48:36 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:36 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:36 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:36 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:37 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:37 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:37 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:37 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:38 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:38 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:38 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:41 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:41 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 245 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:48:42 +0800] "POST //api/trade/notify_credit.php HTTP/1.0" 200 2634 "-" "-" "-"
202.104.248.100 - - [03/Jun/2011:14:49:06 +0800] "GET //data/avatar/9/8/98c90fdce084c5ce811a98464244cc6f.php HTTP/1.1" 200 31 "-" "Mozilla/4.0 (compatible; MSIE
7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MALC; Maxthon 2.0)" "-"
..................................

可见他到这里注入成功了。
然后依次根据其他访问记录找出wenshell的位置。删除之

我今天被6个IP注入 好像有1个没成功 5个成功了。服务器上全是webshell =。=

已经发帖反馈,目前DiscuzX官方还没有出解决方案补丁,不知道想不想出了 反正我把notify_credit做掉了。先等等看再说了。


Update: 2011/6/4
经过在CG群里面的讨论,发现官方确实已经修复了这个问题,不过是悄悄的进村,打枪的不要的。
实际上notify_credit只是一个launcher,真正出问题的是notify_credit调用的腾讯财付通支付插件,api_tenpay.php
我对比了新旧文件,发现在逻辑上,代码只有在大约143行有如下不同:
老代码:

[php] foreach($_GET as $k => $v) {
$value = urldecode($v);
$this->setParameter($k, $value);
}
foreach($_POST as $k => $v) {
$value = urldecode($v);
$this->setParameter($k, $value);
}
}[/php]

新代码:

[php] foreach($_GET as $k => $v) {
$this->setParameter($k, $v);
}
foreach($_POST as $k => $v) {
$this->setParameter($k, $v);
}
}[/php]

去掉了urldecode。我还不是很理解,CG群里面的Zouzhe写道

urldecode是比较危险的,要慎用,或者不用,用base64encode或者自己写个加密函数都好。
假设用户在浏览器地址栏上输入%2527,就会被urldecode成单引号(%25 decode成%,%27 decode成'),从而绕过php.ini的magic_quotes_gpc = on的设置

下面是攻击代码节选:

[php] function send(){
global $host, $path, $tmp_expstr;

$expdata = "attach=tenpay&retcode=0&trade_no=%2527&mch_vno=".urlencode(urlencode($tmp_expstr))."&sign=".sign($tmp_expstr);
$data = "POST $path HTTP/1.1\r\n";
$data .= "Host: $host\r\n";
$data .= "Content-Type: application/x-www-form-urlencoded\r\n";
$data .= "Content-Length: ".strlen($expdata)."\r\n";
$data .= "Connection: Close\r\n\r\n";
$data .= $expdata;
$fp = fsockopen($host, 80);
fputs($fp, $data);
$resp = '';
while ($fp && !feof($fp))
$resp .= fread($fp, 1024);
return $resp;
} [/php]

Demon提到在PHP手册上,urldecode有个很显眼的warning:

Warning
The superglobals $_GET and $_REQUEST are already decoded. Using urldecode() on an element in $_GET or $_REQUEST could have unexpected and dangerous results.

那么他是怎么创建文件的呢?
对比新旧/api/manyou/my.php文件的大约690行可以找到答案:

旧my.php

[php] function onVideoAuthAuth($uId, $picData, $picExt = 'jpg', $isReward = false) {
global $_G;
$res = $this->getUserSpace($uId);
if (!$res) {
return new ErrorResponse('1', "User($uId) Not Exists");
}

$pic = base64_decode($picData);
if (!$pic || strlen($pic) == strlen($picData)) {
$errCode = '200';
$errMessage = 'Error argument';
return new ErrorResponse($errCode, $errMessage);
}

$secret = md5($_G['timestamp']."\t".$_G['uid']);
$picDir = DISCUZ_ROOT . './data/avatar/' . substr($secret, 0, 1);
if (!is_dir($picDir)) {
if (!mkdir($picDir, 0777)) {
$errCode = '300';
$errMessage = 'Cannot create directory';
return new ErrorResponse($errCode, $errMessage);
}
}

$picDir .= '/' . substr($secret, 1, 1);
if (!is_dir($picDir)) {
if (!@mkdir($picDir, 0777)) {
$errCode = '300';
$errMessage = 'Cannot create directory';
return new ErrorResponse($errCode, $errMessage);
}
}
[/php]

新my.php

[php] function onVideoAuthAuth($uId, $picData, $picExt = 'jpg', $isReward = false) {
global $_G;
$res = $this->getUserSpace($uId);
if (!$res) {
return new ErrorResponse('1', "User($uId) Not Exists");
}
$allowPicType = array('jpg','jpeg','gif','png');
if(in_array($picExt, $allowPicType)) {
$pic = base64_decode($picData);
if (!$pic || strlen($pic) == strlen($picData)) {
$errCode = '200';
$errMessage = 'Error argument';
return new ErrorResponse($errCode, $errMessage);
}

$secret = md5($_G['timestamp']."\t".$_G['uid']);
$picDir = DISCUZ_ROOT . './data/avatar/' . substr($secret, 0, 1);
if (!is_dir($picDir)) {
if (!mkdir($picDir, 0777)) {
$errCode = '300';
$errMessage = 'Cannot create directory';
return new ErrorResponse($errCode, $errMessage);
}
}[/php]

可见 这里多了一段针对创建文件类型的判断,解决了能创建任意类型的漏洞。所以如不不打补丁而且之前被黑的的话,去除notify_credit.php是没有用的,仍有可能利用已经被泄露的sitekey通过有漏洞的manyouAPI文件my.php进行shell植入。

到此真相大白.
整个过程就是这样的,先利用notify_credit的SQL注入漏洞获取manyou的sitekey ,然后利用manyou的API文件my.php的漏洞(视频认证漏洞),通过sitekey通信后,创建了任意类型的文件,达到挂马的目的。
DZ出过两次补丁包 不过后台一直没有提示有更新 直到6月2号凌晨攻击脚本泄漏到网上 DZ才在后台显示红色警告 通知站长,感觉DZ没有以前负责任 了。

Author Info :
  • From:6月2日DiscuzX 1.5 最新0day注入漏洞的排查原则
  • URL:https://blog.ihipop.com/2011/06/2484.html
  • Please Reserve This Link,Thanks!
  • 《6月2日DiscuzX 1.5 最新0day注入漏洞的排查原则》上有4条评论

    1. Pingback: 对 Discuz!云平台的限制 | Yculer 歪酷人-KIFS
    2. 高手说得很透彻,就是我现在不懂要怎么办?那个被植入的JS链接文件总是在页面头部代码里,到哪里去清除啊?

    发表回复

    您的电子邮箱地址不会被公开。 必填项已用 * 标注