为什么 Google 会优先使用 while(1); 他们的 JSON 响应?

为什么 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 ,然后进行设置。我认为评估的目的是确保人们编写安全的 JSON 解析代码。

我已经看到了这个用在其他几个地方也一样,但很多更使谷歌(邮件,日历,联系人等),奇怪的是, 谷歌文档开头&&&START&&& ,而是和谷歌联系人似乎开始与while(1); &&&START&&&

这里发生了什么?

答案

它可以防止JSON 劫持 ,这是自 2011 年以来使用 ECMAScript 5 在所有主要浏览器中正式修复的主要 JSON 安全问题。

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

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

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

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

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

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

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

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

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

有多种对策:

确保 JSON 从不执行

通过放置while(1);在 JSON 数据之前的声明,Google 确保 JSON 数据永远不会作为 Javascript 执行。

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

for(;;);例如在 Facebook 上看到的结果相同。

确保 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"}

因此,请确保始终在响应的顶级返回一个 Object,以确保 JSON 无效,而 JSON 仍然有效。

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

以上方法比较

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

Google 的方法需要客户端库才能支持自动反序列化,并且可以认为它相对于浏览器错误更安全。

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

这是为了确保其他某些站点无法采取令人讨厌的手段来窃取您的数据。例如,通过替换数组构造函数 ,然后通过<script>标记包括此 JSON URL,恶意的第三方站点可能会从 JSON 响应中窃取数据。通过放置while(1);在开始时,脚本将挂起。

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

这将使第三方很难使用<script>标签将 JSON 响应插入 HTML 文档。请记住, <script>标记不受相同来源策略的限制

注意 :从 2019 年开始,导致该问题中讨论的预防措施的许多旧漏洞不再是现代浏览器中的问题。我将以下答案保留为历史上的好奇心,但实际上自 2010 年问起以来,整个主题已发生了根本变化(!!)。


它防止将其用作简单<script>标记的目标。 (嗯,这并不能阻止它,但是却使它不愉快。)那样,坏蛋就不能只将脚本标记放在自己的站点中,而是依靠活动会话来获取内容。

编辑 - 注意评论(和其他答案)。这个问题与颠覆的内置功能有关,尤其是ObjectArray构造函数。可以对其进行更改,以使否则解析时无害的 JSON 可能会触发攻击者代码。

由于<script>标记免于在网络世界中的安全性必需的 Same Origin Policy,因此while(1)当添加到 JSON 响应时,可以防止在<script>标记中滥用它。