网站建设后期维护流程网页制作教程软件
__proto__
一个Foo类实例化出来的foo对象,可以通过foo.__proto__属性来访问Foo类的原型,也就是说:
foo.__proto__= Foo.prototype 对象 构造函数
所以,总结一下:
-
prototype是一个类的属性,所有类对象在实例化的时候将会拥有prototype中的属性和方法 -
一个对象的
__proto__属性,指向这个对象所在的类的prototype属性 -
每个构造函数(constructor)都有一个原型对象(prototype)
-
对象的
__proto__属性,指向类的原型对象prototype -
JavaScript使用prototype链实现继承机制
原型链污染是什么
之前说到foo.__proto__指向的是Foo类的prototype。那么,如果我们修改了foo.__proto__中的值,是不是就可以修改Foo类呢?
做个简单的实验:
// foo是一个简单的JavaScript对象
let foo = {bar: 1}
// foo.bar 此时为1
console.log(foo.bar)
// 修改foo的原型(即Object)
foo.__proto__.bar = 2
// 由于查找顺序的原因,foo.bar仍然是1
console.log(foo.bar)
// 此时再用Object创建一个空的zoo对象
let zoo = {}
// 查看zoo.bar
console.log(zoo.bar)
最后,虽然zoo是一个空对象{},但zoo.bar的结果居然是2
原因也显而易见:因为前面我们修改了foo的原型foo.__proto__.bar = 2,而foo是一个Object类的实例,所以实际上是修改了Object这个类,给这个类增加了一个属性bar,值为2。
后来,我们又用Object类创建了一个zoo对象let zoo = {},zoo对象自然也有一个bar属性了。
那么,在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。
mess.js
(function()
{var secret = ["aaa","bbb"];secret.forEach();
})();
attach.html
<body><script>Array.prototype.forEach = function(){var result = "result:";for(var i = 0,length = this.length;i<length;i++){result += this[i];result += " ";}document.write(result);}</script><script src="./mess.js"></script>
</body>
</html>
