安全敏感变量和内置浏览器API克星 | DOM Clobbering技术防御详解
字数 1484 2025-08-18 17:33:04

DOM Clobbering技术详解与防御指南

一、DOM Clobbering概述

DOM Clobbering是一种无JavaScript注入攻击技术,攻击者通过在网页HTML代码中插入非<script>标签的代码,利用命名属性访问方法将其转换成可执行代码,从而干扰Web应用程序客户端的JavaScript代码执行。

核心原理

  • 源于JavaScript变量和命名HTML标签之间的命名冲突
  • 利用HTML元素的idname属性覆盖JavaScript变量或API
  • 浏览器基于"命名属性可见性算法"自动将HTML元素映射到JavaScript对象

二、命名属性访问机制

JavaScript可以通过多种方式访问DOM元素:

  1. 标准方法:document.getElementById(), document.querySelector()
  2. 命名属性访问:document.xwindow.x(x为元素的id或name属性值)

浏览器会自动将具有idname属性的HTML元素映射到documentwindow对象的属性上。

三、漏洞代码示例与分析

示例1:全局配置覆盖

var s = document.createElement('script');
let config = window.globalConfig || {href: 'script.js'};
s.src = config.href;
document.body.appendChild(s);

攻击方式

<a id="globalConfig" href="malicious.js">

漏洞分析

  1. 第2行使用||运算符进行默认值赋值
  2. 攻击者注入的<a>标签覆盖了window.globalConfig
  3. 导致加载恶意脚本而非预期脚本

示例2:document属性覆盖

document.conf = {};
const queryParams = new URLSearchParams(window.location.search);
if(isTrustedOrigin(queryParams.get('next'))){
    document.conf.src = queryParams.get('next');
}

let next = document.conf.src || 'https://benign1.com/index.html';
window.location.href = next;

攻击方式


漏洞分析

  1. 第1行设置的document.conf可被后续DOM Clobbering覆盖
  2. 攻击者注入的``标签覆盖了document.conf
  3. 导致XSS攻击

四、常见漏洞模式

  1. 模式A/E:通过Window对象引用未定义变量并在敏感指令中使用
  2. 模式B/C:将自定义和本地document/window属性视为可信值
  3. 模式F/G/H:跨脚本标签的指令位置导致的复杂漏洞

五、防御措施与安全编码指南

1. 显式变量声明

  • 使用var/let/const明确声明变量
  • 避免依赖||运算符进行默认值赋值
  • 示例修复:
    const globalConfig = window.globalConfig !== undefined ? 
                        window.globalConfig : 
                        {href: 'script.js'};
    

2. 严格的类型检查

  • 对DOM属性进行类型验证
  • 使用instanceoftypeof运算符
  • 示例修复:
    if (window.globalConfig instanceof Object) {
        // 安全使用
    }
    

3. 避免使用document存储全局变量

  • 使用globalThis或模块作用域变量
  • 示例修复:
    const config = {}; // 替代document.conf
    

4. 命名空间隔离

  • 为用户生成内容添加前缀
  • 使用MutationObserver监控DOM变化
  • 示例:
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            // 检查并修改新增节点的id/name属性
        });
    });
    observer.observe(document, {childList: true, subtree: true});
    

六、综合防御建议

  1. 安全编码实践

    • 遵循上述安全编码模式
    • 特别注意模式A-H中的风险点
  2. HTML代码清洗

    • 对用户输入进行严格的过滤和转义
    • 使用专业库如DOMPurify
  3. 内容安全策略(CSP)

    • 实施严格的CSP策略
    • 限制非授权脚本执行
  4. 固定对象属性

    • 使用Object.freeze()防止对象被修改
    • 示例:
      const config = Object.freeze({href: 'script.js'});
      
  5. 禁用DOM Clobbering

    • 在关键对象上设置configurable: false
    • 示例:
      Object.defineProperty(window, 'globalConfig', {
          value: {},
          writable: true,
          configurable: false
      });
      

七、参考资料

  1. HTML Living Standard - Named Access on the Window Object
  2. DOM Clobbering Strikes Back - PortSwigger Research
  3. Sanitising HTML: The DOM Clobbering Issue - Fastmail Blog
  4. Web IDL Standard - Legacy Platform Object Abstract Ops
DOM Clobbering技术详解与防御指南 一、DOM Clobbering概述 DOM Clobbering是一种无JavaScript注入攻击技术,攻击者通过在网页HTML代码中插入非 <script> 标签的代码,利用命名属性访问方法将其转换成可执行代码,从而干扰Web应用程序客户端的JavaScript代码执行。 核心原理 源于JavaScript变量和命名HTML标签之间的命名冲突 利用HTML元素的 id 或 name 属性覆盖JavaScript变量或API 浏览器基于"命名属性可见性算法"自动将HTML元素映射到JavaScript对象 二、命名属性访问机制 JavaScript可以通过多种方式访问DOM元素: 标准方法: document.getElementById() , document.querySelector() 等 命名属性访问: document.x 或 window.x (x为元素的id或name属性值) 浏览器会自动将具有 id 或 name 属性的HTML元素映射到 document 和 window 对象的属性上。 三、漏洞代码示例与分析 示例1:全局配置覆盖 攻击方式 : 漏洞分析 : 第2行使用 || 运算符进行默认值赋值 攻击者注入的 <a> 标签覆盖了 window.globalConfig 导致加载恶意脚本而非预期脚本 示例2:document属性覆盖 攻击方式 : 漏洞分析 : 第1行设置的 document.conf 可被后续DOM Clobbering覆盖 攻击者注入的 ``标签覆盖了 document.conf 导致XSS攻击 四、常见漏洞模式 模式A/E :通过Window对象引用未定义变量并在敏感指令中使用 模式B/C :将自定义和本地document/window属性视为可信值 模式F/G/H :跨脚本标签的指令位置导致的复杂漏洞 五、防御措施与安全编码指南 1. 显式变量声明 使用 var / let / const 明确声明变量 避免依赖 || 运算符进行默认值赋值 示例修复: 2. 严格的类型检查 对DOM属性进行类型验证 使用 instanceof 和 typeof 运算符 示例修复: 3. 避免使用document存储全局变量 使用 globalThis 或模块作用域变量 示例修复: 4. 命名空间隔离 为用户生成内容添加前缀 使用MutationObserver监控DOM变化 示例: 六、综合防御建议 安全编码实践 遵循上述安全编码模式 特别注意模式A-H中的风险点 HTML代码清洗 对用户输入进行严格的过滤和转义 使用专业库如DOMPurify 内容安全策略(CSP) 实施严格的CSP策略 限制非授权脚本执行 固定对象属性 使用 Object.freeze() 防止对象被修改 示例: 禁用DOM Clobbering 在关键对象上设置 configurable: false 示例: 七、参考资料 HTML Living Standard - Named Access on the Window Object DOM Clobbering Strikes Back - PortSwigger Research Sanitising HTML: The DOM Clobbering Issue - Fastmail Blog Web IDL Standard - Legacy Platform Object Abstract Ops