复现原型链污染

目录

一、原型链污染是什么

1.原理

2.例题

3.分析

二、prototype和_proto的分别是什么

proto属性指向当前对象的原型对象,即构造函数的prototype属性。

获取实例对象obj的原型对象的三种方法

总结:

三 、Javascript原型链继承

1.了解     

2.例题

3.总结

4.要点

四、哪些情况下原型链会被污染?

1.首先假设一个merge函数

2. 以上代码存在合并的过程,存在赋值的操作target[key] = source[key],那么key如果是__proto__,那么我们就可以进行原型链的污染。

3.修改命令,使得_proto_被认为成一个键名

五、原型链污染例题分析:

 1.逻辑:

2.怎么做


一、原型链污染是什么

1.原理

简单来说,我们可以将它理解为一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。

2.例题

复现原型链污染_第1张图片

3.分析

因为在第六行我们修改了foo的原型foo.__proto__.bar = 2,而foo是一个Object类的实例,所以实际上是修改了Object这个类,给这个类增加了一个属性bar,值为2。 后来,我们又用Object类创建了一个zoo对象let zoo = {},zoo对象自然也有一个bar属性了。 所以在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染

二、prototype和_proto的分别是什么

proto属性指向当前对象的原型对象,即构造函数的prototype属性。

var obj = new object ();

obj._proto_ === object.prototype //true

obj._proto_ === obj.constructor.prototype //true

获取实例对象obj的原型对象的三种方法

1.obj.proto

2.obj.constructor.prototype

3.obj.constructor.prototype

总结:

  1.prototype是一个类的属性,所有类对象在实例化的时候将会拥有prototype中的属性和方法

      2.一个对象的__proto__属性,指向这个对象所在的类的prototype属性

三 、Javascript原型链继承

1.了解     

所有类对象在实例化的时候将会拥有prototype中的属性和方法,这个特性被用来实现              JavaScript中的继承机制。

2.例题

复现原型链污染_第2张图片

Son类继承了Father类的last_name属性,最后输出的是Name: Melania Trump

3.总结

对于对象son,在调用son.last_name的时候,实际上JavaScript引擎会进行如下操作:

  1. 在对象son中寻找last_name

  2. 如果找不到,则在son.__proto__中寻找last_name

  3. 如果仍然找不到,则继续在son.__proto__.__proto__中寻找last_name

  4. 依次寻找,直到找到null结束。比如,Object.prototype__proto__就是null

4.要点

JavaScript的这个查找的机制,被运用在面向对象的继承中,被称作prototype继承链。

以上就是最基础的JavaScript面向对象编程,牢记以下几点:

  1. 每个构造函数(constructor)都有一个原型对象(prototype)

  2. 对象的__proto__属性,指向类的原型对象prototype

  3. JavaScript使用prototype链实现继承机制

四、哪些情况下原型链会被污染?

重点:怎么设置_proto_的值,找控制数组对象的键名进行操作。

1.首先假设一个merge函数

复现原型链污染_第3张图片

2. 以上代码存在合并的过程,存在赋值的操作target[key] = source[key],那么key如果是__proto__,那么我们就可以进行原型链的污染。

                      复现原型链污染_第4张图片       

 

结论:输出结果显示原型链并没有被污染,因为创建O2的过程中_proto_已经代表o2的原型,并没有被认为是一个key,所以_proto_属性并没有生效,那么接下来看怎么解决,如何让_proto_被认为是一个键名。

3.修改命令,使得_proto_被认为成一个键名

复现原型链污染_第5张图片

结论:通过用JSON.parse的函数去定义,使得_proto_属性被当成了一个键名,此时o3也有了b属性,说明原型链已经被污染了。

五、原型链污染例题分析:

复现原型链污染_第6张图片

 1.逻辑:

用户提交的信息通过lodash.merge函数或对象的合并,用merge方法合并到session里,多次提交,session里最终保存你提交的所有信息。而这里的lodash.merge操作实际上就存在原型链污染漏洞。

这里的lodash.merge操作就存在原型链污染的漏洞,因为原型链污染有merge方法。

2.怎么做

污染原型链后,我们相当于可以给Object对象插入任意属性,这个插入的属性反应在最后的lodash.template中。

复现原型链污染_第7张图片

因为sourceurl为空字符串,因此我们通过merge方法可以污染原型链,添加一个merge sourceurl方法 ,给它赋值,通过原型链污染实现任意命令执行。给所有Object对象中都插入一个sourceURL属性。最后,这个sourceURL被拼接进new Function的第二个参数中,造成任意代码执行漏洞。再将带有__proto__的Payload以json的形式发送给后端,因为express框架支持根据Content-Type来解析请求Body,为我们注入原型提供了很大方便:

{"__proto__": {"sourceURL": "\u000areturn ()=>{for (var a in {}) {delete Object.prototype[a];}

return global.process.mainModule.constructor._load('child_process').execSync('id')}\u000a//"}}

分析:以"_proto_"的方式进行污染sourceURL,\u000areturn ()=>{for (var a in {}) {delete Object.prototype[a];}把对象里的所有属性循环出来后把他删除,再写return,通过process下的child_process执行代码,拿到模块调用函数方法,因为代码最终返回:'return ***' ,\uoooa把代码换行,\uoooa//让原来的return失效,新的return取代

你可能感兴趣的:(原型模式)