通过命名空间混淆实现突变XSS - DOMPurify < 2.0.17 bypass
字数 1955 2025-08-20 18:18:05

DOMPurify < 2.0.17 命名空间混淆绕过分析

1. 漏洞概述

本漏洞利用HTML规范中的命名空间特性和表单元素解析规则,通过精心构造的HTML标记绕过DOMPurify的过滤机制,最终实现跨站脚本攻击(XSS)。该漏洞影响DOMPurify 2.0.17之前的版本。

2. 关键概念

2.1 DOMPurify工作原理

DOMPurify的工作流程:

  1. 将输入HTML解析为DOM树
  2. 遍历DOM树,删除所有不在白名单中的元素和属性
  3. 将过滤后的DOM树序列化为HTML字符串
  4. 返回安全的HTML字符串

典型使用方式:

div.innerHTML = DOMPurify.sanitize(htmlMarkup);

2.2 HTML解析与序列化的不一致性

HTML规范明确指出:序列化DOM树后再解析,不保证返回原始DOM结构。这种不一致性是mXSS(突变XSS)的根本原因。

2.3 表单元素的特殊解析规则

HTML规范中表单元素(<form>)的特殊性:

  • 表单元素不能嵌套
  • 解析器使用"表单元素指针"跟踪当前表单
  • 结束标签</form>会将表单元素指针设为null

特殊嵌套示例

<form id="outer"><div></form><form id="inner"><input>

解析后会产生嵌套的表单结构,但序列化后再解析会消除嵌套。

2.4 HTML命名空间与外部内容

HTML解析器涉及三种命名空间:

  1. HTML命名空间 (http://www.w3.org/1999/xhtml)
  2. SVG命名空间 (http://www.w3.org/2000/svg)
  3. MathML命名空间 (http://www.w3.org/1998/Math/MathML)

命名空间切换规则

  • 遇到<svg>切换到SVG命名空间
  • 遇到<math>切换到MathML命名空间

2.5 集成点(Integration Points)

MathML文本集成点

  • <math>, <mi>, <mo>, <mn>, <ms>, <mtext>

HTML集成点

  • <math annotation-xml> (当encoding属性为text/htmlapplication/xhtml+xml)
  • <svg foreignObject>, <svg desc>, <svg title>

2.6 特殊元素mglyph和malignmark

在MathML文本集成点中,只有<mglyph><malignmark>作为直接子元素时保持MathML命名空间,其他元素默认切换到HTML命名空间。

3. 漏洞利用分析

3.1 利用Payload

<form><math><mtext></form><form><mglyph><style></math>

3.2 解析过程

初始解析

  1. 第一个<form>打开,设置表单元素指针
  2. <math>切换到MathML命名空间
  3. <mtext>是MathML文本集成点
  4. </form>关闭表单,指针设为null
  5. 第二个<form>打开
  6. <mglyph>作为<form>的子元素,在HTML命名空间
  7. <style>在HTML命名空间,内容作为文本处理

过滤后DOM树

- html:form
  - mathml:math
    - mathml:mtext
      - html:form
        - html:mglyph
          - html:style
            - 文本内容: "</math>"

序列化后HTML

<form><math><mtext><form><mglyph><style></math></style></mglyph></form></mtext></math></form>

重新解析时

  1. 第一个<form>打开
  2. <math>切换到MathML命名空间
  3. <mtext>是MathML文本集成点
  4. 尝试打开第二个<form>,但由于在<mtext>内,表单元素指针不为null,第二个<form>被忽略
  5. <mglyph>现在是<mtext>的直接子元素,保持在MathML命名空间
  6. <style>在MathML命名空间,内容不被视为文本
  7. </math>关闭MathML命名空间
  8. ``在HTML命名空间创建,执行XSS

3.3 关键点

  1. 表单嵌套的解析差异:初始解析允许特殊形式的嵌套,但重新解析时会消除嵌套
  2. mglyph的命名空间变化:初始在HTML命名空间,重新解析后在MathML命名空间
  3. style元素的解析差异:HTML命名空间的style内容作为文本,MathML命名空间的style内容作为标记解析

4. 相关变种

另一个利用相同原理的Payload:

<math><mtext><table><mglyph><style><math><table id="</table>">

5. 防御建议

  1. 避免序列化-解析往返:使用DOMPurify的RETURN_DOMRETURN_DOM_FRAGMENT选项

    // 推荐用法
    const cleanDOM = DOMPurify.sanitize(html, {RETURN_DOM: true});
    
  2. 升级DOMPurify:确保使用2.0.17或更高版本

  3. 理解HTML解析复杂性:开发者应充分了解HTML解析的特殊情况,特别是命名空间和元素嵌套规则

6. 总结

该漏洞展示了HTML解析器复杂性与安全过滤器的交互问题,通过:

  • 滥用表单元素的解析特性
  • 利用MathML命名空间中的特殊元素行为
  • 依赖序列化-解析过程的不一致性

实现了对DOMPurify的绕过,强调了在安全过滤中直接操作DOM而非序列化HTML的重要性。

DOMPurify < 2.0.17 命名空间混淆绕过分析 1. 漏洞概述 本漏洞利用HTML规范中的命名空间特性和表单元素解析规则,通过精心构造的HTML标记绕过DOMPurify的过滤机制,最终实现跨站脚本攻击(XSS)。该漏洞影响DOMPurify 2.0.17之前的版本。 2. 关键概念 2.1 DOMPurify工作原理 DOMPurify的工作流程: 将输入HTML解析为DOM树 遍历DOM树,删除所有不在白名单中的元素和属性 将过滤后的DOM树序列化为HTML字符串 返回安全的HTML字符串 典型使用方式: 2.2 HTML解析与序列化的不一致性 HTML规范明确指出:序列化DOM树后再解析, 不保证 返回原始DOM结构。这种不一致性是mXSS(突变XSS)的根本原因。 2.3 表单元素的特殊解析规则 HTML规范中表单元素( <form> )的特殊性: 表单元素不能嵌套 解析器使用"表单元素指针"跟踪当前表单 结束标签 </form> 会将表单元素指针设为null 特殊嵌套示例 : 解析后会产生嵌套的表单结构,但序列化后再解析会消除嵌套。 2.4 HTML命名空间与外部内容 HTML解析器涉及三种命名空间: HTML命名空间 ( http://www.w3.org/1999/xhtml ) SVG命名空间 ( http://www.w3.org/2000/svg ) MathML命名空间 ( http://www.w3.org/1998/Math/MathML ) 命名空间切换规则 : 遇到 <svg> 切换到SVG命名空间 遇到 <math> 切换到MathML命名空间 2.5 集成点(Integration Points) MathML文本集成点 : <math> , <mi> , <mo> , <mn> , <ms> , <mtext> HTML集成点 : <math annotation-xml> (当encoding属性为 text/html 或 application/xhtml+xml ) <svg foreignObject> , <svg desc> , <svg title> 2.6 特殊元素mglyph和malignmark 在MathML文本集成点中, 只有 <mglyph> 和 <malignmark> 作为直接子元素时保持MathML命名空间,其他元素默认切换到HTML命名空间。 3. 漏洞利用分析 3.1 利用Payload 3.2 解析过程 初始解析 : 第一个 <form> 打开,设置表单元素指针 <math> 切换到MathML命名空间 <mtext> 是MathML文本集成点 </form> 关闭表单,指针设为null 第二个 <form> 打开 <mglyph> 作为 <form> 的子元素,在HTML命名空间 <style> 在HTML命名空间,内容作为文本处理 过滤后DOM树 : 序列化后HTML : 重新解析时 : 第一个 <form> 打开 <math> 切换到MathML命名空间 <mtext> 是MathML文本集成点 尝试打开第二个 <form> ,但由于在 <mtext> 内,表单元素指针不为null,第二个 <form> 被忽略 <mglyph> 现在是 <mtext> 的直接子元素,保持在MathML命名空间 <style> 在MathML命名空间,内容不被视为文本 </math> 关闭MathML命名空间 `` 在HTML命名空间创建,执行XSS 3.3 关键点 表单嵌套的解析差异 :初始解析允许特殊形式的嵌套,但重新解析时会消除嵌套 mglyph的命名空间变化 :初始在HTML命名空间,重新解析后在MathML命名空间 style元素的解析差异 :HTML命名空间的style内容作为文本,MathML命名空间的style内容作为标记解析 4. 相关变种 另一个利用相同原理的Payload: 5. 防御建议 避免序列化-解析往返 :使用DOMPurify的 RETURN_DOM 或 RETURN_DOM_FRAGMENT 选项 升级DOMPurify :确保使用2.0.17或更高版本 理解HTML解析复杂性 :开发者应充分了解HTML解析的特殊情况,特别是命名空间和元素嵌套规则 6. 总结 该漏洞展示了HTML解析器复杂性与安全过滤器的交互问题,通过: 滥用表单元素的解析特性 利用MathML命名空间中的特殊元素行为 依赖序列化-解析过程的不一致性 实现了对DOMPurify的绕过,强调了在安全过滤中直接操作DOM而非序列化HTML的重要性。