文章总结: 本文深入分析原型污染漏洞的两种常见输入源:URL查询参数和JSON数据。当恶意构造的proto键值通过递归合并操作进入对象时,会污染Object原型链导致全局属性注入。文章指出URL解析和JSON.parse()均不会拦截proto键名,关键在于后续合并操作是否进行键名过滤,并建议审计时重点关注这些数据入口的清洗机制。 综合评分: 85 文章分类: 漏洞分析,WEB安全,代码审计,安全开发,应用安全
揭开原型污染的“污染源”:从URL到JSON,黑客的隐形入口在哪?
原创
升斗安全XiuXiu 升斗安全XiuXiu
升斗安全
2026年5月8日 07:55 广东
在小说阅读器读本章
去阅读
【文章说明】
- 目的:本文内容仅为网络安全技术研究与教育目的而创作。
- 红线:严禁将本文知识用于任何未授权的非法活动。使用者必须遵守《网络安全法》等相关法律。
- 责任:任何对本文技术的滥用所引发的后果自负,与本公众号及作者无关。
- 免责:内容仅供参考,作者不对其准确性、完整性作任何担保。
阅读即代表您同意以上条款。
在挖洞的过程中,有一类漏洞总是让人又爱又恨——它藏得深,影响却往往直击要害。这就是原型污染(Prototype Pollution)。今天我们不聊原理,也不讲怎么利用,先来看看这些“污染物”到底是从哪来的,长什么样。因为只有先找到源头,才好在实战中顺藤摸瓜,一击必中。
所谓原型污染源,说白了,就是那些攻击者能直接拿捏、并且可以向原型对象里塞进任意属性的输入通道。
听起来有点玄,但其实你在挖洞时经常跟它们打交道。最常见的也就这几种:
- 通过查询字符串或 URL 片段(井号后面那部分)传进来的参数
- 基于 JSON 格式的输入
- Web 消息(postMessage 那一类)
别看这些东西平时老老实实,一旦程序不小心把它们跟现成的对象做了合并,麻烦就来了。
先看怎么通过 URL 来搞事
想象一个再普通不过的地址:
https://vulnerable-website.com/?__proto__[evilProperty]=payload
你第一眼可能觉得,这不过是 URL 里带了个参数,键叫 __proto__[evilProperty],值是 payload,没什么特别的。URL 解析器也确实会把它当成一个普普通通的字符串。
但关键在于接下来的这一步——如果网站后端或前端代码,把从查询字符串里解析出来的这些键值对,一股脑赋值合并到某个已有对象里,戏就来了。
很多人直觉上会以为,合并后的结果大概是这个样子:
{ existingProperty1: 'foo', existingProperty2: 'bar', __proto__: { evilProperty: 'payload' }}
看起来就是把 __proto__ 当成一个普通的属性名加进去了,好像无害。可惜,真实情况不是这么玩的。
真正的“魔术”发生在递归合并那一行——它本质上会执行类似这样的操作:
targetObject.__proto__.evilProperty = 'payload';
这时候,JavaScript 引擎不把 __proto__ 当普通属性,而是把它当成原型的 getter。于是 evilProperty 根本没有被挂到目标对象自己身上,而是直接赋给了它所引用的原型对象。
如果目标对象用的是默认的 Object.prototype,那不好意思,整个运行时里的所有对象,都将被迫“继承”这个 evilProperty——除非它们自己已经有同名的属性盖住了它。
当然,实际渗透里你肯定不满足于注入一个名叫 evilProperty 又毫无卵用的属性。但技术路线是通的:你可以用完全一样的套路,去污染那些应用程序自己或者某个依赖库里会用到的关键属性,链条断裂、权限绕过、甚至 RCE 都可能由此而生。
除了 URL,JSON 输入也是另一个常见的污染入口
很多时候,用户能控制的数据会通过 JSON.parse() 转成对象。有意思的是,JSON.parse() 也会把 __proto__ 这类键当成普通字符串,压根不拦着。
比如攻击者通过 Web 消息之类的方式,塞进来这么一段看似无辜的 JSON:
{ "__proto__": { "evilProperty": "payload" }}
用 JSON.parse() 一解析,出来的对象还真就稳稳当当地包含一个键名叫 __proto__ 的属性:
const objectLiteral = {__proto__: {evilProperty: 'payload'}};const objectFromJson = JSON.parse('{"__proto__": {"evilProperty": "payload"}}');objectLiteral.hasOwnProperty('__proto__'); // falseobjectFromJson.hasOwnProperty('__proto__'); // true
看出差别没?字面量方式创建的对象,__proto__ 没有变成自有属性,所以 hasOwnProperty 返回 false;但从 JSON 解析来的对象,却实实在在地拥有了这个属性。
如果后面代码没做键名过滤,又把这个解析出来的对象合并到现有对象上,那赋值过程就会重演 URL 场景里的悲剧——原型污染再次触发,和前面一模一样。
简单总结一下:不管是 URL 里的参数,还是 JSON 里的键名,只要进入系统后没有经过严格的“洗数据”,又被递归合并到其他对象里,__proto__ 这个看似无害的东西就会变成一个通往全局原型的高速通道。
知道污染物从哪儿来,下次在做代码审计或者黑盒测试时,多往这些地方多看一眼,也许就会有意外之喜。
觉得有收获?点赞、在看走一波,也欢迎分享给一起挖洞的兄弟。
如果你手里正好有疑似原型污染的场景啃不下来,评论区交流,说不定有大神能帮你拨开迷雾。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:升斗安全 升斗安全XiuXiu 升斗安全XiuXiu《揭开原型污染的“污染源”:从URL到JSON,黑客的隐形入口在哪?》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论