Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Secure and insecure sessions with Rails

I have an e-commerce site where when a user logs in, they can make a purchase with saved credit card data. So, I want to use a secure session.

However, I have non-SSL pages on the site and the user needs to be logged in on those pages too. So I want an insecure session for this user too.

How can I do this with Rails?

like image 910
Michael Avatar asked Jan 17 '23 12:01

Michael


1 Answers

You have correctly realized that the problem with mixing http and https in a standard Rails application is that the session will need to be insecure (i.e. referenced via an insecure cookie), which means it is vulnerable to session side-jacking.

As you mentioned in your comment to @nmott's answer, one approach is to have both a secure and an insecure cookie.

Rather than referencing two identical sessions, for my purposes I find it sufficient to have an insecure Rails session along with a secure signed cookie that merely references the user_id of the currently logged in user. In other words, I don't need a complete copy of the session, just something unique for each user (in a secure cookie) that matches the insecure session.

In each action that is accessed via SSL (and has a current user), I check that the secure signed cookie user_id matches the user_id stored in the insecure Rails session. If there is a match, I assume everything is fine and proceed as normal by referencing the insecure session. If there is not a match, then I display an error message. I accomplish this with a before_filter method such as the following:

def verify_secure_user_cookie
  # If we have a current user and the request is SSL, we want to make sure the user
  # has a secure cookie that matches the current user's id.  This prevents attackers
  # from side-jacking a session by obtaining a cookie from a non-SSL request.
  if current_user and request.ssl?
    unless cookies.signed[:user_id] == current_user.id
      raise StandardError, "Invalid secure user cookie"
    end
  end
end

Presumably, the legitimate user will always have the secure cookie and never see the error message. An attacker would only be able to copy the insecure cookie and would not have access to the secure cookie. In such a case, he could side-jack the session and access non-SSL pages, but he would not be able to access SSL pages using the victim's session.

Thus, your non-SSL pages are still vulnerable to side-jacking, but your SSL pages are not vulnerable to session side-jacking. For this to be effective, you have to enforce SSL for all actions that need to be secure (either from eavesdropping or from session side-jacking). Using force_ssl in the controller is one way to do this, or you can roll your own.

like image 156
Nathan Avatar answered Jan 26 '23 02:01

Nathan