通过一道题认识到这个漏洞
[GYCTF2020]Ez_Express 1
于是就学了一下
首先呢JavaScript是一门灵活的语言,基于原型实现继承,原型是Javascript的继承的基础。
对于原型的理解可以类似为java语言里的类和对象的关系,对象是类的实例化,类就是对象的原型。
原型是Javascript的继承的基础
在js中我们构建一个类如下
function Test() {
this.test = "test"
}
构造了一个Test类
在js中每个实例对象都有一个私有属性__proto__ 这个属性是每一个实例对象都具有的
而__proto__指向它的构造函数的原型prototype也就是
现在我们实例化了一个对象test1,
test1.__proto__ == Test.prototype
也就是实例化的对象的属性的__proto__等于类的 prototype
那么如果能修改类实例属性,是不是就能修改类的相关信息呢?
可能你觉得只是相等而已,其实这里面有个指针,当其中一个变了另一个也会变(__proto__或prototype)
请看一下案例
这里修改test2.__proto__ 之后test1.b也被赋予了值
这就要知道是怎么去给它赋值的
是因为:对于对象test1,在调用test1.b的时候,实际上JavaScript引擎会进行如下操作:
1.在对象test1中寻找b
2.找不到,在test1.__proto__中寻找b(这里的test1.__proto__同样指向Test的原型prototype)
3.如果仍然找不到,则继续在test1.__proto__.__proto__中寻找b
4.依次寻找,直到找到null结束。比如,Object.prototype的__proto__就是null
所以说我们可以发现事情的端倪了,然后加以利用
那么在Javascript中,我们何时可以控制实例对象的__proto__来污染原型链呢,只要找到可以控制数组(对象)的键名的位置即可,比如
1.对象clone
2.对象merge
以merge举例,要使__proto__作为key被赋值,还需要一个条件为传递的参数需要是以json来做解析,否则__proto__会被当作原型而不是一个key,故也就无法成功污染
也就是说如果看到clone或者merge就有可能存在原型链污染
这里直接用前辈的实例举例子
直接赋值,污染原型链失败:
使用Json.parse,污染成功
也就是说我们可能通过实例修改类的相关值了
大体思路就是这样
本文是由前辈文章加以解释修改的原文:初探JavaScript原型链污染 - Escape-w - 博客园 (cnblogs.com)