原型链污染是一种安全漏洞,指攻击者通过恶意输入篡改object.prototype,使所有对象继承被污染属性,可能导致拒绝服务、逻辑绕过或rce;其特征是行为异常而非内存增长,常见于lodash.merge等深度操作后。

原型链泄露(Prototype Pollution)不是内存泄漏,而是一种安全漏洞——它指攻击者通过恶意输入篡改对象的原型(如 Object.prototype),导致后续所有对象意外继承被污染的属性,可能引发拒绝服务、逻辑绕过甚至远程代码执行。
识别原型链泄露的关键特征
这类问题不会表现为内存持续增长或页面卡顿,而是行为异常且难以复现。常见线索包括:
- 某个本不该存在的属性(如
__proto__、constructor、toString)在任意对象上突然可读/可写 - 调用
{}.toString()报错,或返回非预期字符串(说明Object.prototype.toString被覆盖) - 使用
lodash.merge、deepAssign、JSON.parse + 递归赋值等深度操作后,基础对象行为异常 - Node.js 服务中出现未定义的全局属性访问(如
process.env.NODE_ENV突然为"polluted")
快速检测是否存在污染
在控制台或调试环境中运行以下检查语句:
-
{}.__proto__.pollution_test = 1; console.log({}.pollution_test);→ 若输出1,说明已污染 -
Object.prototype.polluted = true; console.log(({}).polluted);→ 同样输出true即危险 - 对常用库做验证:
require('lodash').has({}, '__proto__')在旧版 lodash 中可能返回true(CVE-2019-10744)
注意:现代浏览器和 Node.js(v12.19+ / v14.6+)已限制对 __proto__ 的直接写入,但污染仍可通过 Object.setPrototypeOf 或 constructor.prototype 绕过。
排查污染源头的实用方法
重点审查所有接受用户输入并执行深度合并、路径赋值、反序列化操作的代码:
- 搜索项目中所有
merge、assign、set、update类函数调用,尤其来自lodash、fast-deep-equal、hoek等库 - 检查 JSON 解析后是否执行了类似
obj[key] = value的动态赋值,且key来自不可信来源(如 URL 参数、表单字段名) - 验证第三方中间件(如 Express 的
body-parser、qs库)版本:旧版qs(allowPrototypes: true,极易触发污染
修复与防护建议
不依赖“堵住所有入口”,而是建立防御纵深:
- 升级依赖:确保
lodash 、<code>qs 、<code>hoek 等已知存在 CVE 的库更新到安全版本 - 禁用危险选项:配置
qs.parse(str, { allowPrototypes: false });使用JSON.parse时避免后续_.set操作 - 输入白名单:对键名做正则校验(如
/^[a-zA-Z0-9_]+$/),拒绝含__proto__、constructor、prototype的字段 - 运行时防护:在应用启动时冻结关键原型:
Object.freeze(Object.prototype)(注意部分库会因此报错,需充分测试)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











