题 为什么Google会在(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 然后你就定了我认为eval预防是为了确保人们编写安全的JSON解析代码。

我已经在其他几个地方看到了这种情况,但谷歌(邮件,日历,联系人等)的情况更是如此。奇怪的是, 谷歌文档 以。。开始 &&&START&&& 相反,谷歌联系人似乎开始 while(1); &&&START&&&

这里发生了什么?


3491
2018-04-19 18:00


起源


我相信你的第一印象是正确的。如果你开始寻找代码并尝试根据来源修剪输入流,你会重新考虑并安全地(并且因为谷歌的行动,更容易)方式。 - Esteban Küber
可能是一个后续问题:为什么谷歌会提前 )]}' 现在而不是 while(1);?答案是否相同? - Gizmo
会阻止eval,但不会有无限循环。 - Mardoxx
这个 )]}' 也可能是保存字节,就像facebook一样 for(;;); 这节省了一个字节:) - Gras Double
为了防止披露json, JSON hijacking - Ashraf.Shk786


答案:


它阻止了 JSON劫持

举例说明:谷歌有一个像这样的网址 mail.google.com/json?action=inbox 它以JSON格式返回收件箱的前50条消息。由于同源策略,其他域上的邪恶网站无法通过AJAX请求获取此数据,但它们可以通过以下方式包含URL <script> 标签。访问该URL 你的 饼干和 覆盖全局数组构造函数或访问器方法 只要设置了对象(数组或散列)属性,它们就可以有一个方法,允许它们读取JSON内容。

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

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


3770
2018-04-19 18:11



为什么获取此数据的请求不需要CSRF令牌? - Jakub P.
是否 for(;;); 做同样的工作?我在facebook的ajax回复中看到过这个。 - King Julien
@JakubP。在Google规模下存储和维护CSRF令牌需要大量的基础架构和成本。 - abraham
@JakubP。反CSRF令牌混乱缓存,并需要一些服务器端的加密评估。在谷歌规模,这将需要大量的CPU。这种方式将其卸载给客户端。 - bluesmoon
在我看来,更好的方法是让服务器只在设置了正确的标头时才发送JSON。您可以在AJAX调用中执行此操作,但不能使用脚本标记。这样,敏感信息甚至不会被发送,您不必依赖浏览器端的安全性。 - mcv


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

始终在外部返回带有Object的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。


445
2018-02-02 12:09



OWASP推荐很有意思,因为它简单。有人知道谷歌的方式更安全吗? - funroll
我相信这个 不 以任何方式更安全。在这里提供OWASP似乎是+1的充分理由。 - vaxquis
2014年的哪些浏览器允许您替换Array或Object构造函数? - Filipe Giusti
值得注意的是 为什么 返回一个对象文字失败了 script 标签或 eval 功能。大括号 {} 可以解释为代码块或对象文字,并且JavaScript本身更喜欢前者。作为代码块,它当然是无效的。通过这种逻辑,我看不出未来浏览器行为的任何可预见的变化。 - Manngo
糟糕的代码是不够的,因为攻击者也可以劫持浏览器的脚本错误处理器(window.onerror)我不确定是什么行为 onerror 语法错误。我猜谷歌也不确定。 - oriadam


这是为了确保其他一些网站无法做出令人讨厌的技巧来试图窃取您的数据。例如,通过 替换数组构造函数,然后通过一个包含这个JSON URL <script> 标记,恶意第三方网站可能会窃取JSON响应中的数据。通过投入 while(1); 在开始时,脚本将挂起。

另一方面,使用XHR和单独的JSON解析器的同一站点请求很容易忽略 while(1); 字首。


344
2018-05-16 02:08



从技术上讲,如果您有前缀,“正常”JSON解析器应该给出错误。 - Matthew Crumley
攻击者只会使用普通老人 <script> 元素,而不是XHR。 - Laurence Gonsalves
@Matthew,当然,你可以在将数据传递给JSON解析器之前删除它。你不能这样做 <script> 标签 - bdonlan
这有什么例子吗?再次引用替换数组构造函数,但这是一个长期修复的错误。我不明白如何访问通过脚本标记接收的数据。我很想看到一个在最近的浏览器中工作的虚拟实现。 - Dennis G
@joeltine,不,不是。看到 stackoverflow.com/questions/16289894/... 。


这将使第三方难以将JSON响应插入HTML文档中 <script> 标签。记得那个 <script> 标签免于 同源政策


98
2018-04-19 18:04



这只是答案的一半。如果它不是为了超越的伎俩 Object 和 Array构造函数,执行一个有效的JSON响应,好像它是JavaScript在任何情况下都是完全无害的。是的 while(1); 如果a的目标是,则阻止响应作为JavaScript执行 <script> 标签,但你的答案并没有解释为什么这是必要的。 - Mark Amery
但它如何防止iframe - Ravinder Payal
@RavinderPayal <iframe> 标签不能免于同源政策...... - YoYoYonnY
脚本标记永远不会免于同源策略。你能帮我清楚一下吗? - Suraj Jain


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

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


65
2018-04-19 18:02



这只是答案的一半。如果它不是为了超越的伎俩 Object 和 Array构造函数,执行一个有效的JSON响应,好像它是JavaScript在任何情况下都是完全无害的。是的 while(1); 如果a的目标是,则阻止响应作为JavaScript执行 <script> 标签,但你的答案并没有解释为什么这是必要的。 - Mark Amery


自从 <script>标签免于同源策略,这是网络世界中的安全必需品,而(1)当添加到JSON响应时,防止在其中滥用它 <script>标签。


3
2017-08-18 04:14