原型链污染的本质是攻击者通过向object.prototype注入恶意属性,导致所有对象继承该属性,从而引发权限绕过、逻辑错乱、遍历异常乃至远程代码执行;其发生源于递归合并时未过滤__proto__等敏感键名,防御需冻结原型、使用object.create(null)、清洗输入并替换危险工具。

原型链污染的本质是“改了祖宗,全家中招”
JavaScript 对象查找属性时会一路向上找原型,直到 Object.prototype。它就像所有普通对象的“共同祖先”。一旦攻击者把恶意属性(比如 admin: true 或 toString: maliciousFn)写进 Object.prototype,所有对象——包括 {}、[]、new Date()——都会自动继承这个属性。这不是某个变量被篡改,而是整个运行时环境的底层行为被悄悄覆盖。
污染是怎么发生的?关键在“递归+不设防”
漏洞通常出现在处理用户输入的对象合并或深拷贝操作中,尤其当代码未过滤敏感键名时:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
_.merge({}, userInput)合并 JSON 解析结果,而输入含{"__proto__": {"isAdmin": true}} - 手动实现递归赋值,直接执行
target[key] = source[key],未拦截__proto__、constructor、prototype及其大小写变体(如__PROTO__) - 依赖旧版工具库,例如 lodash merge 或
defaultsDeep,它们默认允许向原型写入
真实危害不止于“多一个字段”
污染后看似只是加了个属性,实际可能引发连锁反应:
-
权限绕过:
if (user.isAdmin)意外为true,因user继承自被污染的Object.prototype -
逻辑错乱:覆盖
toString或valueOf,干扰 JSON 序列化、模板渲染、日志输出,甚至隐藏攻击痕迹 -
遍历异常:污染
hasOwnProperty,导致for...in、Object.keys()行为失常,配置解析失败或跳过安全校验 -
远程代码执行(RCE):在 Express 中污染
constructor.prototype可劫持中间件加载;Vue CLI 旧版曾因不安全 merge 触发任意代码执行
防御不是靠单一手段,而是分层设卡
真正可靠的防护需要多个环节协同:
-
启动即冻结关键原型:在 HTML 第一个
<script></script>顶部立即执行Object.freeze(Object.prototype)、Object.freeze(Array.prototype)等,确保第三方脚本加载前环境已锁定 -
业务层主动隔离:配置对象、映射表等场景改用
Object.create(null)创建无原型对象,天然免疫污染 -
输入必须清洗:解析外部数据(JSON、URL 参数、表单)后,先移除所有
__proto__、constructor、prototype及其大小写变体,再做合并;更推荐白名单机制,只保留明确允许的字段名 -
替换危险工具:避免使用存在风险的通用深拷贝函数;浅拷贝可用
Object.assign({}, input);深拷贝优先用structuredClone()(现代环境),或自定义函数跳过原型相关键
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










