JavaScript原型链污染
字数 884 2025-08-27 12:33:23
JavaScript原型链污染漏洞详解
一、JavaScript原型链基础
1. 原型对象概念
在JavaScript中,所有对象都有一个原型对象(prototype),通过__proto__属性可以访问该对象的原型:
let obj = {};
obj.__proto__; // 返回obj的原型对象
2. 原型链结构
原型链是由一系列原型对象组成的链式结构:
- 每个对象都有一个原型对象
- 原型对象又有自己的原型对象
- 最终的原型链会指向
null
obj.__proto__.__proto__; // 最终会返回null
3. 原型继承
JavaScript中常见的继承方式包括:
- 原型链继承
- 借用构造函数继承
- 原型式继承
- 寄生式继承
二、原型链污染原理
1. 对象访问方式
JavaScript中访问对象属性的两种方式:
example.a.b // 访问example对象下a对象的b属性
example.a["b"] // 访问example对象下a数组的下标为b的值
2. 原型链污染漏洞
通过特殊方式访问和修改原型链上的属性:
a["__proto__"]["admintoken"] = "ccda";
这种操作会污染所有继承自该原型的对象,导致所有实例都会获得这个新属性。
三、漏洞实例分析
1. 漏洞代码示例
matrix[client.row][client.col] = client.data;
其中data是用户可控的输入参数,当row和col被控制为__proto__时,可以污染原型链。
2. 攻击目标
题目要求:传入的querytoken与user.admintoken的md5哈希值相同。
3. 攻击思路
由于user和matrix都是Array实例,可以通过污染Array的原型来修改user.admintoken。
4. 攻击演示
a = b = {};
b["__proto__"]["admintoken"] = "ccda";
a.admintoken; // 返回"ccda",证明原型污染成功
四、防御措施
- 避免使用
__proto__:使用Object.getPrototypeOf()和Object.setPrototypeOf()替代 - 冻结原型对象:
Object.freeze(Object.prototype) - 输入验证:严格检查用户输入的属性名
- 使用Map代替Object:Map不会受到原型污染影响
- 使用
Object.create(null):创建没有原型的对象
五、总结
原型链污染是一种通过修改原型对象来影响所有继承自该原型的对象的攻击方式。攻击者可以利用JavaScript的动态特性,通过控制对象属性访问来污染原型链,进而影响应用程序的行为。开发者需要了解这种攻击方式并采取适当的防御措施。