【发布时间】:2020-07-06 02:21:51
【问题描述】:
我正在使用旧版 Rails 应用程序,我正在尝试清理一些 CSRF 漏洞。如果我从表单中删除隐藏的 CSRF 字段,我仍然可以成功提交表单。
出现问题的唯一迹象是日志中的警告:WARNING: Can't verify CSRF token authenticity。
在某些页面,protect_from_forgery 会捕获请求,如果没有 csrf 令牌,应用程序将崩溃,但它的命中和未命中取决于页面:例如。登录页面在没有令牌的情况下工作,但更新用户页面没有。
我尝试为protect_from_forgery 制定一个自定义策略(由Marc Gauthier 建议),类似于:
protect_from_forgery with: :MyStrategy
class MyStrategy
byebug
def initialize(controller)
@contriller = controller
end
def handle_unverified_request
puts "HELLO!"
Rails.logger.warn [
"handle_unverified_request",
"#{@controller.controller_name}-#{@controller.action_name}"
].join(" - ")
end
end
启动应用程序时这似乎没有任何作用,byebug 调用将暂停,但我从未收到 puts 消息或错误日志。
我也尝试了诸如with: :exception 之类的常规策略,但没有任何变化,有些页面可以工作,有些页面不能,但它们是一致的。
【问题讨论】:
-
我担心你提到的“碰巧”行为。你是说同一个表单在没有 CSRF 令牌的情况下有时会成功提交,有时会失败?似乎不可能!这真的是你说的吗?对不起,但我相信你一定是弄错了。但也许我还没有理解你所说的“碰巧”是什么意思。
-
同一个表单要么总是工作要么不工作,但是根据页面的不同,CSRF 保护工作或不工作。因此,例如,对于登录页面和忘记密码页面,令牌将不起作用(我可以删除它并毫无问题地提交表单)但是在编辑用户详细信息页面上,如果我删除令牌,表单将不会提交并且应用程序将崩溃(如预期/期望的那样)。
-
你能再分享一些代码吗?例如。
ApplicationController的完整代码(大概是您调用protect_from_forgery的地方)可能会有所帮助。 -
不幸的是,作为一个旧版客户端应用程序,
ApplicationController的行数超过 400 行,我不愿意从他们的应用程序中分享这么多内容。有什么我应该寻找的具体内容或您想查看的特定方法吗?我意识到这不是很有帮助,我只是希望有人可能遇到过类似的事情。 -
专注于登录。控制器是什么,我不知道就叫它LoginController。 LoginController 或 ApplicationController 中有一行无法通过 CSRF 检查。开始删除与接收登录表单无关的所有内容,逐节,逐个方法,同时在每次删除后尝试提交表单。最终,您将删除导致问题的行。没有看到你的代码,这是我能建议的最好的。如果你在调试别人的 400 行 ApplicationController,这可能是最好的方法。
标签: ruby-on-rails ruby-on-rails-3 csrf