Closed f1337 closed 3 years ago
We should also use a separate key for our session encryption vs our database encryption. More investigation on how this cookie encryption key is set/stored is needed.
This has been bumped in priority. Let's pick it up next sprint.
Great article comparing/contrasting various session storage options
This gem may be exactly what we're looking for!
Scratch that... it looks like this is only for signed key rotation "Graceful secret key rotation for the signed cookie store in Rails"
Here's an example that gracefully rotates the keys
va.gov has two cookies that I'm aware of. The api_session cookie belongs to the vets-api session, but we also have an sso_cookie, which pertains to the shared cookie between MHV and va.gov. If we ever do rotate the sso key, this will need to be coordinated between va.gov and MHV (https://dsva.slack.com/archives/CQHBJ5U06/p1624652893152200?thread_ts=1624650862.151000&cid=CQHBJ5U06)
The sso cookie is custom encrypted via the SSOEncryptor/Aes256CbcEncryptor whereas the vets_api_session cookie is encrypted/decrypted via the the secret_key_base value
This explains how session cookies are used in vets-api along with encryption methods. Also explained is how vets-api encrypts db attributes with proposed solutions on how to rotate encryption keys gracefully.
The vets-api api_session
cookie gets encrypted using the apps secret_key_base The secret key base is stored in credstash and accessed via settings.yml. Each environment has it’s own secret_key_base, located in the devops repo. Rails 5 introduced encrypted creds, which is typically where the secret_key_base would be stored, but vets-api uses credstash for sensitive key storage.
Since vets-api is in api_only mode, out of the box it doesn’t include the session/cookie middleware. The middleware was extended in order to add back the session layer. See application.rb here.
The proposed solution is to gracefully rotate out the old keys (secret_key_base) in order to avoid logging users out that have a current session.
Upon visiting vets-api with a session encrypted with the old key, the session will be rotated and re-encrypted with the new secret_key_base value. Given this, currently logged in users have a chance to visit vets-api, get their cookie read with the old_secret_key_base and have it rewritten with the new secret_key_base.
I’ve created a branch and started to poke at the cookie_rotation initializer which will gracefully rotate cookies.
In the devops repo, I’ve created a branch that adds the settings config for the secret_key_base and old_secret_key_base values. I’ve created the old_secret_key_base values in credstash, which are a copy of the current secret_key_base values. I still need to create version 2 of the secret_key_base values. I believe you can generate new keys via the rails secret
command.
Currently, local and dev environment login is broken (see slack conversation) so I did a test in staging. I was able to successfully decrypt the cookie, given that I had the secret_key_base. A malicious actor could hijack a session. See the steps below:
Steps to reproduce:
Next steps for api_session cookie key rotation:
Summary
This request is based on an chain-exploit from Metasploit. It is based on our using an encrypted cookie for session storage.
Exploit outline
Marshal.load
everything in the contents, including protected class access.Kernel.exec
, then get our MPI certificates, then have full access to MPI.Suggested Remediation
@f1337 recommends we start rotating session keys, or move to server side session storage. However, database sessions can be SLOW, so consider storing sessions in redis, shared memory, etc.
AC