2011 年 2 月 8 日 星期二

Ruby on Rails 中 CSRF 保护绕过

由 michael 发布

Ruby on Rails 中存在一个漏洞,攻击者可利用此漏洞绕过提供的CSRF保护。此漏洞已被分配CVE标识符CVE-2011-0447。

  • 受影响的版本:2.1.0 及更高版本
  • 不受影响:不使用内置CSRF保护的应用程序。
  • 已修复版本:3.0.4,2.3.11

影响

可将浏览器插件和HTTP重定向的某些组合用于诱骗用户浏览器发出跨域请求,而其中包括攻击者指定的任意HTTP标头。攻击者可利用此漏洞来欺骗 ajax 和API请求,并绕过内置CSRF保护,并成功攻击应用程序。所有运行受影响版本的用户应立即升级或应用补丁。

版本

可在正常位置获得 3.0.4 和 2.3.11 版本。

升级过程

此修复程序中有两项主要更改,CSRF保护失败时的行为已更改,现在对所有GET请求都要求有令牌。

应用此补丁后,失败的CSRF请求将不再生成HTTP 500 错误,而会重置会话。用户可以通过在自己的控制器中覆盖handle_unverified_request来覆盖此行为。

用户仍须注意,用户不能通过非会话数据自动登录。例如,一个使用过滤器来实现“记住我”功能的应用程序必须在其handle_unverified_request处理程序中删除这些 Cookie,或确保仅在GET请求中执行记住我代码。删除 remember_me Cookie 的自定义处理程序看上去会像

def handle_unverified_request super # 调用重置会话的默认行为 cookies.delete(:remember_me) # 删除自动登录 Cookie,以便拒绝欺诈请求。 end

要确保应用程序向每个 ajax 请求发送CSRF令牌,需要执行两个步骤。在元标记中提供令牌,然后确保你的 JavaScript 读取这些值并随每个请求一并提供。第一步涉及在应用程序布局中的某个位置包括csrf_meta_tag帮助程序。Rails 3 应用程序可能已经包括此帮助程序,不过它现在已回溯移植到 2.3.x 系列。其使用方法的示例在 application.html.erb 中会类似于以下内容

<%= javascript_include_tag :defaults %> <%= csrf_meta_tag %>

除了改变模板外,还需要修改应用程序的 javascript 以在 Ajax 请求中发送令牌。Rails 3 应用程序可以使用 rake rails:update 来更新 rails.js 文件,2.x 应用程序如果没有使用内置的 ajax 视图帮助器,则需要将一个特定于框架的代码段添加到 application.js 。可在以下位置找到这些代码段的示例:

解决方法

此漏洞没有可行的解决方法。

修补程序

为帮助无法立即升级的用户,我们已为这两个受支持的版本提供了补丁程序。它们采用 git-am 格式,3-0-csrf.patch 包含两个变更集,其他仅包含一个变更集。

鉴于此问题的严重性,我们还为 2.2 和 2.1 系列提供了反向移植修复程序。这些版本不会发布 gem,但 git 中的稳定分支将予以更新。

请注意,目前仅支持 2.3.x 和 3.0.x 系列。建议尽早升级较早的不受支持的版本的使用者,因为我们无法无限期地提供持续的安全修复。

致谢

感谢 Google 安全团队的 Felix Gröbert 向我们报告该漏洞,并与我们合作,确保修复不会引入任何新问题。还要感谢 Shopify 开发团队,感谢他们在验证修复程序和升级流程方面给予的帮助。原始漏洞已由 kuza55 向供应商报告