开发者问题收集

为什么 Google 会在其 JSON 响应前面添加 while(1);?

2010-04-19
601358

为什么 Google 要将 while(1); 添加到其(私有)JSON 响应中?

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

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

我认为这是为了防止人们在其上执行 eval() ,但您真正需要做的就是替换 while ,然后就可以了。我认为 eval 预防是为了确保人们编写安全的 JSON 解析代码。

我也在其他几个地方看到过这种用法,但在 Google(邮件、日历、通讯录等)中使用得更多。奇怪的是, Google Docs &&&START&&& 开头,而 Google 通讯录似乎以 while(1); &&&START&&& 开头。

这是怎么回事?

3个回答

它可以防止 JSON 劫持 ,这是一个重大的 JSON 安全问题,自 2011 年起,该问题已在所有主流浏览器中通过 ECMAScript 5 正式 修复

人为示例:假设 Google 有一个 URL,如 mail.google.com/json?action=inbox ,它会以 JSON 格式返回收件箱中的前 50 封邮件。由于同源策略,其他域中的恶意网站无法发出 AJAX 请求来获取此数据,但它们可以通过 <script> 标记包含 URL。该 URL 使用 您的 cookie 进行访问,并且通过 覆盖全局数组构造函数或访问器方法 ,它们可以在设置对象(数组或哈希)属性时调用一个方法,从而允许它们读取 JSON 内容。

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

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

rjh
2010-04-19

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

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

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

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

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

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

有多种对策:

确保 JSON 永远不会执行

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

只有合法页面才能真正获取整个内容,删除 while(1); ,并将剩余部分解析为 JSON。

例如,在 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。

Arnaud Le Blanc
2014-02-02

这是为了确保其他网站无法使用恶意手段窃取您的数据。例如,通过 替换数组构造函数 ,然后通过 <script> 标记包含此 JSON URL,恶意第三方网站可以从 JSON 响应中窃取数据。通过在开头放置 while(1); ,脚本将挂起。

另一方面,使用 XHR 和单独的 JSON 解析器的同一站点请求可以轻松忽略 while(1); 前缀。

bdonlan
2009-05-16