为什么Google在他们的JSON响应前面加上这时候(1);?

为什么Google在他们的(私有)JSON响应前面加上while(1);

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

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

我假设这是为了防止人们对其进行eval()操作,但您真正需要做的就是替换while,然后您就会被设置。我假设灰度预防是为了确保人们编写安全的JSON解析代码。

我在其他几个地方也看到过这种情况,但在Google(邮件,日历,联系人等)中更是如此奇怪的是,googledocs&&&START&&&开头,而Google通讯录似乎以while(1); &&&START&&&开头。

这是怎么回事?

580770 次浏览

这是为了确保其他网站不会做一些令人讨厌的伎俩来窃取您的数据。例如,通过替换数组构造函数,然后通过<script>标签包含此JSON URL,恶意的第三方网站可以从JSON响应中窃取数据。通过在开头放置while(1);,脚本将挂起。

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

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


它可以防止它被用作简单的<script>标签的目标。(好吧,它不能阻止它,但它会让它变得不愉快。)这样坏人就不能只是把脚本标签放在他们自己的网站上,然后依靠一个活动会话来获取你的内容。

编辑-注意注释(和其他答案)。该问题与颠覆性的内置设施有关,特别是ObjectArray构造函数。这些可以被更改,以便在解析时无害的JSON可能会触发攻击者代码。

这将使第三方难以将JSON响应插入到带有<script>标记的超文本标记语言文档中。请记住,<script>标记不受同源政策的约束。

它可以防止JSON劫持,这是一个主要的JSON安全问题,在所有主要浏览器中正式排名第一,使用ECMAScript 5排名第二。

人造示例:假设Google有一个像mail.google.com/json?action=inbox这样的URL,它以JSON格式返回收件箱的前50条消息。由于主域同源策略,其他域上的邪恶网站无法发出AJAX请求来获取此数据,但它们可以通过<script>标签包含URL。URL使用 cookie访问,到覆盖全局数组构造函数或访问器方法,它们可以在设置对象(数组或哈希)属性时调用一个方法,允许它们读取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永远不会执行

通过在JSON数据之前放置while(1);语句,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,知道对象是空的本身可能是有价值的信息。

上述方法的比较

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

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

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

由于<script>标签不受同源策略的约束,这是Web世界中的安全必要性,因此while(1)添加到JSON响应时可以防止在<script>标签中滥用它。

身份验证到位后,JSON劫持保护可以采取各种形式。Google将当(1)附加到他们的JSON数据中,所以如果任何恶意脚本对其进行评估,恶意脚本将进入无限循环。

参考:Web安全测试食谱:快速发现问题的系统技术

由于这是一篇高流量的文章,我希望在这里提供一个对原始问题稍微不确定的答案,从而提供有关JSON劫持攻击及其后果的进一步背景

顾名思义,JSON劫持是一种类似于跨站点请求伪造的攻击,攻击者可以从应用程序中访问跨域敏感JSON数据,这些应用程序将敏感数据作为数组文字返回GET请求。JSON调用返回数组文字的示例如下所示:

[{"id":"1001","ccnum":"4111111111111111","balance":"2345.15"},{"id":"1002","ccnum":"5555555555554444","balance":"10345.00"},{"id":"1003","ccnum":"5105105105105100","balance":"6250.50"}]

这种攻击可以通过3个主要步骤来实现:

第1步:让经过身份验证的用户访问恶意页面。第2步:恶意页面将尝试访问用户登录的应用程序中的敏感数据。这可以通过在超文本标记语言页面中嵌入脚本标记来完成,因为主域同源策略不适用于脚本标记。

<script src="http://<jsonsite>/json_server.php"></script>

浏览器将向json_server.php发出GET请求,用户的任何身份验证cookie都将与请求一起发送。第3步:此时,当恶意站点执行脚本时,它无权访问任何敏感数据。可以使用对象原型设置器访问数据。在下面的代码中,当尝试设置“ccnum”属性时,对象原型属性将绑定到定义的函数。

Object.prototype.__defineSetter__('ccnum',function(obj){secrets =secrets.concat(" ", obj);});

至此,恶意站点已经成功劫持了(ccnum)返回的敏感财务数据byjson_server.phpJSON

需要注意的是,并非所有浏览器都支持此方法;概念验证是在Firefox 3. x上完成的。

有几种方法可以防止JSON劫持:

  • 由于SCRIPT标签只能生成HTTP GET请求,因此它们只向POST返回JSON对象请求。

  • 防止Web浏览器将JSON对象解释为有效的JavaScript代码。

  • 通过要求所有JSON请求都需要预定义的随机值来实现跨站点请求伪造保护。

正如你所看到的,While(1)在最后一个选项下。用最简单的术语来说,while(1)是一个无限循环,它将运行到显式发出Brex语句为止。因此,这将被描述为要应用的密钥的锁(谷歌Brex语句)。因此,JSON劫持,黑客没有密钥将被一致地驳回。唉,如果你用解析器读取JSON块,这时(1)循环会被忽略。

因此,总而言之,while(1)循环可以更容易地可视化为简单中断语句cypher,google可以使用它来控制数据流。

然而,该声明中的关键字是“简单”这个词。值得庆幸的是,经过身份验证的无限循环的使用在自2010年已经从基本实践中删除,因为它在孤立时绝对减少了CPU使用率(以及互联网已经摆脱了通过粗暴的“快速修复”强制执行的事实)。今天,代码库已经嵌入了预防措施,该系统不再至关重要或有效。(部分原因是从JSON劫持转向更有成效的数据农业技术,我目前不会详细介绍)