背景细节
我正在使用Devise进行身份验证以登录到Rails 5应用程序.
每当我捆绑Audited或Paper Trail gem时,当我尝试#create一个新会话时(通过登录表单 - /users/sign_in),我收到以下错误:
ActionController::InvalidAuthenticityToken
Run Code Online (Sandbox Code Playgroud)
环境细节
Ruby 2.3.1
宝石:
重现步骤:
我们最近遇到了一个问题,其中用户A可能无意中劫持了用户B的会话,该用户B试图在(几乎)与用户A同时访问控制器生成的下载.
我们仍然不能100%确定实现这一目标所需的所有条件,但我们可以在生产和登台环境中可靠地重现问题.这些环境的重要细节如下.
Application Server:Phusion Passenger 5.0.21或5.0.24(意思是我们尝试了两个版本并且都重现了这个问题)
框架:Rails 4.2.4
语言:Ruby 2.2.3
操作系统:CentOS 6
有趣的是,我们可以不使用重现此问题的Phusion客运4.0.53.
它可能看起来太简单了,但这就是必要的.
这就是某人的会话被无意中劫持所需要的一切.(看起来轮盘赌A或B的会话是否被劫持,虽然它可能不像看起来那么随机.)
我们知道用户的会话已被劫持,因为我们可以看到页面上显示的当前会话的用户名和姓.
每次,一个用户"成为"另一个用户.
如果用户访问角色不同,则还意味着您现在可能具有不同的访问级别.例如,有人可能突然成为管理员,如果这是他们无意中被劫持的会话....
最初似乎Phusion Passenger是导致此问题的唯一因素,因为当我们切换回版本4时,此问题不再出现.
在一些代码改变之后,我们确定我们的控制器代码中的方法似乎导致了这个问题的发生.
这是一个示例Controller方法,它将在Phusion Passenger 5.0.21或5.0.24上生成此问题:
def sample_method
respond_to do |format|
format.csv {
headers.merge!({'Cache-Control'=>'must-revalidate, post-check=0, pre-check=0'})
render :text => proc { |response, output|
100.times do |i|
output.write("This is line #{i}\n")
end
}
}
end
end
Run Code Online (Sandbox Code Playgroud)
似乎我们对Cache-Control的修改可能已经很好地解决了这个问题.
也许我们不应该对此进行修改,但我们希望有人可能会深入了解缓存控制参数如何能够突然让我们陷入不同的会话.
为了测试这个,你必须有一个映射到Controller#sample_method的路由,你必须有一个按钮可以点击下载这个文件.
我意识到我们正在指定我们想要一个CSV并且没有返回CSV,但在这种情况下我用proc替换了我们的实际CSV,因为我们的CSV是在一个单独的类中生成的.
上面列出的环境中的上述代码将重现该问题.
我们使用Devise gem进行用户身份验证.如果您要设置测试应用程序以尝试重现此问题,则需要设置Devise和两个帐户.
顺便说一句,你还需要在两台独立的计算机上安排两个人来测试它.您既需要同时登录系统,也要同时尝试多次点击该按钮. …
ruby session ruby-on-rails session-hijacking ruby-on-rails-4