Javascript 为什么谷歌会在第1段中提前结束;他们对JSON的反应如何?

Javascript 为什么谷歌会在第1段中提前结束;他们对JSON的反应如何?,javascript,json,ajax,security,Javascript,Json,Ajax,Security,谷歌为什么在while(1)前加前缀到他们的(私有)JSON响应 例如,以下是在中打开和关闭日历时的响应: 我认为这是为了防止人们对其执行eval(),但您真正需要做的就是在时替换,然后设置。我假设eval预防是为了确保人们编写安全的JSON解析代码 我在其他几个地方也看到过这种用法,但谷歌(邮件、日历、联系人等)更是如此。奇怪的是,它以&&&&&&&&&&&开头,而谷歌联系人似乎以开头,而(1)&&&启动&& 这是怎么回事?这是为了确保其他网站不会采取卑鄙的手段试图窃取您的数据。例如,通过,然

谷歌为什么在while(1)前加前缀
到他们的(私有)JSON响应

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

我认为这是为了防止人们对其执行
eval()
,但您真正需要做的就是在
时替换
,然后设置。我假设eval预防是为了确保人们编写安全的JSON解析代码

我在其他几个地方也看到过这种用法,但谷歌(邮件、日历、联系人等)更是如此。奇怪的是,它以
&&&&&&&&&&&
开头,而谷歌联系人似乎以
开头,而(1)&&&启动&&


这是怎么回事?

这是为了确保其他网站不会采取卑鄙的手段试图窃取您的数据。例如,通过,然后通过
标记包含此JSON URL,恶意第三方站点可以从JSON响应中窃取数据。通过在while(1)中放置
在开始时,脚本将挂起


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

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


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


编辑-记下评论(和其他答案)。这个问题与被破坏的内置设施有关,特别是
对象
数组
构造函数。可以对这些内容进行更改,以便在解析无害的JSON时触发攻击者代码。

这将使第三方难以将JSON响应插入带有
标记的HTML文档中。请记住,
标记不受。

的限制,这是一个严重的JSON安全问题,在所有使用ECMAScript 5的主要浏览器中都是正式存在的

人为的例子:假设谷歌有一个类似
mail.Google.com/json?action=inbox
的URL,它以json格式返回收件箱的前50条消息。由于同源策略,其他域上的恶意网站无法发出AJAX请求以获取此数据,但它们可以通过
标记包含URL。通过cookie访问URL,只要设置了对象(数组或散列)属性,他们就可以调用一个方法,允许他们读取JSON内容

while(1)
&&&&&BLAH&&&&
阻止了这一点:位于
mail.google.com
的AJAX请求将拥有对文本内容的完全访问权,并且可以将其删除。但是,
标记插入会在没有任何处理的情况下盲目执行JavaScript,从而导致无限循环或语法错误


这并没有解决问题。

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

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

攻击者可以代表您请求其他域上的页面,例如使用
标记,但无法获取任何有关结果的信息(标题、内容)

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

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

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

有多种对策:

确保JSON永远不会执行 通过放置
while(1)语句,Google确保JSON数据永远不会作为JavaScript执行

只有合法的页面才能真正获得全部内容,去掉
while(1),并将其余部分解析为JSON

例如(;;)的
也有相同的结果

确保JSON不是有效的JavaScript 类似地,在JSON之前添加无效的标记,如
&&&&&&&&&&&
,可以确保它永远不会执行

始终返回外部带有对象的JSON 这是为了防止JSON劫持,是入侵性较小的一种

与前面的对策类似,它确保JSON永远不会作为JavaScript执行

一个有效的JSON对象,如果没有被任何东西包围,在JavaScript中是无效的:

eval('{"foo":"bar"}')
// SyntaxError: Unexpected token :
但是,这是有效的JSON:

JSON.parse('{"foo":"bar"}')
// Object {foo: "bar"}
因此,确保始终在响应的顶层返回一个对象可以确保JSON不是有效的JavaScript,同时仍然是有效的JSON

正如@hvd在注释中指出的,空对象
{}
是有效的JavaScript,知道对象是空的本身可能是有价值的信息

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

谷歌之路
JSON.parse('{"foo":"bar"}')
// Object {foo: "bar"}