CookieSession recommendations

After looking at the controversy, delving into my security textbook, and reading some articles on hashing, I would like to recommend some tweaks to the CookieSesson defaults and the new 'rake secret'.

1) Change the default hash used in the cookies to SHA256 as a hole was semi-recently found in SHA1.

2) Make 'rake secret' use the lengthier SHA512 hash and output the secret key in base64, or better yet, in a binary string. The 30 character length requirement will require multiple hashes to be generated; however, it will add a significant amount of entropy to every character. (The limited character set in a hex-characters-only key may lead to a differential cryptanalysis -- I'm no crypto-expert, so if someone else knows different, please ease my mind) OR 3) Make 'rake secret' use OpenSSL to generate the secret key.

4) Add, at least an option, to hash the IP address of the user into the cookie's hash. This should prevent against replay attacks automatically without the application developer having to write in this check.

I am willing to write the patches for any/all of these changes.

Also, I noted that a secret key was also set in a comment in the generated ApplicationController. I assume that this is unnecessary since the secret is set by default in the environment.rb. I recommend taking this out of the ApplicationController, assuming it's unnecessary.

And a comment on previous thoughts about using asymmetric key cryptography for generating a signature: I don't recommend this as it is much much more processor intensive than generating a cryptographically secure hash, and a cryptographically secure hash is probably just as effective -- for now.

If I'm beating a dead horse on any of this, I apologize. I tried to do as much research on the controversy as possible, but I, of course, could have missed some things.

After looking at the controversy, delving into my security textbook, and reading some articles on hashing, I would like to recommend some tweaks to the CookieSesson defaults and the new 'rake secret'.

1) Change the default hash used in the cookies to SHA256 as a hole was semi-recently found in SHA1.

2) Make 'rake secret' use the lengthier SHA512 hash and output the secret key in base64, or better yet, in a binary string. The 30 character length requirement will require multiple hashes to be generated; however, it will add a significant amount of entropy to every character. (The limited character set in a hex-characters-only key may lead to a differential cryptanalysis -- I'm no crypto-expert, so if someone else knows different, please ease my mind) OR 3) Make 'rake secret' use OpenSSL to generate the secret key.

4) Add, at least an option, to hash the IP address of the user into the cookie's hash. This should prevent against replay attacks automatically without the application developer having to write in this check.

I am willing to write the patches for any/all of these changes.

Great! These are fine changes and your efforts are quite welcome.

Also, I noted that a secret key was also set in a comment in the generated ApplicationController. I assume that this is unnecessary since the secret is set by default in the environment.rb. I recommend taking this out of the ApplicationController, assuming it's unnecessary.

Agreed.

And a comment on previous thoughts about using asymmetric key cryptography for generating a signature: I don't recommend this as it is much much more processor intensive than generating a cryptographically secure hash, and a cryptographically secure hash is probably just as effective -- for now.

If I'm beating a dead horse on any of this, I apologize. I tried to do as much research on the controversy as possible, but I, of course, could have missed some things.

Not at all. I look forward to your patches!

Best, jeremy

I'm +1 on *anything* that prevents replay attacks (it's one of my big peeves about CookieSessions in the first place), but I wonder about the edge cases.

If I'm coming through a proxy farm like AOL's, will I always come through the same proxy during the same session? What about mobile users moving to different cells - do their IPs stay constant? Or DHCP users on networks with short leases? I recall reading (a few years ago) about cable companies switching users' IP addresses frequently in a sort of security-by-obscurity defense against botnet infections.

In *theory*, there are a lot of legitimate reasons for a user's IP address to change during a session, which would break this. But I have no idea if any of those ways really happen with any significant frequency, so I'm really not implying-by-asking - just asking.

Don't add checks by IP, you will break things. For example, I load balance my internet connection over a cable and DSL line at home, and connections from the same machine on my internal network can appear to come from either the cable IP or the DSL IP. This is on a fairly simple home setup. Large enterprises are sure to have proxy server architectures that don't guarantee that that all connections from the client A to server B go through the same proxy server.

I'm not sure if it is possible to make CookieStore sessions invulnerable to replay attacks. Without some server controlled state, replay attacks should always be possible. This is similar to the impossibility of implementing completely secure DRM (it doesn't work because the user always has at least theoretical access to the encryption keys).

The best you can do with a CookieStore is mitigate the replay attacks, and the best way to do that is probably an application configurable timeout. The timeout should preferably based on the start of the session and not the last access time, so no session can be used indefinately.

The idea of using OpenSSL for the key is a good one (I used it manually to create my keys), but keep in mind that this won't work when OpenSSL isn't installed, so there needs to be a fallback method.

>> 4) Add, at least an option, to hash the IP address of the user into >> the cookie's hash. This should prevent against replay attacks >> automatically without the application developer having to write in >> this check.

I'm +1 on *anything* that prevents replay attacks (it's one of my big peeves about CookieSessions in the first place), but I wonder about the edge cases.

If I'm coming through a proxy farm like AOL's, will I always come through the same proxy during the same session? What about mobile users moving to different cells - do their IPs stay constant?

Worse, you may get a new IP address for each connection, and with plans/batteries being what they are, you can imagine a lot of these rapid-fire connect/disconnect cycles. My daily e-mail checking habit involves several IP addresses within the span of a few minutes.

Assaf

My ADSL provider makes short disconnects twice a day to force changing of the IP. Imagine if the app I was currently using suddenly blocked me because it would think that I’m an attacker …

After looking at the controversy, delving into my security textbook, and reading some articles on hashing, I would like to recommend some tweaks to the CookieSesson defaults and the new 'rake secret'.

1) Change the default hash used in the cookies to SHA256 as a hole was semi-recently found in SHA1.

I don't mind either way, another few bytes couldn't hurt if the algorithm is readily available.

But which attack on SHA1 are you referring to? Any 'feasible' attack I've seen involves finding collisions, i.e. one person creating two messages with the same digest, which is of no significance here.

Finding a message M1 where, for a given message M0, SHA1(M1) = SHA1(M0), requires an effort of ~2**106 (Bruce Schneier, Feb 2005 [1]).

Please cite some sources, there's already been plenty of FUD on this topic.

2) Make 'rake secret' use the lengthier SHA512 hash and output the secret key in base64, or better yet, in a binary string. The 30 character length requirement will require multiple hashes to be generated; however, it will add a significant amount of entropy to every character. (The limited character set in a hex-characters-only key may lead to a differential cryptanalysis -- I'm no crypto-expert, so if someone else knows different, please ease my mind)

Encoding doesn't matter, we just need a secret with enough significant bits.

If you're saying that the requirement should be raised to account for people using hex-only (which they might, as that's what the generated string does), you may have a point.

OR 3) Make 'rake secret' use OpenSSL to generate the secret key.

AFAIK Rails' SecretKeyGenerator already does use OpenSSL or other strong platform-specific crypto libraries if available.

"rake secret", at least here on rails 2.0.2, outputs a 128-char hex string, that's 512 bits. I'm not in a position to comment on whether that's strong or weak.

4) Add, at least an option, to hash the IP address of the user into the cookie's hash. This should prevent against replay attacks automatically without the application developer having to write in this check.

As mentioned by others, this is very likely to break things.

Crypto is hard, and the more people who look at Rails' implementation, the better.

There's been a lot of random noise and FUD on this topic, but if you know what you're doing I'm sure more input and contributions are welcome.

Regards, Isak

[1] <http://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html&gt;

> > 1) Change the default hash used in the cookies to SHA256 as a hole > was semi-recently found in SHA1.

I don't mind either way, another few bytes couldn't hurt if the algorithm is readily available.

But which attack on SHA1 are you referring to? Any 'feasible' attack I've seen involves finding collisions, i.e. one person creating two messages with the same digest, which is of no significance here.

The problem is that when somebody can find a collision, they can use those collisions to effectively reverse the hash to determine the secret key.

Finding a message M1 where, for a given message M0, SHA1(M1) = SHA1(M0), requires an effort of ~2**106 (Bruce Schneier, Feb 2005 [1]).

Please cite some sources, there's already been plenty of FUD on this topic.

Bruce Schneier reported in August 2005 that SHA1 can be cracked on the order of 2^63, which can be done. [http://www.schneier.com/blog/archives/2005/08/new_cryptanalyt.html\]

Another Chinese researcher is reported to have cracked SHA1 in January 2007, but nothing has been confirmed regarding her research. [http://en.epochtimes.com/news/7-1-11/50336.html\]

> 2) Make 'rake secret' use the lengthier SHA512 hash and output the > secret key in base64, or better yet, in a binary string. The 30 > character length requirement will require multiple hashes to be > generated; however, it will add a significant amount of entropy to > every character. (The limited character set in a hex-characters-only > key may lead to a differential cryptanalysis -- I'm no crypto-expert, > so if someone else knows different, please ease my mind)

Encoding doesn't matter, we just need a secret with enough significant bits.

If you're saying that the requirement should be raised to account for people using hex-only (which they might, as that's what the generated string does), you may have a point.

I guess I'm saying a couple things: 1) Increase the amount of significant bits that 'rake secret' outputs and 2) either (a) the key should converted from whatever-encoding into binary or we should (b) implement an entropy check to verify that there are enough significant bits.

> 3) Make 'rake secret' use OpenSSL to generate the secret key.

AFAIK Rails' SecretKeyGenerator already does use OpenSSL or other strong platform-specific crypto libraries if available.

SecretKeyGenerator tries these generators, in this order:

    1. Ruby's SecureRandom     2. Win32's CryptGenRandom     3. dev/urandom     4. OpenSSL     5. the time, a random number, and a couple strings

I would like to see this order: 4, 1, 3, 2, 5. Basically, this is my ordering of trust. I don't have any sources to back this up, yet. They will come as soon as I have a minute to find them.

"rake secret", at least here on rails 2.0.2, outputs a 128-char hex string, that's 512 bits. I'm not in a position to comment on whether that's strong or weak.

That is very strong, however, the fact that it only uses a-f and 0-9 leaves the potential for a differential cryptanalysis based on the bits that never change. I don't know if this is possible at this time -- it's probably not, but I'd rather eliminate the potential hole.

> 4) Add, at least an option, to hash the IP address of the user into > the cookie's hash. This should prevent against replay attacks > automatically without the application developer having to write in > this check.

As mentioned by others, this is very likely to break things.

Based on the discussion, I agree. Scrap this idea.

Here's my reasoning for suggesting the change to the order that 'rake secret' finds a random number generator.

> > 3) Make 'rake secret' use OpenSSL to generate the secret key.

> AFAIK Rails' SecretKeyGenerator already does use OpenSSL or other > strong platform-specific crypto libraries if available.

SecretKeyGenerator tries these generators, in this order:

    1. Ruby's SecureRandom     2. Win32's CryptGenRandom     3. dev/urandom     4. OpenSSL     5. the time, a random number, and a couple strings

I would like to see this order: 4, 1, 3, 2, 5. Basically, this is my ordering of trust. I don't have any sources to back this up, yet. They will come as soon as I have a minute to find them.

I would alter my proposed order to 4, 3, 1, 2, 5, and here's why:

OpenSSL is simply the most proven and trusted. It's purpose is security, and if it becomes vulnerable, the makers will fix it.

dev/urandom is next in line because it is almost as good as dev/ random. The problem with it is that it doesn't block when it runs out of entropy, -- it recycles previously used numbers. This is fine for a system that isn't generating tons of secure random numbers.

SecureRandom looks ok and hasn't had any serious vulnerabilities released about it (that I can find). However, it isn't implemented in Ruby 1.8 (it's new in 1.9), so it simply hasn't proven itself yet.

The CryptGenRandom is pretty serious flawed since Windows 2000 through the original Vista release [http://eprint.iacr.org/2007/419.pdf\]. Hebrew University found a vulnerability that allows a crack on the order of 2^23. And in the new Vista SP1, Microsoft switched the PRNG to the new Dual_EC-DRBG which is said to have an NSA backdoor [Schneier on Security archives/2007/12/dual_ec_drbg_ad.html].

The final option should be a last resort.

Comments? Objections? Suggestions?

I already cited an article that touch on the topic, but probably should have linked RFC 4270: Attacks on Cryptographic Hashes in Internet Protocols[1], which is written specifically to elaborate on this issue.

Regards, Isak

[1] <http://tools.ietf.org/html/rfc4270&gt;