从 XSS Payload 学习浏览器解码
字数 1911 2025-08-26 22:11:57
从XSS Payload学习浏览器解码机制
基础知识
浏览器在处理XSS攻击向量时涉及多种解码机制,主要包括HTML解码、URL解码和JavaScript Unicode解码。理解这些解码顺序和规则对于防御和利用XSS漏洞至关重要。
解码机制详解
1. HTML解码
HTML实体编码(如j或j表示字母"j")会在HTML解析阶段被解码。这种编码主要用于在HTML中显示特殊字符而不干扰DOM解析。
关键点:
- 在普通元素(如
<div>)中,HTML实体会被解码 - 在RCDATA元素(
<textarea>和<title>)中,HTML实体也会被解码,但不会解析子元素 - 在原始文本元素(
<script>和<style>)中,HTML实体不会被解码
2. URL解码
URL编码(如%61表示字母"a")在URL属性(如href)中被处理。
关键点:
- URL的协议部分(如
javascript:)必须是ASCII字符,编码后的协议不会被识别 - URL解码发生在HTML解码之后
- 只有特定属性(如
href、src等)会触发URL解码
3. JavaScript Unicode解码
JavaScript支持Unicode转义序列(如\u0061表示字母"a")。
关键点:
- 仅适用于字符串字面量和标识符(如函数名、变量名)
- 不能用于其他语法元素(如引号、括号等)
- 在字符串中的Unicode转义会被解码为相应字符
案例分析
基础案例
-
URL编码的javascript协议
<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29"></a>- 结果:不执行
- 原因:URL协议部分必须是ASCII,编码后的"javascript"不被识别
-
HTML实体编码的javascript协议
<a href="javascript:%61%6c%65%72%74%28%32%29">- 结果:执行
- 原因:HTML解码后得到可识别的javascript协议,然后URL解码执行
-
URL编码的冒号
<a href="javascript%3aalert(3)"></a>- 结果:不执行
- 原因:同案例1,协议部分被编码
-
HTML实体编码的标签
<div><img src=x onerror=alert(4)></div>- 结果:不执行
- 原因:HTML编码用于显示特殊字符,不会创建DOM元素
5-6. textarea中的脚本
<textarea><script>alert(5)</script></textarea>
<textarea><script>alert(6)</script></textarea>
- 结果:都不执行
- 原因:RCDATA元素只显示文本,不解析子元素
进阶案例
-
HTML实体编码的属性值
<button onclick="confirm('7');">Button</button>- 结果:执行
- 原因:属性值先HTML解码,然后作为JS执行
-
JS Unicode编码的引号
<button onclick="confirm('8\u0027);">Button</button>- 结果:不执行
- 原因:JS中引号不能用Unicode表示
-
script中的HTML实体
<script>alert(9);</script>- 结果:不执行
- 原因:原始文本元素不进行HTML解码
-
JS Unicode编码的函数名
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>- 结果:执行
- 原因:函数名是标识符,支持Unicode表示
11-13. JS Unicode编码的语法元素
html <script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script> <script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script> <script>alert('13\u0027)</script>
- 结果:都不执行
- 原因:括号和引号等语法元素不能用Unicode表示
- JS Unicode编码的换行符
<script>alert('14\u000a')</script>- 结果:执行
- 原因:换行符在JS字符串中有效
综合案例
- 混合编码
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(15)"></a>- 结果:执行
- 解码过程:
- HTML解码得到
javascript:%5c%75%30%30%36%31... - URL解码得到
javascript:\u0061\u006c\u0065\u0072\u0074(15) - JS解码执行
alert(15)
- HTML解码得到
总结与防御建议
-
解码顺序总结:
- 首先进行HTML解码
- 然后进行URL解码(在特定属性中)
- 最后进行JS Unicode解码(在JS上下文中)
-
元素类型影响:
- 原始文本元素(
<script>、<style>):只包含文本,不进行HTML解码 - RCDATA元素(
<textarea>、<title>):进行HTML解码,不解析子元素 - 普通元素:进行HTML解码并解析子元素
- 原始文本元素(
-
防御建议:
- 对用户输入进行适当的编码/转义
- 根据输出上下文使用正确的编码方式
- 使用CSP等安全策略限制脚本执行
- 避免将用户输入直接放入JS上下文
-
测试技巧:
- 理解浏览器解析顺序
- 根据目标上下文选择合适的编码方式
- 测试不同编码组合的解析结果
通过深入理解这些解码机制,安全人员可以更有效地发现和防御XSS漏洞,同时也能更好地构造有效的XSS攻击向量进行测试。