JSON Hijacking在现代浏览器中仍然是一个问题吗?

时间:2013-04-29 23:28:45

标签: javascript json security browser tornado

我正在使用Backbone.js和Tornado Web服务器。在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包装在一个对象中,这感觉更自然。

我无法在现代浏览器中重现这些攻击(即当前的Chrome,Firefox,Safari和IE9)。与此同时,我无法确认现代浏览器解决这些问题的任何地方。

确保我既不会误导任何糟糕的编程技巧也不会误导谷歌搜索技能:

现在这些JSON劫持攻击在现代浏览器中仍然存在问题吗?

(注意:很抱歉可能重复:Is it possible to do 'JSON hijacking' on modern browser?,但由于接受的答案似乎没有回答这个问题 - 我认为现在是时候再问一遍并得到一些更明确的解释。)

1 个答案:

答案 0 :(得分:102)

不,不再可能捕获传递给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,并通过短格式和长格式测试初始化​​数组和对象。

{1.5}中的ES4 spec“需要使用Object和Array的全局标准绑定来构造对象和数组初始化器的新对象”,并在实现先例中注意到“Internet Explorer 6,Opera 9.20,Safari 3不尊重Object和Array的本地或全局重新绑定,而是使用原始的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中解决。