AEAD encrypted cookies and sessions#28132
Conversation
|
Could you explain briefly too why migrating to AEAD is good? |
|
Sure, by using AES with GCM, ciphertexts will be shorter and decryption and encryption will be quicker. With GCM, authentication and encryption are processed together instead of separately like we see with the HMAC and AES CBC authenticated encryption setup. Additionally, the announcement today from Google about SHA1 collisions somewhat drove me to make this PR. While unrelated to security and encryption features in Rails, the announcement motivated me to look into what it would take to update Rails' cookies to use more modern encryption. If we do not go down the AEAD route for encrypted cookies, we should at least be exploring using SHA256 for the digest option for As an aside, AEAD in general aims to make cryptographic processes simpler and less error prone. I think it may be worthwhile making GCM the default for |
|
Thanks for the explanation! |
|
@eugeneius there is a small cookie jar class in this PR to upgrade HMAC CBC encrypted cookies to GCM. This could be altered to handle the upgrade from SHA1 to SHA256 though. I think in the long run introducing GCM cookies is better though. The smaller ciphertexts is a worthwhile improvement. |
|
Oh, nice! You even mentioned it in the description 🤦♂️ |
|
Put together some small benchmarks comparing the two modes. The script also outputs the length of two ciphertexts, one for each mode. The repo is here: https://github.com/mikeycgto/message_encryptor-benchmark |
Important to note here this finding of a SHA1 collision has nothing to do with the security of HMAC-SHA1, which MessageVerifier uses. So people shouldn't panic if they cannot upgrade straight away. That said, not only is an AEAD mode faster for encryption/decryption (AES-GCM especially with processor instructions) but it also produces smaller cookies (shown in #25874) so 👍👍👍 if we can transparently upgrade. |
|
Agreed @bdewater. HMACs in general are still secure even when the underlying hash function have known collisions issues. Google's announcement motivated me to look into what it would take to update Rails' cookies to use more modern encryption and security. This is actually something I've been thinking about for a while, today's news just lit the spark for me! |
Notes on Legacy SupportThought more about this and want to clarify somethings as far as legacy support goes. Currently there are two legacy cookie jar classes This PR adds a I think it's worth considering at this time if If support is kept, I fully intend to test all legacy configurations. That is, I want to make sure "encrypted" cookies that are just signed with a Thus, my main question is, should Possible Major API ChangesI'd also go as far as to suggest some major API changes to the cookie middleware. Specifically, we could deprecate the
This suggestion is obviously a lot more significant than what the PR has initially set out to do. I figured it is worth suggesting and discussing though! |
54c40b5 to
3b1e5f4
Compare
3b1e5f4 to
be8b9e8
Compare
AFAIK Rails usually introduces deprecation warnings in minor versions before removing stuff. With 5.1 already in beta, removal seems more suited when master targets 5.2. Just my $0.02. |
c5eaeaf to
8170de3
Compare
guides/source/security.md
Outdated
There was a problem hiding this comment.
Also needs to keep the 80 char limit.
There was a problem hiding this comment.
We need to copy over the intro from the _5_1.rb file and nestle the config to be under config.action_dispatch.
There was a problem hiding this comment.
To nestle the config under action_dispatch we'll need to move the false assign to this file:
Your override in initializer further below in that file then needs to take the new namespace into account.
actionpack/CHANGELOG.md
Outdated
There was a problem hiding this comment.
Remember to rewrite this too 😉
actionpack/CHANGELOG.md
Outdated
There was a problem hiding this comment.
Don't forget to add your name too 😄
*Michael Coyne*
|
@kaspth these changes sound good. Will get to them either later tonight or tomorrow morning sometime. Thanks for reviewing it again! |
f5fc1ba to
362d263
Compare
|
Made some more changes and moved the One small question I have is if this config value is set to Thanks again for all the reviews! Can't wait to see this feature merged in -- smaller 🍪 for all!! |
362d263 to
d6bfe8d
Compare
|
Thought a bit more about this and I realized that because the two old salt values are still set by default, Perhaps we should add a second configuration flag, such as Ultimately, I think having direct configuration flags for both AEAD cookies as well as supporting the upgrade behavior is easier for developers to deal with than indirectly controlling this behavior via the salt config values. This way, new applications or applications that no longer need the upgrade behavior can easily opt-out of it. Thoughts? |
d6bfe8d to
3faa392
Compare
|
Just rebased and my |
0c37842 to
834db45
Compare
|
I decided to add the Not sure how to handle the failing test with regards to |
It shouldn't be opt-in on a if respond_to?(:action_dispatch)
action_dispatch.use_authenticated_cookie_encryption = true
endright after here: rails/railties/lib/rails/application/configuration.rb Lines 87 to 89 in 75fa8dd I don't understand the need for |
kaspth
left a comment
There was a problem hiding this comment.
Some last defaults wrangling, but we're getting pretty close!
guides/source/configuring.md
Outdated
There was a problem hiding this comment.
Will double check this.
guides/source/configuring.md
Outdated
There was a problem hiding this comment.
Are we sure that's the default?
There was a problem hiding this comment.
Will double check this.
There was a problem hiding this comment.
I think this gets solved by Rails removing support for upgrading the cookies from CBC, so I'd rather not make this a config.
There was a problem hiding this comment.
See my latest comment for more discussion on this flag. I'm thinking to we just leave the upgrade behavior as is and have future version use "pure" GCM cookies...
There was a problem hiding this comment.
I was recently schooled on the new_framework_defaults_* file by @matthewd and how I've been doing them wrong.
We should follow the now added example above: use the future default, but start it commented out.
There was a problem hiding this comment.
Understood. This file was a bit of mystery to me as well. Did this discussion occur in the PR from dhh for the new fragment caching feature? I'm definitely interested in fully understanding its uses!
There was a problem hiding this comment.
Newer Rails app load_defaults from the version they were created with:
So a brand new 5.2 app shouldn't have this file, it's only for 5.1 upgrading apps.
actionpack/CHANGELOG.md
Outdated
There was a problem hiding this comment.
Let's mention the AES GCM benefits here (faster, shorter — copy from the security guide if you like) and that new_framework_defaults_5.2.rb shows how to upgrade.
I can make this change and remove the test I added.
Originally I had the Due to these salt values still being defined the Perhaps this can be solved by removing the upgrade middleware altogether in future versions. I know cleaning up the cookies middleware in general is one of the overall goals for the GSoC project so perhaps we should just leave this be for now and have it get released as is in Rails 5.2? |
My thoughts exactly 👍 (though the GSoC project might not necessarily clean up old cookies versions, but we'll see). I think it's fine to check for the presence of the 3 salt values because |
There was a problem hiding this comment.
So this would be:
request.secret_key_base.present? &&
request.authenticated_encrypted_cookie_salt.present? &&
request.encrypted_signed_cookie_salt.present? &&
request.encrypted_cookie_salt.present?And we can kill the use_authenticated_cookie_encryption? and upgrade_legacy_hmac_aes_cbc_cookies? methods then.
authenticated_encrypted_cookie_salt was placed up further, since it's less likely to be assigned on upgrading apps and we'll avoid the presence check on the present in older releases salt values.
Related: I'm not sure why we check the presence of the secret_key_base here. Rails apps won't boot without it these days.
There was a problem hiding this comment.
Checking secret_key_base seemed a bit unnecessary and I do think it's likely safe to drop at this point.
I'll also rework my commits soon and drop the upgrade_legacy_hmac_aes_cbc_cookies flag and revert the upgrade_legacy_hmac_aes_cbc_cookies? method to just check if the salt values are present?. I'll also update the above mention changes to the various guides. At that point, I think we'll be close to ready for this PR. Thanks again!!
This commit changes encrypted cookies from AES in CBC HMAC mode to Authenticated Encryption using AES-GCM. It also provides a cookie jar to transparently upgrade encrypted cookies to this new scheme. Some other notable changes include: - There is a new application configuration value: +use_authenticated_cookie_encryption+. When enabled, AEAD encrypted cookies will be used. - +cookies.signed+ does not raise a +TypeError+ now if the name of an encrypted cookie is used. Encrypted cookies using the same key as signed cookies would be verified and serialization would then fail due the message still be encrypted.
834db45 to
5a3ba63
Compare
|
@mikeycgto great work! 👏 |
|
@kaspth thanks so much for all the help and the feedback! Excited to see this get merged and see Rails get more modern encryption!! |
|
@mikeycgto no problem! Thanks for bringing Rails up to speed 💪 |
Summary
This PR is the start of migrating from HMAC AES-CBC encrypted cookies to AEAD encrypted cookies. Commit d4ea18a added AES-256-GCM for Authenticated Encryption support. I'm hoping this PR could be the start of migrating cookies and sessions to this form of encryption.
I think it's worth considering to what degree we should be supporting legacy signed and encrypted cookies as well. This PR includes a
UpgradeLegacyHmacAesCbcCookieJarclass which aims to seamlessly upgrade encrypted cookies. Should we be looking to deprecate older legacy schemes now?Other Information
This PR comments out some tests that are now broken. Depending on how we move forward with encrypted cookies and to the degree to which legacy cookies are supported, I will update, fix, and add any tests as needed.