不,不再可能在 Firefox 21、Chrome 27 或 IE 10 中捕获传递给[]
or{}
构造函数的值。这是一个小测试页面,基于http://www.thespanner.co.uk中描述的主要攻击/2011/05/30/json 劫持/:
( http://jsfiddle.net/ph3Uv/2/ )
var capture = function() {
var ta = document.querySelector('textarea')
ta.innerHTML = '';
ta.appendChild(document.createTextNode("Captured: "+JSON.stringify(arguments)));
return arguments;
}
var original = Array;
var toggle = document.body.querySelector('input[type="checkbox"]');
var toggleCapture = function() {
var isOn = toggle.checked;
window.Array = isOn ? capture : original;
if (isOn) {
Object.defineProperty(Object.prototype, 'foo', {set: capture});
} else {
delete Object.prototype.foo;
}
};
toggle.addEventListener('click', toggleCapture);
toggleCapture();
[].forEach.call(document.body.querySelectorAll('input[type="button"]'), function(el) {
el.addEventListener('click', function() {
document.querySelector('textarea').innerHTML = 'Safe.';
eval(this.value);
});
});
<div><label><input type="checkbox" checked="checked"> Capture</label></div>
<div><input type="button" value="[1, 2]" /> <input type="button" value="Array(1, 2);" /> <input type="button" value="{foo: 'bar'}" /> <input type="button" value="({}).foo = 'bar';" /></div>
<div><textarea></textarea></div>
它覆盖window.Array
并添加一个setter,Object.prototype.foo
并通过short 和long 形式测试初始化数组和对象。
ES4 规范在第1.5 节中“要求使用 Object 和 Array 的全局标准绑定来为对象和数组初始化器构造新对象”,并在 Implementation Precedent 中指出“Internet Explorer 6、Opera 9.20 和 Safari 3 可以不尊重 Object 和 Array 的本地或全局重新绑定,而是使用原始的 Object 和 Array 构造函数。” 这保留在ES5 的第 11.1.4 节中。
Allen Wirfs-Brock 解释说 ES5 还指定对象初始化不应触发 setter,因为它使用 DefineOwnProperty。MDN:Working with Objects指出“从 JavaScript 1.8.1 开始,在对象和数组初始化程序中设置属性时不再调用 setter。” 这已在V8 问题 1015中得到解决。