提问



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


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


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&&&开头,而谷歌联系人似乎从while(1); &&&START&&&开始。[34]


这里发生了什么?

最佳参考


它可以防止JSON劫持。[35]


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


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


这并未解决跨站点请求伪造的问题。[37]

其它参考1


它可以防止通过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 推荐的防止JSON劫持的方法,并且是一种不那么具有侵入性的方法。[38]


与之前的反措施类似,它确保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


这是为了确保某些其他网站不会尝试窃取您的数据。例如,通过替换数组构造函数,然后通过<script>标记包含此JSON URL,恶意第三方网站可以从JSON响应中窃取数据。通过在while(1);开始时,脚本将挂起。[39]


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

其它参考3


这将使第三方难以将JSON响应插入带有<script>标记的HTML文档中。请记住,<script>标签免于同源政策。[40]

其它参考4


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


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

其它参考5


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