浏览器解码顺序xss
浏览器解析和执行内容时遵循特定的解码顺序,这对XSS(跨站脚本攻击)的防御至关重要。攻击者常利用解码顺序的差异绕过过滤。以下是浏览器处理不同上下文的典型解码顺序:
1. HTML 解析优先
浏览器首先将响应作为HTML文档解析,按顺序处理:
-
字符实体解码
<
→<
,>
→>
,&
→&
等被还原。<!-- 输入: --> <img src=x onerror=alert(1)> <!-- 解码后: --> <img src=x onerror=alert(1)>
-
标签/属性解析
浏览器识别标签(<div>
、<script>
)和属性(href
、onclick
)。
2. JavaScript 执行(在特定上下文中)
当解析到 <script>
标签或事件处理器(如 onload
)时,浏览器进入JS解析模式:
-
JS字符串解码
Unicode转义(\u0061
→a
)、十六进制(\x61
→a
)被还原。// 输入: \u0061lert(1); // 解码后执行: alert(1);
-
注意:HTML实体在JS中不会被二次解码!
<script>// 以下代码不会执行,因为 < 在JS中是字符串var x = "<img src=x onerror=alert(1)>"; </script>
3. 特殊属性/协议的处理
某些属性触发额外解析层:
-
href
/src
等URL属性
若协议为javascript:
,会进行URL解码:<!-- 输入: --> <a href="javascript:%61lert(1)">Click</a> <!-- 解码后: --> <a href="javascript:alert(1)">Click</a>
-
CSS 中的解析
style
属性或<style>
标签内支持\XX
十六进制解码:<div style="background:url(javascript:alert(1))"></div>
关键顺序总结
graph LR
A[原始响应] --> B[HTML 实体解码]
B --> C[HTML 标签/属性解析]
C --> D{是否在 JS/CSS/URL 上下文?}
D -- JS --> E[JS 转义字符解码]
D -- URL --> F[URL 解码]
D -- CSS --> G[CSS 转义解码]
E --> H[执行 JS]
F --> H
G --> H
XSS 攻击的关键点
-
上下文混淆
- 过滤器可能只转义 HTML 实体(如
<
→<
),但若payload在<script>
中,需转义JS语法(如"
→\x22
)。 - 例:
<script>var user = "{{ user_input }}"; // 需防御JS字符串而非HTML </script>
- 过滤器可能只转义 HTML 实体(如
-
编码嵌套绕过
多层编码可能绕过简单过滤器:<!-- 输入: --> <a href="javascript:&#x61;lert(1)"></a> <!-- 解码步骤: --> <!-- 1. HTML解码:a → a (&已被解码为&) --> <!-- 2. URL解码:javascript:%61lert(1) → javascript:alert(1) -->
防御建议
- 根据输出上下文转义:
- HTML 正文:
<
→<
- HTML 属性:
"
→"
- JS 字符串:动态内容用
\xHH
转义 - URL:严格校验协议(禁止
javascript:
)
- HTML 正文:
- 使用安全框架自动处理(如React的JSX、DOMPurify)。
- 避免将用户输入放在高危位置(如
<script>
、href
、eval()
)。