Learn from:https://wiki.wgpsec.org/knowledge/ctf/js-prototype-chain-pollution.html

先放一张图

js 是由对象组成的,对象与对象之间存在着继承关系

每个对象都有一个指向它的原型的内部链接,而这个原型对象又有他自己的原型,直到 null 为止

整体看来就是多个对象层层继承,实例对象的原型链接形成了一条链,也就是 js 的原型链

在 js 中每个函数都有一个 prototype 属性,而每个对象中也有一个 **proto** 属性用来指向实例对象的原型

而每个原型也都有一个 constructor 属性执行相关联的构造函数,我们就是通过构造函数生成实例化的对象

由于对象之间存在继承关系,所以当我们要使用或者输出一个变量就会通过原型链向上搜索,当上层没有就会再向上上层搜索,直到指向 null,若此时还未找到就会返回 undefined

这幅图的原型链是

cat->Cat.protype->Object.prototype->null

原型链污染通常出现在对象数组的键名或者属性名可控,同时是赋值语句的情况下 ( 通常使用 json 传值 )

Learn form:https://pazuris.cn/2023/07/26/NodeJs%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93/

师傅讲的很详细

prototype和__proto__的区别

在 JavaScript 中,每个对象都有一个 __proto__ 属性,它指向该对象的原型。原型是一个对象,也可以有自己的原型,这样就形成了一个原型链。同时,每个函数也有一个 prototype 属性,它是一个对象,当该函数作为构造函数创建实例时,实例对象的 __proto__ 属性会指向该构造函数的 prototype 属性,这样就可以实现属性和方法的继承。

区别在于:

  • prototype属性是函数所独有的,而__proro__属性是每个对象都有的(再强调一次,函数也是js对象)
  • prototype 属性指向一个对象,它是用来存储属性和方法,这些属性和方法可以被该函数的实例对象所继承。而 __proto__ 属性指向该对象的原型,它是用来实现对象之间的继承。简单来说就是functionName.prototype===varName.__proto__,都可以访问到对象的原型。

nodejs原型链污染

概念

一句话概括原型链污染:如果修改了一个对象的原型,那么会影响所有来自于这个原型的对象,这就是原型链污染。

原型链污染通常出现在对象,数组的键名或者属性名可控,同时是赋值语句的情况下 (简单来说就是键名和键值都可控情况下),将键名设置为__proto__就可以利用赋值语句修改原型对象,进而实现原型链污染,常见的危险函数有merge和clone。