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


4074

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

这里发生了什么?


45
我相信您的第一印象是正确的。如果您开始寻找代码并尝试根据源来裁剪输入流,那么您将重新考虑并以安全的方式(并且由于Google的行为,更加简便)进行操作。
EstebanKüber2010年

34
可能是一个后续问题:Google为什么)]}'现在代替while(1);?答案会一样吗?
Gizmo

3
可以防止eval,但不能无限循环。
Mardoxx

9
)]}'也可能是为了保存字节,例如使用的facebook for(;;);会保存一个字节:)
Gras Double

3
为了防止json泄露,即JSON hijacking
Ashraf.Shk786

Answers:


4293

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

人为的例子:假设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,而不进行任何处理,从而导致无限循环或语法错误。

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


228
为什么获取此数据的请求不需要CSRF令牌?
Jakub P.

235
是否for(;;);做同样的工作吗?我已经在facebook的ajax响应中看到了这一点。
朱利安国王

183
@JakubP。要在Google范围内存储和维护CSRF令牌,需要大量的基础架构和成本。
亚伯拉罕

127
@JakubP。反CSRF令牌会使缓存混乱,并且需要在服务器端进行一定数量的密码评估。在Google规模上,这将需要大量CPU。这种将其卸载到客户端。
bluesmoon

96
在我看来,更好的方法是让服务器仅在设置了正确的标头后才发送JSON。您可以在AJAX调用中执行此操作,但不能使用脚本标签。这样,敏感信息甚至都不会发送,您也不必依赖浏览器端的安全性。
mcv

574

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

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

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

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

除了使用脚本标记请求JSON内容时,JSON是在攻击者的受控环境中作为Javascript执行的。如果攻击者可以替换对象构造期间使用的Array或Object构造函数或其他某种方法,则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无效,而JSON仍然有效。

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

以上方法比较

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

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

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


23
OWASP推荐很有趣,因为它很简单。有人知道Google的方式更安全的原因吗?
Funroll

18
我相信它在任何方面都不是更安全。在这里提供OWASP似乎是+1的充分理由。

30
可能值得注意的是,为什么返回对象文字会使script标记或eval函数失败。花括号{}可以解释为代码块或对象文字,而JavaScript本身更喜欢前者。作为代码块,它当然是无效的。按照这种逻辑,我看不到未来浏览器行为的任何可预见的变化。
芒果

16
错误的代码是不够的,因为攻击者还可以劫持浏览器的脚本错误处理程序(window.onerror),我不确定onerror语法错误的行为是什么。我猜Google也不确定。
oriadam

12
“有效的JSON对象,如果没有用任何东西括起来,则在Javascript中无效:”-除了空对象({})的小写情况之外,空对象也是有效的空块。如果知道对象为空可能本身就是有价值的信息,则这可能是可利用的。

371

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

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


6
从技术上讲,如果您有前缀,则“普通” JSON解析器应该给出错误。
马修·克鲁姆利

12
攻击者只会使用简单的旧<script>元素,而不是XHR。
劳伦斯·贡萨尔维斯

9
@Matthew,当然可以,但是您可以在将数据传递到JSON解析器之前将其删除。您无法使用<script>标签来做到这一点
bdonlan

7
有这个例子吗?再次引用了替换数组构造函数,但这是一个长期存在的错误。我不明白如何访问通过script标记接收的数据。我很想看到一个虚拟的实现,它可以在最近的浏览器中运行。
丹尼斯·G

7
@joeltine,不,不是。参见stackoverflow.com/questions/16289894/…

111

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


21
这只是答案的一半。如果不是要覆盖Objectand Array构造函数的技巧,那么执行有效的JSON响应(就好像是JavaScript一样)在任何情况下都是无害的。是的,while(1);如果以<script>标记为目标,则阻止将响应作为JavaScript执行,但是您的答案并未说明为什么这样做是必要的。
Mark Amery 2014年

但是它如何防止iframe
Ravinder Payal

脚本标记永远不会不受同一原始策略的限制。你能帮我清理一下吗?
Suraj Jain

82

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


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

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


17
这只是答案的一半。如果不是要覆盖Objectand Array构造函数的技巧,那么执行有效的JSON响应(就好像是JavaScript一样)在任何情况下都是无害的。是的,while(1);如果以<script>标记为目标,则阻止将响应作为JavaScript执行,但是您的答案并未说明为什么这样做是必要的。
Mark Amery 2014年

11

由于该<script>标记不受Web世界安全性必需的Same Origin Policy的限制,因此将其while(1)添加到JSON响应后,可以防止在<script>标记中滥用该标记。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.