Rails 4 为 API 操作跳过protect_from_forgery

Posted

技术标签:

【中文标题】Rails 4 为 API 操作跳过protect_from_forgery【英文标题】:Rails 4 skipping protect_from_forgery for API actions 【发布时间】:2014-07-09 12:53:51 【问题描述】:

我一直在使用 API 实现 Rails 4 应用程序。我希望能够从手机和 webapp 本身调用 API。我在研究protect_from_forgery时遇到了this note:

请务必记住,XML 或 JSON 请求也会受到影响,如果您正在构建 API,您将需要以下内容:

class ApplicationController < ActionController::Base
  protect_from_forgery
  skip_before_action :verify_authenticity_token, if: :json_request?

  protected

  def json_request?
    request.format.json?
  end
end

我正在考虑这样做,但我有一些保留/问题:

    这个解决方案似乎让 CSRF 漏洞打开了,因为现在攻击者可以使用onclick javascript 来制作一个链接来发布 JSON? 检查 API 令牌是否是合理的替代方法?即,如果 api 令牌存在并且对于当前用户是正确的,而不是跳过真实性检查,而是允许它在检查失败并在 handle_unverified_request 中恢复,该怎么办? 或者我应该只制作网络应用程序和移动设备send the CSRF token in the HTTP headers?那安全吗?考虑到手机一开始没有呈现 html 表单,它如何获得 CSRF 令牌?

编辑澄清:

我更关心 webapp 用户点击精心制作的 CSRF 链接。移动用户经过身份验证、授权、拥有 API 密钥,所以我不关心他们。但是通过为 webapp 用户启用 CSRF 保护,移动用户被阻止使用受保护的 API。我想知道处理这个问题的正确策略,我不相信 Rails 文档给出了正确的答案。

【问题讨论】:

您有两种不同的场景:Web 应用程序和非 Web 应用程序。 CSRF 仅适用于 Web 应用程序,因为攻击依赖于利用现有的有效浏览器会话。因此,如果您使用浏览器会话进行身份验证,则需要使用 CSRF 令牌保护。如果您使用 API 密钥进行身份验证,那么您不会受到 CSRF 的影响,因为没有可用于伪造的有效会话。如果您在同一个 API 上使用这两种技术,则需要为每种请求类型使用适当的方法。 【参考方案1】:

攻击者可以随心所欲地对您的控制器进行 CURL,但如果您的 API 需要身份验证,他们将无处可去。

让 API 消费者发送 CSRF 并不是 CSRF 真正做的事情。为此,您需要实现一种敲门机制,您的客户端首先点击授权端点以获取代码(也称为 CSRF),然后在 POST 中提交。这对移动客户端来说很糟糕,因为它会使用它们的带宽、功率并且滞后。

无论如何,如果它是经过授权的客户端访问你的控制器,它实际上是伪造的吗(即 CSRF 中的 F)?

【讨论】:

我更关心 webapp 用户点击精心制作的 CSRF 链接。移动用户经过身份验证、授权、拥有 API 密钥,所以我不关心他们。但是通过为 webapp 用户启用 CSRF 保护,移动用户被阻止使用受保护的 API。我想知道处理这个问题的正确策略,我不相信 Rails 文档给出了正确的答案。 @ChrisCameron CORS 应该保护您免受来自您不信任的域的精心制作的 ajax 调用。除非您在 CORS 策略中允许不受信任的域。【参考方案2】:

在 HTTP 标头中发送 CSRF 令牌确实是一种常见的方法。它确保客户端以某种方式获得了有效的令牌。例如,精心制作的 CSRF 链接将与凭据 cookie 一起发送,但标头将不包含 CSRF 令牌。您自己在客户端上的 javascript 将可以访问域 cookie,并且能够将令牌从 cookie 复制到所有 XHR 请求的标头中。

AngularJS 遵循这种方法,as explained here。

关于你的前两个问题:

    此解决方案似乎让 CSRF 漏洞打开...

确实,这就是为什么您不应该在您的 API 中也禁用 CSRF 令牌的原因。

    检查 API 令牌是否是合理的替代方法? ...

可能不会。考虑以下内容(来自OWASP):

GET 请求中的 CSRF 令牌可能会在多个位置泄露:浏览器历史记录、HTTP 日志文件、需要记录 HTTP 请求第一行的网络设备,以及受保护站点链接到外部站点时的引用标头.

一般建议:不要试图发明***。 OWASP 有一个名为REST Security Cheat Sheet 的页面以及我之前链接到的页面。您可以遵循 Angular 方法(将令牌从 cookie 复制到每个 XHR 请求的标头中),对于常规的非 ajax 表单,请确保仅使用 POST 和隐藏字段,这通常在静态服务器表单的 CSRF 保护中完成.

【讨论】:

我也发布了一个类似的question,但我认为OWASP CSRF Cheatsheet 实际上说只要您不允许 CORS 在不受信任的来源上,XHR 请求就会受到 CSRF 的保护。

以上是关于Rails 4 为 API 操作跳过protect_from_forgery的主要内容,如果未能解决你的问题,请参考以下文章

即使设置了标头,也无法验证 CSRF 令牌的真实性 Rails 4 Ajax

Rails:在开发中禁用敲击 JWT 身份验证

在 rspec 中为 API 规范存根protect_from_forgery

Rails:将 API 请求限制为 JSON 格式

如何使用 react_on_rails 的 Redux API 为商店补充水分?

跳过 Rails 中的 JSON 格式生成脚手架