javascript prototype pollution

前言:

​ Prototype pollution是一个老生常谈的问题了;JavaScript是一门非常灵活的语言,在某些方面可能比PHP更加灵活。所以,除了一些sql注入和代码执行等注入型漏洞外,也会有一些独有的安全问题,比如prototype polllution。

正文:

​ 说javascript灵活是因为一般的OOP语言会使用class关键字进行模版的定义,从这个class去实例化的对象都会自然的继承了模版中相应的属性;但是javascrip可以支持直接定义一个对象;大可不必要提前定义模版;

owNrFI.png

​ 可以鲜明的看到直接定义了一个对象,当去尝试new的时候会抛出错误“不是构造器”;当然也可通过构造函数去定义一个模版,后期可以批量的实例化对象;

比如如下的代码定义一个类;用“构造函数”定义一个模版,后期可以批量的实例化对象;

1
2
3
4
function s1mple(){
this.test='javascript prototype pollution'
this.work='search'
}

定义了一个s1mple构造器,相当也定义了一个class;其中test和work是属性;

owaP5n.png

可以看到效果是等效的;

Prototype

​ 每一个函数对象都会有一个prototype属性;指向它实例化的原型;使用该构建函数实例化对象时,会继承该原型中的属性及方法。

__proto__:

所有对象都有一个__proto__属性;它指向了构建它的函数的原型;即:s1mple.prototye==c.__proto__

函数的prototype是原型对象;原型对象也是普通对象;所以也一般实例一样,也具有__proto__属性;

owrSbT.png

constructor:

原型对象的constructor属性指向和它相关联的构造函数;

owBXnK.png

原型链:

javascript的继承机制就是由原型链来实施的;比如如下的代码;

owOMTS.png

owODfJ.png

​ 可以看到,我们将s2mple构建函数的prototype设置成s1mple对象,此时s2mple就会继承了s1mple对象的属性;其实本质就是,将s2mple的原型设置成s1mple对象,当在s2mple对象中调用某个属性的时候如果在s2mple中没有找到,则会去自动触发s2mple对象的__proto__去原型里去寻找,这里设置成了s1mple,所以就直接到s1mple对象中找;最后返回s1mple对象中的值;通过原型链将两个类对象进行串联,使其有继承关系;以此类推直到Object.prototype的__proto__就是null;

原型链污染:

​ js通过原型链索引一个对象的属性和方法,上面了解了原型;分析了其机制;那么就会产生一个问题;如果可以给某些类的原型加上某些属性或者方法;那么继承它的对象就都会有此属性或者方法;如果给Object加上的话,那么所有的对象都会受到污染;这样就可以覆盖某些变量,实际中可绕过某些验证;

1
2
3
4
var cc = {"a":"b"}
cc.__proto__.c='d'
cc.c
'd'

o0kBb4.png

这里可以清晰的看到用原来的对象去访问相应的c属性;会到相应的原型下去进行访问获取;那么如果再次实例化对象的时候因为原型对象已经被插入恶意数据,那么新对象也会被污染,具体看下图:

o0ACin.png

可以看到已经被污染;