【问题标题】:Ruby on Rails security regarding session cookies关于会话 cookie 的 Ruby on Rails 安全性
【发布时间】:2013-01-21 16:29:21
【问题描述】:

在我的应用程序中,我有一个 User 模型,它有一个 rememberable_token 列。创建用户时,会在before_create 过滤器中保存一个随机安全字符串,作为用户的安全令牌:

user.rememberable_token = SecureRandom.urlsafe_base64

在会话控制器中,它使用该令牌的值创建一个永久 cookie,以便用户在关闭浏览器时不会被注销,只有在他们通过logout 操作注销时才会被注销:

会话控制器

def create
  .
  .
  cookies.permanent.signed[:permanent_user_session] = user.rememberable_token
end

def logout  
  cookies.delete :permanent_user_session
  redirect_to root_url  
end

cookie 在应用程序控制器中用于确定是否存在当前用户,以及在一些控制器中用于确定用户是否已登录和授权的 before_filter 中。

应用程序控制器

def current_user  
  @current_user ||= User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) if cookies.signed[:permanent_user_session]
end

def authorize
  unless User.find_by_rememberable_token(cookies.signed[:permanent_user_session])
    render :action => 'login'
  end
end

问题是这是安全的还是容易被会话劫持?如果它容易被劫持,如果在 session#logout 方法中它在删除现有 cookie 之前为用户创建了一个新的 rememberable_token(但不创建具有该值的新 cookie),是否可以?

谢谢。

【问题讨论】:

    标签: ruby-on-rails-3 security session-cookies


    【解决方案1】:

    如果有人在窃取 cookie,此代码:

    def current_user  
     @current_user ||= User.find_by_rememberable_token(cookies.signed[:permanent_user_session]) if cookies.signed[:permanent_user_session]
    end
    

    仍然有效。在您的注销方法中,您必须从用户表中删除令牌并在登录时重新创建。

    基本上,您在创建时所做的事情应该在每次登录时完成,并在每次注销时恢复。

    【讨论】:

    • 如果用户保持登录一周,那么任何窃取其 cookie 的人都可以窃取他们的会话。这是令人担忧的还是任何类型的登录会话 cookie 都可能实现?
    • 这不是会话cookie的漏洞。即使您将会话保留在服务器端并且只有 cookie 上的会话 ID,它也是一样的。您可以每 30 分钟使会话过期,但在每次请求时重置计时器。这使攻击者只有 30 分钟的时间间隔来进行攻击,但也取消了让用户保持登录数周的能力。
    • 另外,请注意:不要将持久登录 COOKIE(令牌)存储在您的数据库中,只存储其中的一个哈希值!登录令牌是密码等效的,因此如果攻击者掌握了您的数据库,他/她可以使用这些令牌登录到任何帐户,就像它们是明文登录密码组合一样。因此,在存储持久登录令牌时使用强加盐哈希(bcrypt / phpass)。您可以在此主题上找到有关登录的更多信息:stackoverflow.com/questions/549/…
    【解决方案2】:

    我可能会这样做:

    在会话创建时:

    random_string = SecureRandom.urlsafe_base64
    cookies.permanent.signed[:permanent_user_session] = random_string   
    user.rememberable_token = Digest::MD5.hexdigest(random_string) && user.save
    

    会话销毁:

    cookies.delete :permanent_user_session
    

    在应用程序控制器中:

    def current_user  
      @current_user ||= User.find_by_rememberable_token(Digest::MD5.hexdigest(cookies.signed[:permanent_user_session])) if cookies.signed[:permanent_user_session]
    end
    
    def authorize
      unless @current_user
        render :action => 'login'
      end
    end
    

    这样,您将存储令牌的哈希,并为每次新登录重新生成一个新的(并在每次注销时过期)。 Rails 负责 CSRF,但长期会话可能不是一个好主意。

    【讨论】:

      猜你喜欢
      • 2018-10-10
      • 2011-04-01
      • 2012-04-15
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 2018-12-04
      • 2012-04-12
      • 2011-04-02
      相关资源
      最近更新 更多