JSON 劫持在现代浏览器中仍然是一个问题吗? [英] Is JSON Hijacking still an issue in modern browsers?

查看:23
本文介绍了JSON 劫持在现代浏览器中仍然是一个问题吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Backbone.js 和 Tornado Web 服务器.在 Backbone 中接收集合数据的标准行为是作为 JSON 数组发送.

另一方面,由于以下漏洞,Tornado 的标准行为是不允许 JSON 数组:

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 劫持"? 但由于接受的答案似乎没有回答这个问题 - 我认为是时候再次提问并获得更清晰的解释了.)

解决方案

不,不再可能捕获传递给 []{} 构造函数的值在 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)));返回参数;}var 原始 = 数组;var toggle = document.body.querySelector('input[type="checkbox"]');var toggleCapture = function() {var isOn = toggle.checked;window.Array = isOn ?捕获:原始;如果(isOn){Object.defineProperty(Object.prototype, 'foo', {set: capture});} 别的 {删除 Object.prototype.foo;}};toggle.addEventListener('click', toggleCapture);切换捕获();[].forEach.call(document.body.querySelectorAll('input[type="button"]'), function(el) {el.addEventListener('点击', function() {document.querySelector('textarea').innerHTML = 'Safe.';评估(this.value);});});

它覆盖了 window.Array 并向 Object.prototype.foo 添加了一个 setter 并通过短格式和长格式测试初始化​​数组和对象.

ES4 规范,在第 1.5 节中,要求全球标准用于构造对象和数组初始值设定项的新对象的对象和数组的绑定",并在实现先例中指出Internet Explorer 6、Opera 9.20 和 Safari 3 不尊重对象和数组的本地或全局重新绑定,但使用原始的 Object 和 Array 构造函数."这保留在 ES5,第 11.1.4 节中.

Allen Wirfs-Brock 解释说 ES5 也指定对象初始化不应触发 setter,因为它使用 DefineOwnProperty.MDN:使用对象 指出从 JavaScript 1.8.1 开始,在对象和数组初始值设定项中设置属性时不再调用 setter."这已在 V8 问题 1015 中得到解决.

I am using Backbone.js and the Tornado web server. The standard behavior for receiving collection data in Backbone is to send as a JSON Array.

On the other hand, Tornado's standard behavior is to not allow JSON Array's due to the following vulnerability:

http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx

A related one is: http://haacked.com/archive/2009/06/25/json-hijacking.aspx

It feels more natural for me to not have to wrap up my JSON in an object when it really is a list of objects.

I was unable to reproduce these attacks in modern browsers (i.e. current Chrome, Firefox, Safari, and IE9). At the same time I was unable to confirm anywhere that modern browsers had addressed these issues.

To ensure that I am mislead neither by any possible poor programming-skills nor poor googling-skills:

Are these JSON Hijacking attacks still an issue today in modern browsers?

(Note: Sorry for the possible duplicate to: Is it possible to do 'JSON hijacking' on modern browser? but since the accepted answer does not seem to answer the question - I thought it was time to ask it again and get some clearer explanations.)

解决方案

No, it is no longer possible to capture values passed to the [] or {} constructors in Firefox 21, Chrome 27, or IE 10. Here's a little test page, based on the main attacks described in 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>

It overrides window.Array and adds a setter to Object.prototype.foo and tests initializing arrays and objects via the short and long forms.

The ES4 spec, in section 1.5, "requires the global, standard bindings of Object and Array to be used to construct new objects for object and array initializers" and notes in Implementation Precedent that "Internet Explorer 6, Opera 9.20, and Safari 3 do not respect either local or global rebindings of Object and Array, but use the original Object and Array constructors." This is retained in ES5, section 11.1.4.

Allen Wirfs-Brock explained that ES5 also specifies that object initialization should not trigger setters, as it uses DefineOwnProperty. MDN: Working with Objects notes that "Starting in JavaScript 1.8.1, setters are no longer called when setting properties in object and array initializers." This was addressed in V8 issue 1015.

这篇关于JSON 劫持在现代浏览器中仍然是一个问题吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆