闭包提权:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var o = (function() { var obj = { a: 1, flag: "flag{test}", }; return { get: function(k) { return obj[k]; }, add: function() { n++; } }; } )();
console.log(o.get("flag")) // flag{test}
|
首先,这里通过闭包实现了将obj这个对象让外面不可更改。实现只读的效果。
作用:比如在有些环境下,如第三方库当中,需要保持稳定性,防止一个库被另一个库修改。
利用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| console.log(o.get("valueOf")) //[Function: valueOf]
console.log(o.get("valueOf")()) // TypeError: Cannot convert undefined or null to objec // 由于valueOf是Object.prototype的方法,所以在调用时,this指向的是Object.prototype,而Object.prototype并没有flag属性,所以会报错
//定义一个原型,让obj[k]能拿到这个原型,然后返回this指向obj Object.defineProperty(Object.prototype, "hacker", { get: function() { return this; } }); console.log(o.get("flag")) // flag{test}
console.log(o.get("hacker")) // { a: 1, flag: 'flag{test}' } let obj1 = o.get("hacker"); obj1.flag = 2;
console.log(o.get("flag")) // 2
if (o.get("flag") !== "flag{test}") { console.log("flag is correct!"); } // flag is correct!
|
利用成功
防御的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| //防御1 var o = (function() { var obj = { a: 1, flag: "flag{test}", }; Object.setPrototypeOf(obj, null); return { get: function(k) { return obj[k]; }, }; } )();
//防御2,如果obj要使用它的原型的话可以用以下方法 var o = (function() { var obj = { a: 1, flag: "flag{test}", }; // Object.setPrototypeOf(obj, null); return { get: function(k) { if(obj.hasOwnProperty(k)){ return obj[k]; } }, }; } )();
|