重写内置对象的原型方法,外部代码可以通过重写代码达到暴漏和修改已绑定参数的函数。这在es5的方法下使用polyfill
时是一个严重的安全问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function bind(fn) { var prev = Array.prototype.slice.call(arguments, 1); return function bound() { var curr = Array.prototype.slice.call(arguments, 0); var args = Array.prototype.concat.apply(prev, curr); return fn.apply(null, args); }; }
function unapplyAttack() { var concat = Array.prototype.concat; Array.prototype.concat = function replaceAll() { Array.prototype.concat = concat; var curr = Array.prototype.slice.call(arguments, 0); var result = concat.apply([], curr); return result; }; }
|
上面的函数声明忽略了函数bind的prev
参数,意味着调用unapplyAttack
之后首次调用.concat
将会抛出错误。
使用Object.freeze,可以使对象不可变,你可以防止任何内置对象原型方法被重写。
1 2 3 4 5 6 7 8
| (function freezePrototypes() { if (typeof Object.freeze !== 'function') { throw new Error('Missing Object.freeze'); } Object.freeze(Object.prototype); Object.freeze(Array.prototype); Object.freeze(Function.prototype); }());
|
你可以在这里阅读更多关于unapply攻击。