我正在使用 Backbone.js 和 Tornado 网络服务器。在 Backbone 中接收集合数据的标准行为是作为 JSON 数组发送。
另一方面,由于以下漏洞,Tornado 的标准行为是不允许 JSON Array 的:
http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
相关的是: http://haacked.com/archive/2009/06/25/json-hijacking.aspx
当我的 JSON 确实是一个对象列表时,不必将我的 JSON 包装在一个对象中,这对我来说感觉更自然。
我无法在现代浏览器(即当前的 Chrome、Firefox、Safari 和 IE9)中重现这些攻击。同时,我无法确认现代浏览器在任何地方都解决了这些问题。
为了确保我不会被任何可能糟糕的编程技能或糟糕的谷歌搜索技能误导:
这些 JSON 劫持攻击在现代浏览器中是否仍然是一个问题?
(注意:很抱歉可能与 Is it possible to do 'JSON hijacking' on modern browser? 重复,但由于接受的答案似乎无法回答问题 - 我认为是时候再问一次并获得更清晰的解释了。)
最佳答案
不,不再可能在 Firefox 21、Chrome 27 或 IE 10 中捕获传递给 []
或 {}
构造函数的值。这里有一点测试页面,基于 http://www.thespanner.co.uk/2011/05/30/json-hijacking/ 中描述的主要攻击:
( 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
并向 Object.prototype.foo
添加一个 setter,并通过短格式和长格式测试初始化数组和对象。
ES4 spec ,在第 1.5 节中,“要求使用 Object 和 Array 的全局标准绑定(bind)来为对象和数组初始值设定项构造新对象”,并在实现先例中指出“Internet Explorer 6、Opera 9.20 和 Safari 3 都不尊重Object 和 Array 的本地或全局重新绑定(bind),但使用原始的 Object 和 Array 构造函数。”这保留在 ES5, section 11.1.4 .
Allen Wirfs-Brock explained ES5 还指定对象初始化不应该触发 setter,因为它使用了 DefineOwnProperty。 MDN: Working with Objects注意到“从 JavaScript 1.8.1 开始,在对象和数组初始值设定项中设置属性时不再调用 setter。”这已在 V8 issue 1015 中得到解决.
https://stackoverflow.com/questions/16289894/