浅谈原型污染
字数 1453 2025-08-29 08:30:30
JavaScript原型污染漏洞详解
1. 什么是原型污染
原型污染(Prototype Pollution)是一种JavaScript安全漏洞,它允许攻击者向全局对象原型中添加任意属性,这些属性随后可能会被用户定义的对象继承。
关键特性:
- 通常不能作为独立漏洞被利用,但可以与其他漏洞串联
- 在客户端可能导致DOM型XSS攻击
- 在服务器端可能引发远程代码执行(RCE)
- 主要影响内置的全局Object.prototype
2. 漏洞产生原理
原型污染漏洞通常发生在JavaScript函数将包含用户可控属性的对象递归合并到现有对象中时,而没有事先对键进行清理。
攻击流程:
- 攻击者注入一个键名为
__proto__的属性 - 合并操作将嵌套属性分配到对象的原型上而非目标对象本身
- 所有继承该原型的对象都会获得这些恶意属性
关键要素:
- 污染源:能够注入任意属性的输入点
- 污染接收点(Sink):能导致代码执行的函数或DOM元素
- 可利用的工具(Gadget):被传递到接收点且未经适当过滤的属性
3. 污染源分析
3.1 通过URL的原型污染
示例URL:
https://vulnerable-website.com/?__proto__[evilProperty]=payload
解析过程:
- URL解析器将
__proto__视为普通字符串 - 键值对被合并到现有对象中
- JavaScript引擎将
__proto__视为原型访问器 evilProperty被赋值给原型对象而非目标对象
3.2 通过JSON输入的原型污染
恶意JSON示例:
{
"__proto__": {
"evilProperty": "payload"
}
}
关键点:
JSON.parse()将__proto__视为普通字符串键- 生成的对象具有
__proto__自有属性 - 后续合并操作可能导致原型污染
4. 污染接收点(Sink)
接收点是能够执行任意代码的JavaScript函数或DOM元素,包括但不限于:
eval()及相关函数- DOM操作函数
- 动态脚本加载
- 模板引擎
- 反序列化函数
5. 可利用的工具(Gadget)
工具特征:
- 被应用程序以不安全方式使用
- 可通过原型污染被攻击者控制
- 不是对象的自有属性
典型示例:
let transport_url = config.transport_url || defaults.transport_url;
let script = document.createElement('script');
script.src = transport_url;
攻击方式:
- 污染
Object.prototype添加transport_url属性 - 库代码使用被污染的默认值
- 加载恶意脚本
6. 防御措施
6.1 输入验证与过滤
- 禁止合并包含
__proto__、constructor或prototype键的对象 - 使用对象白名单策略
6.2 安全合并函数
实现安全的深度合并函数,例如:
function safeMerge(target, source) {
for (const key in source) {
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
continue;
}
if (typeof source[key] === 'object' && source[key] !== null) {
if (!target[key]) Object.assign(target, {[key]: {}});
safeMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
6.3 使用Object.create(null)
创建无原型的对象:
const safeObject = Object.create(null);
6.4 冻结原型
防止原型被修改:
Object.freeze(Object.prototype);
6.5 使用Map替代普通对象
对于键值存储,使用Map更安全:
const safeMap = new Map();
7. 检测方法
7.1 手动测试
尝试注入以下payload并观察行为:
{"__proto__":{"testProperty":"testValue"}}
7.2 自动化工具
- 使用专门的扫描工具如PPFuzz
- 结合DAST工具进行检测
8. 实际案例分析
8.1 Lodash漏洞(CVE-2018-3721)
- 影响版本:< 4.17.5
- 问题函数:
_.defaultsDeep - 修复方式:添加原型键检查
8.2 jQuery漏洞
- 影响版本:< 3.4.0
- 问题函数:
$.extend - 修复方式:深度复制时跳过
__proto__
9. 总结
原型污染是一种危险的JavaScript漏洞,其危害程度取决于:
- 应用程序中存在的可污染属性
- 这些属性被如何使用
- 是否有合适的接收点
防御的关键在于:
- 严格控制对象合并操作
- 避免信任原型链上的属性
- 实施深度防御策略