为什么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&&&
while(1); &&&START&&&
。
这里发生了什么?
它可以防止JSON劫持。
有争议的例子:假设Google有一个像mail.google.com/json?action=inbox
这样的网址,它会以JSON格式返回收件箱中的前50封邮件。 由于同源策略,其他域上的恶意网站无法通过AJAX请求获取此数据,但它们可以通过<script>
标记包含该URL。 使用Cookie访问URL,通过覆盖全局数组构造函数或访问器方法,只要设置了对象(数组或哈希)属性,就可以调用该方法,从而允许他们读取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永不执行
放置一段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"}
因此,确保始终返回响应顶级的对象,确保JSON不是有效的Javascript,同时仍然是有效的JSON。
正如注释中的@hvd所指出的那样,空对象{}
是有效的Javascript,并且知道该对象是空的可能本身就是有价值的信息。
以上方法的比较
OWASP方式不那么干扰,因为它不需要客户端库更改,并传输有效的JSON。 但是,不确定过去或未来的浏览器错误是否会打败。 正如@oriadam所指出的那样,通过错误处理(如window.onerror),数据是否可能在解析错误中泄漏尚不清楚。
谷歌的方式需要客户端库以支持自动反序列化,并且可以被认为对浏览器错误更安全。
这两种方法都需要进行服务器端更改,以避免开发人员意外发送易受攻击的JSON。
这是为了确保一些其他网站不能做恶作剧来试图窃取你的数据。 例如,通过替换数组构造函数,然后通过<script>
标记包含此JSON URL,恶意第三方网站可以从JSON响应中窃取数据。 放while(1);
在开始时,脚本会挂起。
另一方面,使用XHR和单独的JSON解析器的同一站点请求可以轻松地忽略while(1);
字首。
上一篇: Why does Google prepend while(1); to their JSON responses?