【问题标题】:Is JSON Hijacking still an issue in modern browsers?JSON 劫持在现代浏览器中仍然是一个问题吗?
【发布时间】:2013-04-23 18:47:47
【问题描述】:

我正在使用 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?,但由于接受的答案似乎没有回答问题 - 我认为是时候再问一次并获得一些更清晰的解释了。)

【问题讨论】:

  • 使用评估?那么可能,否则不。如果主干解析响应的方式没有任何改变或改变,那么你应该是安全的
  • 一般来说,您永远不应该假设某人将使用“现代”浏览器来处理网络安全问题。
  • @Luke - 请参阅下面对 Reid 的评论。总的来说很重要 - 但我不是在问一般的安全问题。 (我的用户只有首先使用现代浏览器才能进行身份验证。)
  • @Luke,有时我们必须继续前进并允许我们使用现代模式进行开发(例如这种情况下的 REST :获取数据是一种 GET 操作,不应该是其他东西)而不保护旧模式如果它们现在似乎只适用于一小部分受众,则威胁。所以这个问题真的很有价值,可以让人们评估他是否可以在他的应用案例中忽略这个威胁。在某些时候,使用非常过时的软件的用户很可能遇到其他类型的威胁(恶意软件),我们无论如何都无法保护他们。
  • @jpaugh,你在哪里看到这样的假设?我只是在某种程度上假设那些拥有这种过时软件的人无论如何都是“无法保护的”。 (关于证明我的溜冰鞋的成本是合理的,我已经习惯于将其价格的三分之一用于碳纤维速滑鞋,这些碳纤维速滑鞋在我磨损现有溜冰鞋所需的时间不到三分之一的时间内就磨损了。无论如何,我认为它们是值得的,前提是您喜欢骑它们,这是我的情况。)

标签: javascript json security browser tornado


【解决方案1】:

不,不再可能在 Firefox 21、Chrome 27 或 IE 10 中捕获传递给 []{} 构造函数的值。这是一个小测试页面,基于 @987654321 中描述的主要攻击@:

(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 的全局标准绑定来为对象和数组初始值设定项构造新对象”,并在实施先例中指出“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 解决了这个问题。

【讨论】:

  • 早在 2009 年,Brendan Eich 就建议浏览器不评估作为 application/json (bugzilla.mozilla.org/show_bug.cgi?id=376957#c75) 的脚本,这对我来说仍然是个好主意。
  • 请注意,仍然可以使用表单进行盲 POST CSRF,尤其是使用 text/plain 编码,并且需要使用令牌/随机数来击败。
  • 对 POST CSRF 表示同意。感谢您在这里提供的所有重要信息。
  • 您的说法是正确的,因为它只是简单地覆盖了 Array 构造函数。微软的 IE 和 Edge 仍然容易受到 UTF-7 JSON 劫持的影响。最近测试过(今天又是为了好玩),它仍然有效。
  • UTF-16BE 也是如此,感谢 Gareth Heyes,blog.portswigger.net/2016/11/json-hijacking-for-modern-web.html
猜你喜欢
  • 2012-01-25
  • 2014-11-03
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 2013-10-07
  • 2015-06-28
  • 2010-09-06
相关资源
最近更新 更多