为什么谷歌会预先附加 while(1);到他们的 JSON 响应?确保 JSON 从不执行确保 JSON 不是有效的 JavaScript始终返回外部带有对象的 JSON以上方法的比较

2022-08-29 21:44:46

为什么 Google 会附加到他们的(私有)JSON 响应之前?while(1);

例如,以下是在 Google 日历中打开和关闭日历时的响应:

while (1);
[
  ['u', [
    ['smsSentFlag', 'false'],
    ['hideInvitations', 'false'],
    ['remindOnRespondedEventsOnly', 'true'],
    ['hideInvitations_remindOnRespondedEventsOnly', 'false_true'],
    ['Calendar ID stripped for privacy', 'false'],
    ['smsVerifiedFlag', 'true']
  ]]
]

我认为这是为了防止人们在上面做一个,但你真正要做的就是替换它,然后你就会被设置。我假设评估预防是为了确保人们编写安全的JSON解析代码。eval()while

我也在其他几个地方看到过这个,但谷歌(邮件,日历,联系人等)更是如此。奇怪的是,Google Docs以开头,而Google Contacts似乎以.&&&START&&&while(1); &&&START&&&

这是怎么回事?


答案 1

它阻止了 JSON 劫持,这是一个主要的 JSON 安全问题,自 2011 年以来,使用 ECMAScript 5 在所有主流浏览器中都得到了正式修复

人为的例子:假设Google有一个URL,它以JSON格式返回收件箱的前50条消息。由于同源策略,其他域上的邪恶网站无法发出AJAX请求来获取此数据,但它们可以通过标记包含URL。URL 随 Cookie 一起访问,通过重写全局数组构造函数或访问器方法,只要设置了对象(数组或哈希)属性,他们就可以调用一个方法,从而允许他们读取 JSON 内容。mail.google.com/json?action=inbox<script>

或 可以防止这种情况:AJAX 请求将具有对文本内容的完全访问权限,并且可以将其剥离。但是标签插入会盲目地执行JavaScript而不进行任何处理,从而导致无限循环或语法错误。while(1);&&&BLAH&&&mail.google.com<script>

这并不能解决跨站点请求伪造的问题。


答案 2

它可以防止通过 JSON 劫持泄露响应。

从理论上讲,HTTP响应的内容受同源策略的保护:来自一个域的页面不能从另一个域上的页面获取任何信息(除非明确允许)。

攻击者可以代表您请求其他域上的页面,例如通过使用 或 标记,但它无法获取有关结果的任何信息(标头、内容)。<script src=...><img>

因此,如果您访问攻击者的页面,它将无法从 gmail.com 读取您的电子邮件。

除了使用脚本标记请求 JSON 内容时,JSON 在攻击者的控制环境中作为 JavaScript 执行。如果攻击者可以替换数组或对象构造函数或对象构造函数或对象构造函数期间使用的其他方法,则 JSON 中的任何内容都将通过攻击者的代码并被泄露。

请注意,这发生在 JSON 作为 JavaScript 执行时,而不是在解析时。

有多种对策:

确保 JSON 从不执行

通过在 JSON 数据之前放置一个语句,Google 可以确保 JSON 数据永远不会作为 JavaScript 执行。while(1);

只有合法的页面才能实际获取整个内容,去除 ,并将其余部分解析为 JSON。while(1);

例如,在Facebook上看到过类似的东西,结果也一样。for(;;);

确保 JSON 不是有效的 JavaScript

同样,在 JSON 之前添加无效标记(如 )可确保永远不会执行。&&&START&&&

始终返回外部带有对象的 JSON

这是OWASP推荐的防止JSON劫持的方法,也是侵入性较小的方法。

与前面的对策类似,它确保JSON永远不会作为JavaScript执行。

一个有效的JSON对象,当没有被任何东西包围时,在JavaScript中是无效的,因为被解释为代码块:{ }

eval('{"foo":"bar"}')
// SyntaxError: Unexpected token :

但是,这是有效的 JSON:

JSON.parse('{"foo":"bar"}')
// Object {foo: "bar"}

因此,确保始终在响应的顶层返回对象可确保 JSON 不是有效的 JavaScript,同时仍然是有效的 JSON。

正如@hvd在注释中指出的那样,空对象是有效的JavaScript,知道对象是空的可能本身就是有价值的信息。{}

以上方法的比较

OWASP 方式的侵入性较小,因为它不需要更改客户端库,并且可以传输有效的 JSON。但是,目前还不确定过去或将来的浏览器错误是否可以击败它。正如@oriadam所指出的,目前尚不清楚数据是否可以通过错误处理(例如window.onerror)在解析错误中泄漏。

Google的方式需要一个客户端库,以便它支持自动反序列化,并且可以认为在浏览器错误方面更安全。

这两种方法都需要服务器端更改,以避免开发人员意外发送易受攻击的 JSON。