image-20220918094707938

image-20220918094707938

image-20220918094718704

image-20220918094718704

image-20220918094731646

image-20220918094731646

image-20220918094749027

image-20220918094749027

image-20220918094800472

image-20220918094800472

代码结构大致如上,查了查发现需要学习到几个知识点,js继承的机制也就是原型链。

原型

首先其实要知道nodejs其实就是javascript,只是nodejs更像是一个中间层运行在服务端,单从语法上来说是一样的,所以这里可以一起看。

js的特性:万物皆是对象。

显示原型:prototype,函数独有的
隐式原型:__proto__,对象都有的

简单来个结论:构造函数的显示原型等于实例化对象的隐式原型,如果一开始绕不过去可以先记住这个再去理清楚逻辑。

demo:

function a(){};
let b=new a();
a.prototype==b.__proto__;//true

知识点plus:
js的继承是通过原型之间的相等关系产生的原型链实现的,这不同于我们常用的c+ java的思路,这也就会导致变量以递归方式进行继承或覆盖等操作时,可以对继承的上一级对象属性进行一个修改继而影响到所有继承自该对象的属性,我们称其为原型链污染。

在demo中,a函数是b对象的构造函数,如果把a函数看成我们平时理解的一个类,那么a函数本身就是这个类的构造函数,如果对表述有一定的疑惑,可以看这个demo来理解。

function a(){};
let b=new a();
a.constructor==Function;//true
b.constructor=a;//true

总结一下:
js里万物皆对象,对象的顶级就是Object,任何一个对象都具备构造函数这个属性,函数的顶级就是Function。
Object.constructor==Function;//true

基于以上两个知识点,我们便可以写出绕过思路了。

image-20220918100539316

image-20220918100539316

禁用了__proto__,我们依旧可以使用constrctor和prototype来获得顶级的prototype。

原型链污染

poc验证:

{"constructor":{"prototype":{"name":"Baker"}}}