在Rails中为经过身份验证的POST端点禁用CSRF保护是否安全?

时间:2012-05-18 10:52:57

标签: ruby-on-rails security iframe csrf

如果我可以在rails应用程序中禁用端点的CSRF令牌检查,我发现自己可以提供更好的用户体验。

端点是create操作(路由到POST /whatever),它位于设计:authenticate!过滤器后面。

我是否会通过禁用该特定端点的CSRF保护来解决任何其他安全风险,或者我是否可以安全地依赖身份验证before_filter来阻止CSRF令牌防范的恶意请求?


以下是关于为什么的更详细解释如果有人感兴趣我想要这样做。

我的用例是我基本上想创建一些非常类似于Facebook的按钮,但是这个按钮(与Facebook版本不同)通常会在同一页面上多次出现。

除了用户使用空cookie访问页面的情况外,CSRF保护工作正常。

在这种情况下,rails会为X个请求中的每个请求生成一个新会话,因为它们都是无cookie的。当然,对于每个新会话,都会生成一个新的CSRF令牌,并在对iframe的响应中返回。

由于浏览器只为域保留一个cookie,因此来自每个iframe的任何后续请求都将映射到同一会话,因此所有CSRF令牌(除了一个)都无效。

映射到单个会话很不错,因为可以提示用户登录一次,然后将每个后续按钮按下映射到相同的登录 - 无需重新加载页面。

折衷方案是使用401 Unauthorized进行回复,但保留被拒绝请求的会话(通过覆盖handle_unverified_request)。这将再次触发弹出窗口,但这次是因为用户已经登录而发生了即时重定向。

当然,最好避免在弹出窗口中闪现符号,因此我只想对create动作一起禁用CSRF保护。

1 个答案:

答案 0 :(得分:9)

经过身份验证的请求正是CSRF的目的。

CSRF的含义是攻击者说服用户的浏览器发出请求。例如,您访问由攻击者托管的页面,其形式类似于

<form action="http://www.yourapp.com/some_action">
  #for parameters here
</action>

页面上的一些自动提交表单的javascript。如果用户已登录到您的应用程序,则此请求将通过任何基于cookie的身份验证检查。但是攻击者不知道csrf令牌。

对于未经身份验证的请求,csrf没有用处 - 攻击者可以继续执行请求 - 他们不需要劫持受害者的​​凭据。

所以,简短版本:禁用csrf保护会让你容易受到csrf风格攻击。

CSRF的真正含义是确保表单包含攻击者无法伪造的参数。会议是一个容易存储这样一个价值的地方,但我想你可以提出替代方案。例如,如果用户无法控制表单中的任何参数,则可以添加另一个参数,该参数将是表单中所有其他参数的签名(可能具有某种时间戳或nonce以防止重放攻击)。收到请求后,您可以通过验证签名来判断请求是否来自您生成的表单。

对这类东西要非常小心,因为它很容易出错(甚至大男孩也错了sometimes