从 XSS Payload 学习浏览器解码
字数 1911 2025-08-26 22:11:57

从XSS Payload学习浏览器解码机制

基础知识

浏览器在处理XSS攻击向量时涉及多种解码机制,主要包括HTML解码、URL解码和JavaScript Unicode解码。理解这些解码顺序和规则对于防御和利用XSS漏洞至关重要。

解码机制详解

1. HTML解码

HTML实体编码(如jj表示字母"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解码之后
  • 只有特定属性(如hrefsrc等)会触发URL解码

3. JavaScript Unicode解码

JavaScript支持Unicode转义序列(如\u0061表示字母"a")。

关键点

  • 仅适用于字符串字面量和标识符(如函数名、变量名)
  • 不能用于其他语法元素(如引号、括号等)
  • 在字符串中的Unicode转义会被解码为相应字符

案例分析

基础案例

  1. 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"不被识别
  2. HTML实体编码的javascript协议

    <a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">
    
    • 结果:执行
    • 原因:HTML解码后得到可识别的javascript协议,然后URL解码执行
  3. URL编码的冒号

    <a href="javascript%3aalert(3)"></a>
    
    • 结果:不执行
    • 原因:同案例1,协议部分被编码
  4. HTML实体编码的标签

    <div>&#60;img src=x onerror=alert(4)&#62;</div>
    
    • 结果:不执行
    • 原因:HTML编码用于显示特殊字符,不会创建DOM元素

5-6. textarea中的脚本

<textarea>&#60;script&#62;alert(5)&#60;/script&#62;</textarea>
<textarea><script>alert(6)</script></textarea>
  • 结果:都不执行
  • 原因:RCDATA元素只显示文本,不解析子元素

进阶案例

  1. HTML实体编码的属性值

    <button onclick="confirm('7&#39;);">Button</button>
    
    • 结果:执行
    • 原因:属性值先HTML解码,然后作为JS执行
  2. JS Unicode编码的引号

    <button onclick="confirm('8\u0027);">Button</button>
    
    • 结果:不执行
    • 原因:JS中引号不能用Unicode表示
  3. script中的HTML实体

    <script>&#97;&#108;&#101;&#114;&#116&#40;&#57;&#41;&#59</script>
    
    • 结果:不执行
    • 原因:原始文本元素不进行HTML解码
  4. 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表示

  1. JS Unicode编码的换行符
    <script>alert('14\u000a')</script>
    
    • 结果:执行
    • 原因:换行符在JS字符串中有效

综合案例

  1. 混合编码
    <a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x31;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x36;&#x33;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x36;&#x25;&#x33;&#x35;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x32;&#x25;&#x35;&#x63;&#x25;&#x37;&#x35;&#x25;&#x33;&#x30;&#x25;&#x33;&#x30;&#x25;&#x33;&#x37;&#x25;&#x33;&#x34;&#x28;&#x31;&#x35;&#x29;"></a>
    
    • 结果:执行
    • 解码过程
      1. HTML解码得到javascript:%5c%75%30%30%36%31...
      2. URL解码得到javascript:\u0061\u006c\u0065\u0072\u0074(15)
      3. JS解码执行alert(15)

总结与防御建议

  1. 解码顺序总结

    • 首先进行HTML解码
    • 然后进行URL解码(在特定属性中)
    • 最后进行JS Unicode解码(在JS上下文中)
  2. 元素类型影响

    • 原始文本元素(<script><style>):只包含文本,不进行HTML解码
    • RCDATA元素(<textarea><title>):进行HTML解码,不解析子元素
    • 普通元素:进行HTML解码并解析子元素
  3. 防御建议

    • 对用户输入进行适当的编码/转义
    • 根据输出上下文使用正确的编码方式
    • 使用CSP等安全策略限制脚本执行
    • 避免将用户输入直接放入JS上下文
  4. 测试技巧

    • 理解浏览器解析顺序
    • 根据目标上下文选择合适的编码方式
    • 测试不同编码组合的解析结果

通过深入理解这些解码机制,安全人员可以更有效地发现和防御XSS漏洞,同时也能更好地构造有效的XSS攻击向量进行测试。

从XSS Payload学习浏览器解码机制 基础知识 浏览器在处理XSS攻击向量时涉及多种解码机制,主要包括HTML解码、URL解码和JavaScript Unicode解码。理解这些解码顺序和规则对于防御和利用XSS漏洞至关重要。 解码机制详解 1. HTML解码 HTML实体编码(如 &#x6a; 或 &#106; 表示字母"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协议 结果 :不执行 原因 :URL协议部分必须是ASCII,编码后的"javascript"不被识别 HTML实体编码的javascript协议 结果 :执行 原因 :HTML解码后得到可识别的javascript协议,然后URL解码执行 URL编码的冒号 结果 :不执行 原因 :同案例1,协议部分被编码 HTML实体编码的标签 结果 :不执行 原因 :HTML编码用于显示特殊字符,不会创建DOM元素 5-6. textarea中的脚本 结果 :都不执行 原因 :RCDATA元素只显示文本,不解析子元素 进阶案例 HTML实体编码的属性值 结果 :执行 原因 :属性值先HTML解码,然后作为JS执行 JS Unicode编码的引号 结果 :不执行 原因 :JS中引号不能用Unicode表示 script中的HTML实体 结果 :不执行 原因 :原始文本元素不进行HTML解码 JS Unicode编码的函数名 结果 :执行 原因 :函数名是标识符,支持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编码的换行符 结果 :执行 原因 :换行符在JS字符串中有效 综合案例 混合编码 结果 :执行 解码过程 : HTML解码得到 javascript:%5c%75%30%30%36%31... URL解码得到 javascript:\u0061\u006c\u0065\u0072\u0074(15) JS解码执行 alert(15) 总结与防御建议 解码顺序总结 : 首先进行HTML解码 然后进行URL解码(在特定属性中) 最后进行JS Unicode解码(在JS上下文中) 元素类型影响 : 原始文本元素( <script> 、 <style> ):只包含文本,不进行HTML解码 RCDATA元素( <textarea> 、 <title> ):进行HTML解码,不解析子元素 普通元素:进行HTML解码并解析子元素 防御建议 : 对用户输入进行适当的编码/转义 根据输出上下文使用正确的编码方式 使用CSP等安全策略限制脚本执行 避免将用户输入直接放入JS上下文 测试技巧 : 理解浏览器解析顺序 根据目标上下文选择合适的编码方式 测试不同编码组合的解析结果 通过深入理解这些解码机制,安全人员可以更有效地发现和防御XSS漏洞,同时也能更好地构造有效的XSS攻击向量进行测试。