在我的一个控制器中,我编写以下内容以保护CSRF中的某些页面。
protect_from_forgery :only => [:foo, :bar]
当我加载与foo
和bar
对应的网址时,我查看了HTML,我没有看到任何包含任何安全令牌的隐藏输入字段或元标记,正如here所述。
但是,在测试期间,我确实发现CSRF
对这些页面无效,尽管它对同一应用程序中未受保护的其他页面有效。
那么Rails 4
在哪里存储用于验证请求来自原始页面的安全令牌?
请注意,我已经阅读了Ruby On Rails Security Guide,并在protect_from_forgery
部分中说明了
这将自动包含所有表单和Ajax中的安全令牌 Rails生成的请求。如果安全令牌与之不匹配 预计,会议将重置。
问题是启用CSRF保护的页面上的表单中似乎缺少此安全令牌,即使CSRF确实对它们无效。
请注意,此代码来自class project,其中一个目标是执行点击劫持攻击以绕过CSRF项目。我在这里问的问题是与赋值的目的正交。
我只是对Rails如何做CSRF感到好奇。
直接执行rails server
后,我找不到安全令牌的相关网址为http://localhost:3000/protected_transfer
。
答案 0 :(得分:10)
CSRF令牌存储在用户的会话中(默认情况下,在Rails中为cookie;在Rails 4中为加密的cookie)。它还通过<meta>
辅助方法作为csrf_meta_tags
标记(供Javascript库使用)以及form_tag
或{生成的任何形式的隐藏字段写入页面页面中的{1}}。
查看此项目时,未显示CSRF令牌的原因是HTML是使用文字form_for
标记编写的,而不是<form>
帮助程序,其中包含CSRF令牌。此外,布局中不存在form_for
助手,这就是元标记无法写入的原因。
表单已硬编码以发布到csrf_meta_tags
,不应受CSRF保护,因此即使视图标记为<form action="post_transfer" method="post">
,此表单也应具有CSRF功能。 <{1}}方法甚至不可能接受合法请求,因为永远不会发送真实性令牌。
我怀疑导师错过了这个,因为测试将合法地使用表单(击中未经验证的端点,并让它成功),然后指示学生尝试针对受保护端点的CSRF(这将永远不会无论如何都要通过集合),所以你最终会测试两种不同的东西,这些东西会因错误的原因产生正确的结果。