首页 文章

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

提问于
浏览
3622

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

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

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&&& 开头,Google联系人似乎从 while(1); &&&START&&& 开始 .

这里发生了什么?

6 回答

  • 3857

    它阻止JSON hijacking,这是一个主要的JSON安全问题,在所有主流浏览器since 2011与EMCA5正式fixed .

    举例:说Google有一个像 mail.google.com/json?action=inbox 这样的网址,它以JSON格式返回收件箱的前50条消息 . 由于同源策略,其他域上的邪恶网站无法通过AJAX请求获取此数据,但是它们可以通过 <script> 标记包含URL . 使用您的cookie访问URL,并且通过overriding the global array constructor or accessor methods,只要设置了对象(数组或散列)属性,就可以调用该方法,从而允许它们读取JSON内容 .

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

    这没有解决cross-site request forgery的问题 .

  • 5

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

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

    攻击者可以代表您在其他域上请求网页,例如通过使用 <script src=...><img> 标记,但它无法获取有关结果( Headers ,内容)的任何信息 .

    因此,如果您访问攻击者的页面,它无法从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 recommended way以防止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,并且知道对象为空可能本身就是有 Value 的信息 .

    以上方法的比较

    OWASP方式不那么具有侵入性,因为它不需要更改客户端库,并传输有效的JSON . 但是,不确定过去或未来的浏览器错误是否会破坏这一点 . 正如@oriadam所指出的,不清楚是否可以通过错误处理(例如window.onerror)将数据泄漏到解析错误中 .

    谷歌的方式需要客户端库,以便它支持自动反序列化,并且可以被认为是更安全的浏览器错误 .

    这两种方法都需要服务器端更改,以避免开发人员意外发送易受攻击的JSON .

  • 100

    它可以防止它被用作简单的 <script> 标记的目标 . (好吧,它不会只是将脚本标记放在他们自己的网站中,并依赖于活动会话来获取您的内容 .

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

  • 67

    由于 <script> 标签是免除同源策略,这是Web环境中的安全必需品, while(1) 添加到JSON响应时可以防止在 <script> 标记中滥用它 .

  • 347

    这将使第三方难以将JSON响应插入带有 <script> 标记的HTML文档中 . 请记住, <script> 标签免于Same Origin Policy .

  • 475

    这是为了确保其他一些网站无法做出令人讨厌的技巧来试图窃取您的数据 . 例如,通过replacing the array constructor,然后通过 <script> 标记包含此JSON URL,恶意第三方网站可能会从JSON响应中窃取数据 . 通过在开头放置 while(1); ,脚本将挂起 .

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

相关问题