具体来说,我编写了一个Rails应用程序,其中我使用了默认(在Rails 2.3.5中)CookieStore
会话存储,我发现了一个奇怪的问题。
我自己和其他一些人已经使用该网站几周了,我们每个人都有一个基于用户名和密码的登录(每个用户自己注册,我将(盐渍和散列)数据存储在数据库中)。我将用户ID存储在Rails session
对象中(因此,在浏览器和服务器之间来回传递的cookie中)。
这里有一点重要:由于这是一个内部网站点,因此我将cookie设置为保持活动状态长达2周,以避免用户不得不一直登录。
今天我重置数据库,有意擦除所有用户记录(以及所有其他数据)。一些用户开始重新注册,然后一个用户发现他们第一次去网站,因为擦除他们自动以不同的用户身份登录!
我想我可以看到为什么会发生这种情况:从该用户的浏览器传递到服务器的用户ID现在与我的数据库中的不同用户记录匹配。我最初的想法是“哦,亲爱的,我没想到!”但我想的越多,我就意识到这可能是预期的行为。
我意识到我可以将我的Rails应用程序更改为用户ActiveRecordStore
但在我这样做之前我想确保我理解这里发生了什么。具体来说,使用CookieStore
会话和让会话保持活跃一段时间的组合真的会造成这样一个巨大的安全漏洞吗?或者我错过了什么? session_id
应该在这里提供更多的安全性吗?
答案 0 :(得分:4)
此设置中的大安全漏洞不是cookie长度,而是在cookie中设置user_id。这意味着登录您网站的任何人都可以通过更改该cookie来以其他人的身份登录!黑客只需顺序遍历user_id,登录并查看是否有任何他们想要窃取或滥用的内容。
如果要滚动自己的身份验证,请尝试以下操作:在用户表中添加“令牌”字符串字段。当有人登录时,将此标记设置为一组随机数字和字母,并将 作为cookie传递给用户。令牌应至少为32个字符,字母数字,大写和小写。
现在,当用户访问某个页面时,他们的帐户会被该哈希值而不是其user_id查找。值是哈希难以猜测,并且永远不会重复。重置数据库时,您的user_id实际上已重复,导致人们彼此登录。
<强>更新强>
@shingara是正确的,因为我的错误是cookie商店已经处理了安全部分。因此,user_id mixup是一次性的,因为您重置了数据库。除非您再次重置数据库,否则这不是您在生产环境中遇到的问题。如果重置是永远的可能性,那么仍然按照我的推荐创建令牌。否则,你很好。
答案 1 :(得分:1)
此处遇到问题的最简单方法是在重置数据库时更改cookie名称。 cookie名称应该在config / initializers / session_store.rb
中ActionController::Base.session = {
:key => '_your_app_session_v2',
您也可以更改密码,但如果用户请求网站使用旧Cookie,则可能会为您的用户带来错误。
答案 2 :(得分:0)
只有当您有2个具有相同user_id的不同用户时才会出现此情况。因此,如果您将user_id定义为unique,则无法实现。
另一种情况,您可以在会话中添加一个用户使用唯一键的哈希值。当您检查会话时,您将获得user_id并检查user_token是否相同。如果没有,则用户未获得授权。
答案 3 :(得分:0)
谢谢你的所有回复。他们都以某种方式回答了我的问题:是的,我的设置(以及我在擦除用户后没有设置新的会话密钥)会造成安全漏洞。
很多Rails教程提倡这种设置,但没有提到你需要的只是将你的cookie作为另一个用户完全认证的事实。
总而言之,我问了这个问题,因为我找不到任何讨论 CookieStore
会话+长cookie生命周期的危险的事情,我发现这很令人惊讶缺少明显的东西。
答案 4 :(得分:0)
我有一个类似的问题并使用类似的代码片段解决了它 this comment by mdesantis on managing Rails secret token