JavaScript原型链污染
字数 1051 2025-08-10 16:34:34

JavaScript原型链污染漏洞详解

一、JavaScript原型链基础

1.1 原型链概念

JavaScript通过原型链实现继承机制。每个对象都有一个原型对象(__proto__),原型对象也可能有自己的原型,形成原型链。

1.2 关键术语

  • prototype:函数的原型属性,只有函数拥有
  • proto:实例对象的原型指针,指向构造函数的prototype
  • constructor:指向构造函数本身

1.3 原型链示例

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const p = new Person('zhangsan', 18);

// 原型关系
f.constructor === Foo;
f.__proto__ === Foo.prototype;
Foo.__proto__ === Function.prototype;

二、原型链污染原理

2.1 基本概念

通过修改实例对象的__proto__中的值,污染类本体,进而影响所有和该对象来自同一个类、父祖类的对象。

2.2 污染条件

需要满足以下条件:

  1. 能够控制对象属性
  2. 能够将__proto__作为键名传入
  3. 存在对象合并、克隆或属性修改操作

2.3 污染示例

function merge(target, source) {
  for (let key in source) {
    if (key in source && key in target) {
      merge(target[key], source[key])
    } else {
      target[key] = source[key]
    }
  }
}

let o1 = {}
let o2 = JSON.parse('{"a": 1, "__proto__": {"b": 2}}')
merge(o1, o2)

let o3 = {}
console.log(o3.b) // 输出2,原型已被污染

三、实际利用场景

3.1 常见易受攻击操作

  1. 对象合并(merge):将多个对象属性合并到一个对象中
  2. 对象克隆(clone):实质是将对象merge到空对象中
  3. 路径查找属性修改:通过路径查找并修改属性

3.2 关键点

  • 直接使用{__proto__: {...}}语法不会触发污染,因为__proto__会被解释为原型
  • 通过JSON.parse解析的__proto__会被视为普通键名,可实现污染

四、实际漏洞分析:CVE-2019-11358

4.1 漏洞描述

jQuery 3.4.0之前版本存在原型污染漏洞,通过jQuery.extend()函数可实现污染。

4.2 漏洞利用

const json1 = '{"__proto__": {"z": 123}}';
jQuery.extend(true, {}, JSON.parse(json1));

// 验证污染
console.log({}.z); // 输出123

4.3 漏洞原理

jQuery.extend()进行深度合并时,未对__proto__进行特殊处理,导致可以修改Object原型。

五、防御措施

  1. 避免使用不安全的合并函数:使用Object.assign等安全方法
  2. 冻结Object.prototypeObject.freeze(Object.prototype)
  3. 检查键名:在合并操作前检查__proto__constructor等敏感属性
  4. 使用无原型对象Object.create(null)创建无原型的对象
  5. 升级依赖库:及时更新存在漏洞的第三方库

六、总结

JavaScript原型链污染是一种通过修改原型链实现污染全局对象的漏洞,主要出现在对象合并、克隆等操作中。理解原型链机制是防御此类漏洞的基础,开发者应特别注意对用户输入的处理,避免将不可信数据直接用于对象操作。

JavaScript原型链污染漏洞详解 一、JavaScript原型链基础 1.1 原型链概念 JavaScript通过原型链实现继承机制。每个对象都有一个原型对象( __proto__ ),原型对象也可能有自己的原型,形成原型链。 1.2 关键术语 prototype :函数的原型属性,只有函数拥有 proto :实例对象的原型指针,指向构造函数的prototype constructor :指向构造函数本身 1.3 原型链示例 二、原型链污染原理 2.1 基本概念 通过修改实例对象的 __proto__ 中的值,污染类本体,进而影响所有和该对象来自同一个类、父祖类的对象。 2.2 污染条件 需要满足以下条件: 能够控制对象属性 能够将 __proto__ 作为键名传入 存在对象合并、克隆或属性修改操作 2.3 污染示例 三、实际利用场景 3.1 常见易受攻击操作 对象合并(merge) :将多个对象属性合并到一个对象中 对象克隆(clone) :实质是将对象merge到空对象中 路径查找属性修改 :通过路径查找并修改属性 3.2 关键点 直接使用 {__proto__: {...}} 语法不会触发污染,因为 __proto__ 会被解释为原型 通过 JSON.parse 解析的 __proto__ 会被视为普通键名,可实现污染 四、实际漏洞分析:CVE-2019-11358 4.1 漏洞描述 jQuery 3.4.0之前版本存在原型污染漏洞,通过 jQuery.extend() 函数可实现污染。 4.2 漏洞利用 4.3 漏洞原理 jQuery.extend() 进行深度合并时,未对 __proto__ 进行特殊处理,导致可以修改Object原型。 五、防御措施 避免使用不安全的合并函数 :使用Object.assign等安全方法 冻结Object.prototype : Object.freeze(Object.prototype) 检查键名 :在合并操作前检查 __proto__ 、 constructor 等敏感属性 使用无原型对象 : Object.create(null) 创建无原型的对象 升级依赖库 :及时更新存在漏洞的第三方库 六、总结 JavaScript原型链污染是一种通过修改原型链实现污染全局对象的漏洞,主要出现在对象合并、克隆等操作中。理解原型链机制是防御此类漏洞的基础,开发者应特别注意对用户输入的处理,避免将不可信数据直接用于对象操作。