JSON劫持仍然是现代浏览器中的问题吗?


149

我正在使用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劫持攻击是否在当今的浏览器中仍然是一个问题?

(注意:很抱歉,可能存在以下重复项:是否可以在现代浏览器中进行“ JSON劫持”? 但是由于接受的答案似乎无法回答问题-我认为是时候再次询问并获得一些更清晰的解释)


使用eval吗?如果没有任何改变或改变主干解析响应的方式,那么您应该很安全
Deeptechtons,

10
一般而言,您绝对不应以有人将使用“现代”浏览器为前提来实现网络安全。
路加福音

7
@Luke-请参阅下面对Reid的评论。总的来说很重要-但是我不是在问一般的安全性问题。(我的用户仅在使用现代浏览器的情况下才能够进行身份验证。)
Rocketman

4
@Luke,有时我们必须继续前进,并允许我们以现代模式进行开发(在这种情况下为REST:在这种情况下,获取数据是GET操作,不应以其他方式进行),而如果现在看来仅适用于旧威胁,则无法防范旧威胁面向少数听众。因此,这个问题非常有价值,可以让人们评估他是否可以忽略其应用案例中的这种威胁。在某些时候,使用非常过时的软件的用户很可能会面临其他威胁(恶意软件),因此我们无论如何也无法从中保护它们。
弗雷德里克

2
@jpaugh,您在哪里看到这样的假设?我只是稍微假设那些拥有这种过时软件的人是“不可保护的”。(关于证明我的溜冰鞋的价格合理,我已经习惯了将其价格的三分之一用于碳速滑冰鞋,而这种碳黑速滑冰鞋的磨损时间不到我要花掉我现有冰刀的时间的三分之一。无论如何,我认为它们值得,只要您喜欢骑马,这就是我的情况。)
Frédéric18年

Answers:


112

不,不再可能捕获在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和添加一个setter Object.prototype.foo并通过短和长格式测试数组和对象的初始化。

ES4规范,在第1.5节,“需要的对象和阵列的全球性的,标准绑定到被用于构建用于对象和数组的初始化新对象”在实施先例与指出,“Internet Explorer 6中,歌剧9.20,和Safari 3执行不尊重Object和Array的本地或全局重新绑定,而是使用原始的Object和Array构造函数。” ES5第11.1.4节中保留了该内容。

Allen Wirfs-Brock解释说,ES5还指定对象初始化不应该触发设置方法,因为它使用DefineOwnProperty。MDN:使用对象指出:“从JavaScript 1.8.1开始,在对象和数组初始化程序中设置属性时不再调用setter。” V8问题1015中已解决此问题


28
早在2009年,Brendan Eich建议浏览器不要评估用作application / json(bugzilla.mozilla.org/show_bug.cgi?id=376957#c75)的脚本,这在我看来仍然是一个好主意。

2
请注意,盲目POST CSRF仍然可以使用表单,尤其是使用文本/纯文本编码时,需要使用令牌/随机数来消除。

1
是POST CSRF。感谢您在这里提供的所有重要信息。
Rocketman

5
当您的陈述仅涉及数组构造函数的覆盖时,您的陈述是正确的。但是,Microsoft的IE和Edge仍然容易受到UTF-7 JSON劫持的攻击。最近对其进行了测试(今天又很有趣),并且仍然有效。
user857990 '16

2
同样感谢UTF-16BE,感谢Gareth Heyes,blog.portswigger.net
2016/11 /
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.