协慌网

登录 贡献 社区

为什么 Google 会在(1)之前提前; 他们的 JSON 回复?

为什么 Google 会while(1);提前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&&&

这里发生了什么?

答案

它可以防止JSON 劫持 ,这是自 2011 年以来在 EMCA5 中正式修复的所有主流浏览器中的主要 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 执行。如果攻击者可以替换数组或对象构造函数或对象构造期间使用的其他方法,则 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。

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

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