为什么Google会在(1)之前提前;他们的JSON回复?

时间:2010-04-19 18:00:10

标签: javascript json ajax security

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

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

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 Docs&&&START&&&开头相反,Google联系人似乎从while(1); &&&START&&&开始。

这里发生了什么?

7 个答案:

答案 0 :(得分:4087)

它阻止了JSON hijacking,这是一个主要的JSON安全问题,在使用ECMAScript 5的所有主要浏览器fixed中正式since 2011

Contrived示例:说Google有一个像mail.google.com/json?action=inbox这样的网址,它会以JSON格式返回收件箱的前50条消息。由于同源策略,其他域上的邪恶网站无法使AJAX请求获取此数据,但它们可以通过<script>标记包含URL。使用您的 Cookie访问该URL,并且overriding the global array constructor or accessor methods只要设置了对象(数组或散列)属性,就可以调用该方法,从而允许他们读取JSON内容。

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

这不涉及cross-site request forgery

的问题

答案 1 :(得分:515)

它可以防止通过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&&&,确保它永远不会被执行。

始终在外部

返回带有Object的JSON

这是OWASP recommended way以防止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。

答案 2 :(得分:355)

这是为了确保其他网站无法做出令人讨厌的伎俩来试图窃取您的数据。例如,通过replacing the array constructor,然后通过<script>标记包含此JSON URL,恶意第三方网站可能会从JSON响应中窃取数据。通过在开始时放置while(1);,脚本将会挂起。

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

答案 3 :(得分:104)

这将使第三方难以将JSON响应插入到带有<script>标记的HTML文档中。请注意<script>标记免于Same Origin Policy

答案 4 :(得分:74)

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


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

编辑 - 记下评论(和其他答案)。该问题与颠覆的内置工具有关,特别是ObjectArray构造函数。这些可以被修改,以便在解析时无关紧要的JSON可以触发攻击者代码。

答案 5 :(得分:10)

由于<script>标记免于同源策略,这是网络世界中的安全必需品,因此while(1)添加到JSON响应时可防止在<script>中滥用它标签。

答案 6 :(得分:0)

身份验证到位后,JSON劫持保护可能需要 多种形式。 Google将 while(1)附加到其JSON数据中,因此 如果有任何恶意脚本对其进行评估,则该恶意脚本会进入 无限循环。

参考:other solutions for Windows