揭开原型污染的“污染源”:从URL到JSON,黑客的隐形入口在哪?

admin 2026-05-11 09:35:40 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文深入分析原型污染漏洞的两种常见输入源:URL查询参数和JSON数据。当恶意构造的proto键值通过递归合并操作进入对象时,会污染Object原型链导致全局属性注入。文章指出URL解析和JSON.parse()均不会拦截proto键名,关键在于后续合并操作是否进行键名过滤,并建议审计时重点关注这些数据入口的清洗机制。 综合评分: 85 文章分类: 漏洞分析,WEB安全,代码审计,安全开发,应用安全


cover_image

揭开原型污染的“污染源”:从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,黑客的隐形入口在哪?》

评论:0   参与:  0