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>

>
> 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 [http://www.schneier.com/blog/
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>