JavaScript 原型链污染探讨
如果你想弄明白什么怎样才可以实现 JavaScript 的原型链污染,那么你首先需要弄清楚两个东西,那就是__proto__
和prototype
。
到底什么才是__proto__
和prototype
?
那我们先来看看比较官方的说法吧:
在这个例子中,obj
是通过Object
构造函数创建的,所以obj.__proto__
指向Object.prototype
。
那我们可以这样去理解,prototype 是类通有的属性,当类被实例化为对象后,对象会拥有 prototype 中的属性和方法。当对象想去访问类的原型时用__proto__
属性来访问类的原型。
prototype 链
了解了__proto__
和prototype
之后,那我们就要去深入了解 JavaScript 的继承链,在 JavaScript 中,每个对象都有一个指向其原型的内部链接(即__proto__
),这个原型本身也是一个对象,通常还有自己的原型,这样就形成了一条原型链。当你访问一个对象的属性时,JavaScript 会沿着这条原型链逐级查找,直到找到该属性或者原型链的顶端(即 Object.prototype)。
实例化 Animal 类创建了 dog 对象,当访问 speak 属性时,在 dog 中寻找不到时,会在dog.__proto__.__proto__
中寻找,发现dog.__proto__.__proto__
中有 speak 属性,也就是Something.prototype
中存在 speak 属性。也就是说 JavaScript 使用 prototype 链实现继承机制。
prototype 链污染(原型链污染)
那我们学习继承、prototype 链不就是为了进行链子污染,然后得到我们想得到的东西吗?
既然dog.__proto__.__proto__
指向创建该对象的构造函数的原型对象(Something.prototype
)。那么我们修改dog.__proto__.__proto__
的内容是不是可以进而实现了修改 Something 类。
示例:
通过这个结果我们可以看出我们轻易的将dog.__proto__.__proto__
的 speak 值进行了更改。我们先将这个继承链给搞出来:
那么攻击者如果通过一个入口点,控制并修改了一个对象的原型,那么将可能影响所有和这个对象来自同一个类、父类直到 Object 类的对象。
典型的便是 merge 操作导致原型链污染:
在 JSON 解析的情况下,__proto__
会被认为是一个真正的“键名”,而不代表“原型”,所以在遍历 object2 的时候会存在这个键。
文章转载自:weljoni
评论