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 文件,不使用内置 Ajax 视图助手的 2.x 应用程序需要向其 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报告给供应商。