为什么谷歌在前面加上 while(1); 到他们的 JSON 响应?

IT技术 javascript json ajax security
2021-01-24 02:00:43

为什么 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&&&.

这里发生了什么?

6个回答

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

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

while(1);&&&BLAH&&&防止这样的:在一个AJAX请求mail.google.com将具有完全访问的文本内容,并且可以去除它扔掉。但是<script>标签插入盲目地执行JavaScript,没有任何处理,导致死循环或语法错误。

这并没有解决跨站点请求伪造的问题

@JakubP。反 CSRF 令牌与缓存混淆,并且需要一定数量的加密评估服务器端。在 Google 规模下,这将需要大量 CPU。这种将其卸载到客户端。
2021-03-21 02:00:43
为什么获取此数据的请求不需要 CSRF 令牌?
2021-03-26 02:00:43
不返回包含数组的对象,而不是直接返回数组,也能解决问题吗?
2021-03-30 02:00:43
@JakubP。以 Google 的规模存储和维护 CSRF 令牌需要大量的基础设施和成本。
2021-04-02 02:00:43
@PedroFelix 不,这不能解决问题,因为仍然可以执行帖子中提到的相同攻击。覆盖访问器方法以检索信息。
2021-04-06 02:00:43

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

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

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

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

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

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

有多种对策:

确保 JSON 永远不会执行

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

只有合法的页面才能真正获取整个内容,剥离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 不是有效的 JavaScript,同时仍然是有效的 JSON。

正如@hvd 在评论中指出的,空对象{}是有效的 JavaScript,知道对象为空本身可能是有value的信息。

以上方法的比较

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

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

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

OWASP 的推荐很有趣,因为它很简单。有人知道 Google 的方式更安全的原因吗?
2021-03-16 02:00:43
我相信它在任何方面都不安全。在此处提供 OWASP 似乎是 +1 的充分理由。
2021-03-16 02:00:43
我想如果您必须使用 JSONP,您可以尝试以某种巧妙(可能不安全)的方式使用 CSRF 令牌。
2021-04-05 02:00:43

这是为了确保某些其他站点无法采取令人讨厌的技巧来尝试窃取您的数据。例如,通过替换数组构造函数,然后通过<script>标签包含此 JSON URL ,恶意第三方站点可以从 JSON 响应中窃取数据。通过将 awhile(1);放在开头,脚​​本将挂起。

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

这将使第三方难以将 JSON 响应插入到带有<script>标记的 HTML 文档中请记住,该<script>标签不受同源策略的约束

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


它防止它被用作简单<script>标签的目标(好吧,它并不能阻止它,但它会让它变得不愉快。)这样坏人就不能将脚本标签放在他们自己的站点中并依靠活动会话来获取您的内容。

编辑- 注意评论(和其他答案)。这个问题与被破坏的内置设施有关,特别是ObjectArray构造函数。这些可以被改变,这样原本无害的 JSON 在解析时可能会触发攻击者代码。