目录
一、原型链污染是什么
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.怎么做
简单来说,我们可以将它理解为一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。
因为在第六行我们修改了foo的原型foo.__proto__.bar = 2
,而foo是一个Object类的实例,所以实际上是修改了Object这个类,给这个类增加了一个属性bar,值为2。 后来,我们又用Object类创建了一个zoo对象let zoo = {}
,zoo对象自然也有一个bar属性了。 所以在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。
var obj = new object ();
obj._proto_ === object.prototype //true
obj._proto_ === obj.constructor.prototype //true
1.obj.proto
2.obj.constructor.prototype
3.obj.constructor.prototype
1.prototype
是一个类的属性,所有类对象在实例化的时候将会拥有prototype
中的属性和方法
2.一个对象的__proto__
属性,指向这个对象所在的类的prototype
属性
所有类对象在实例化的时候将会拥有prototype
中的属性和方法,这个特性被用来实现 JavaScript中的继承机制。
Son类继承了Father类的last_name
属性,最后输出的是Name: Melania Trump
。
对于对象son,在调用son.last_name
的时候,实际上JavaScript引擎会进行如下操作:
在对象son中寻找last_name
如果找不到,则在son.__proto__
中寻找last_name
如果仍然找不到,则继续在son.__proto__.__proto__
中寻找last_name
依次寻找,直到找到null
结束。比如,Object.prototype
的__proto__
就是null
JavaScript的这个查找的机制,被运用在面向对象的继承中,被称作prototype继承链。
以上就是最基础的JavaScript面向对象编程,牢记以下几点:
每个构造函数(constructor)都有一个原型对象(prototype)
对象的__proto__
属性,指向类的原型对象prototype
JavaScript使用prototype链实现继承机制
重点:怎么设置_proto_的值,找控制数组对象的键名进行操作。
target[key] = source[key]
,那么key如果是__proto__
,那么我们就可以进行原型链的污染。结论:输出结果显示原型链并没有被污染,因为创建O2的过程中_proto_已经代表o2的原型,并没有被认为是一个key,所以_proto_属性并没有生效,那么接下来看怎么解决,如何让_proto_被认为是一个键名。
结论:通过用JSON.parse的函数去定义,使得_proto_属性被当成了一个键名,此时o3也有了b属性,说明原型链已经被污染了。
用户提交的信息通过lodash.merge函数或对象的合并,用merge方法合并到session里,多次提交,session里最终保存你提交的所有信息。而这里的lodash.merge
操作实际上就存在原型链污染漏洞。
这里的lodash.merge操作就存在原型链污染的漏洞,因为原型链污染有merge方法。
污染原型链后,我们相当于可以给Object对象插入任意属性,这个插入的属性反应在最后的lodash.template
中。
因为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取代