Announcement

Collapse
No announcement yet.

Rails CookieStore

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Rails CookieStore

    Ruby on Rails isn't exactly known for a strong stance on security, and the new soon-to-be-released version uses a rather controversial feature from a security perspective.

    Many sites were having performance problems storing user sessions. There were several ways this could be accomplished: in flat files, in a database, in memcached...

    Rails 2.0 chose a rather... interesting way of storing sessions: in cookies.

    Rails serializes your complete session and stores it in plaintext in a cookie.

    This has obvious security concerns: sessions often store the user ID you're logged in as in the session. If you can set or change this value you can log in as any user in the system.

    To try to add some security to this approach, the Rails core team added HMAC hashing to CookieStore. The session cookie ends up being the serialized session object plus the HMAC hash of your session data and a server-side secret.

    This seems stupid for a number of reasons. The first is that you are handed your entire session in plaintext. If there is any sensitive data in the session, anyone can read it. It also lets any user probe the session for anything that looks vulnerable and gain insight into the way the application works that they probably shouldn't have. The second is that every session cookie's length is increased by the full length of the hash. That's 32-bytes with a hash algorithm like SHA-256.

    It seems like it'd make a whole shitton more sense to just encrypt the entire session. Sessions would be shorter and unreadable by clients. Overall this whole approach seems like poor use of encryption.

    This was recently compounded by the fact that Rails' default server secret generator was discovered to be rather lousy...
    45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B0
    45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B1
    [ redacted ]

  • #2
    Re: Rails CookieStore

    Originally posted by bascule View Post
    The first is that you are handed your entire session in plaintext. If there is any sensitive data in the session, anyone can read it. It also lets any user probe the session for anything that looks vulnerable and gain insight into the way the application works that they probably shouldn't have.
    Well, if your session is overl SSL, it will continue to be secure. If it is plain HTTP, then it may leak more information than before (and attackers could get at the information in one packet rather than monitoring the whole session). If it is mixed mode, then you might run into some trouble.

    Originally posted by bascule View Post
    The second is that every session cookie's length is increased by the full length of the hash. That's 32-bytes with a hash algorithm like SHA-256.
    (Well, 64 bytes since I assume it is simply storing the hexadecimal representation as text. 4 bytes if they implement some custom Base64 trick.)

    Pardon me, but I don't see why that's a problem. It would seem to be rather trivial when compared to the possible session size (especially in Base64).

    Originally posted by bascule View Post
    It seems like it'd make a whole shitton more sense to just encrypt the entire session. Sessions would be shorter and unreadable by clients. Overall this whole approach seems like poor use of encryption.
    Well, that's exactly what HTTPS is for: encrypting the entire session! But I know what you mean...

    I'm not exactly sure how it would become smaller unless the encryption process started by compressing the data (which it probably should). It is kind of an odd choice to not encrypt.

    I hadn't heard of this issue, but it would seem trivial to implement a replay attack here. What prevents this from being an issue? Server-side, single-use session invalidation? (Asking only in jest ... very few people would ever go through that much effort.)

    Comment


    • #3
      Re: Rails CookieStore

      Originally posted by Voltage Spike View Post
      (Well, 64 bytes since I assume it is simply storing the hexadecimal representation as text. 4 bytes if they implement some custom Base64 trick.)

      Pardon me, but I don't see why that's a problem. It would seem to be rather trivial when compared to the possible session size (especially in Base64).
      Yeah, my bad, I believe the entire session and the HMAC signature are all encoded in base64.

      It is kind of an odd choice to not encrypt.
      Their claimed rationale is:

      "If you're storing secrets in session, odds are you have a code smell and ought not to. In the rare exceptional case, you can switch to a server-side session store or write a simple EncryptedCookieStore subclass."

      I hadn't heard of this issue, but it would seem trivial to implement a replay attack here. What prevents this from being an issue? Server-side, single-use session invalidation? (Asking only in jest ... very few people would ever go through that much effort.)
      They claim to use a timestamp / ip / nonce combination to invalidate sessions and prevent replay attacks.

      Apparently they're also using SHA1, not SHA256... awesome.

      Here's a fun article:

      Owning Rails 2.0 Cookies at OWASP

      And here's another claiming that the secret key generator Rails is using is insecure:

      http://izumi.plan99.net/blog/index.p...r-all-because/
      45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B0
      45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B1
      [ redacted ]

      Comment


      • #4
        Re: Rails CookieStore

        Originally posted by bascule View Post
        They claim to use a timestamp / ip / nonce combination to invalidate sessions and prevent replay attacks.
        I still claim ignorance of both Ruby and Rails, but I have been doing some reading...

        It appears that they claim such things could be used, but, as I said earlier, few developers will go through the effort. Such a technique (excepting simple expiration) would require writing to a central database and it appears the entire purpose of this change is to avoid writing to a central database.

        I guess the rule is simple: if you are building a new session on the server based on a client-side cookie, you should authenticate the user again.

        Really, the only new potential attack here versus client-side session IDs is the ability to modify session data, and they protect against that attack. Having clear-text session data is primarily useful in deciding which of several collected cookies should be sent.

        Originally posted by bascule View Post
        At a glance, it appears to be a brute force attack against SHA-1 and >30 character passwords. Good luck with that, but I won't be holding my breath.

        Bummer, but it appears the author updated the page to indicate Rails is now secure.

        Comment


        • #5
          Re: Rails CookieStore

          Originally posted by Voltage Spike View Post
          It appears that they claim such things could be used, but, as I said earlier, few developers will go through the effort. Such a technique (excepting simple expiration) would require writing to a central database and it appears the entire purpose of this change is to avoid writing to a central database.
          Yeah, looking at the actual source code nothing's tracked in the session. If you get ahold of a sesson cookie, it can be used anywhere so long as the secret doesn't change. There's no built-in expiry mechanism short of changing the server secret.
          45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B0
          45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B1
          [ redacted ]

          Comment


          • #6
            Re: Rails CookieStore

            Well, guess I understand why now...

            Here's a benchmark of CookieStore (using SHA1 HMAC): (times are cpu, interpreter, system, real)
            0.890000 0.000000 0.890000 ( 0.887541)
            0.890000 0.000000 0.890000 ( 0.890730)
            0.890000 0.000000 0.890000 ( 0.889791)

            Here it is with Blowfish:
            2.720000 0.010000 2.730000 ( 2.726776)
            2.720000 0.010000 2.730000 ( 2.724652)
            2.730000 0.010000 2.740000 ( 2.746762)

            That's quite a noticable difference (3X slower)
            45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B0
            45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B1
            [ redacted ]

            Comment

            Working...
            X