1

Where is Rails generating the session id that it gives a user over a cookie? How is it verifying the session id given over a cookie? Does it save the session id, or does it use some hash function based on secret_token?

According to the Rails guide:

The session id is a 32 byte long MD5 hash value.

A session id consists of the hash value of a random string. The random string is the current time, a random number between 0 and 1, the process id number of the Ruby interpreter (also basically a random number) and a constant string. Currently it is not feasible to brute-force Rails' session ids. To date MD5 is uncompromised, but there have been collisions, so it is theoretically possible to create another input text with the same hash value. But this has had no security impact to date.

I found no links to the code that does this. I searched for uses of rand and srand, MD5 and such but found nothing useful. The closest I found was in actionpack/lib/action_dispatch/middleware/session/abstract_store.rb which does the following:

def generate_sid
  sid = SecureRandom.hex(16)
  sid.encode!(Encoding::UTF_8)
  sid
end

This matches up with the format of session id I find in the session cookie, but not with the documentation in the guide. This also doesn't explain how sessions are verified.

According to this blog session id's are not stored or validated on the server side, but then how does it distinguish a session id that is valid or not?

Does someone know where the code that does this is, or a good guide for this? Thanks!

Other References:

Rails 3 ActiveRecordStore session_id tampering

Community
  • 1
  • 1

2 Answers2

3

You are correct, generate_sid1 is in charge of creating a session ID for new sessions.

When a session is first created, it generates a session id, sets it in your cookie, and caches it in CacheStore2. Once you make a request with a cookie, it re-builds the CookieStore and checks to make sure that the session id exists in the cache. If it exists, then it trusts the sesson. If it does not exist, then it does not trust the session. Since the session id is a 32 byte long value, it would be very difficult to guess an active session id that is in the cache.

lightswitch05
  • 9,058
  • 7
  • 52
  • 75
  • Ah so it does keep the session_id cached. That's contrary to what the first article I posted noted, which threw me off. The other piece of my question involving how the session_id is generated I found the answer to and posted as well. Thanks. – Alejandro Wainzinger Jun 03 '14 at 07:49
1

It turns out that SecureRandom.hex calls SecureRandom.random_bytes which is what the paragraph from the Rails guide is describing. It may perhaps have been better for them to reference the SecureRandom function in use, as newer versions may change this algorithm.

Notice the use of current time, pid and so forth.

def self.random_bytes(n=nil)
  n = n ? n.to_int : 16

  if defined? OpenSSL::Random
    @pid = 0 if !defined?(@pid)
    pid = $$
    if @pid != pid
      now = Time.now
      ary = [now.to_i, now.nsec, @pid, pid]
      OpenSSL::Random.seed(ary.to_s)
      @pid = pid
    end
    return OpenSSL::Random.random_bytes(n)
  end

  ...
end

https://github.com/ruby/ruby/blob/v1_9_3_547/lib/securerandom.rb#L56