dbAuth makes extensive use of the CryptoJS library for encrypting cookies and password hashing. The CryptoJS team recently announced a CVE which disclosed that some of the defaults they use for the PBKDF2 hashing algorithm are not secure enough relative to current standards.
NOTE This vulnerability is only of concern if you suspect that someone got ahold of the
User
table in your database. This doesn’t affect session data stored in cookies, or anything sent over-the-wire.
They also noted that the entire library is now deprecated, and recommend moving to the node:crypto
library which ships with node itself. We spent a couple of days working on this change, and it is now available in the v6.3.3 release.
You can upgrade to the release candidate by running yarn rw upgrade
.
What changes did we make?
Password Hashes
dbAuth now hashes passwords using scrypt with reasonable cost, block size and parallelization options (2^14, 8, 1) so that users don’t see a huge delay in login simply waiting for their password to be checked. But, it makes it much more difficult for an attacker to try and find a hash collision using bulk methods as each hash creation could take ~100ms. The cost, block size and parallelization values are stored along with the hash, making this change forward-compatible as computers get faster: the existing hashes can always be checked using the values stored along side, rather than assuming they are in the code and hope they never change.
In a future release we’d like to make these values configurable so that you can set them to whatever you want in the dbAuth config.
Session Cookies
Session cookies are now encrypted using AES-256-CBC and an initialization vector (similar to a salt in password hashing) stored along with the encrypted value in the cookie. Your SESSION_SECRET
is still the key for encrypting and decrypting.
What does this mean for users of your app?
Maybe surprisingly, this can have zero impact on your users!
For users that are already logged in, the very next request to GraphQL to check their login status will re-encrypt their session cookie with the new algorithm. They will continue on with business as usual.
The next time a user logs in, dbAuth will re-hash their password using the new algorithm.
How is this transparent to the user?
We first try to hash the password or decrypt the cookie using the new node:crypto
algorithms. If those fail, we fall back to trying to hash/decrypt using the older CryptoJS algorithms (but implemented in node:crypto
). If those work, that’s when we know to re-hash/re-encrypt using the new algorithm. If those fail, then the password really was wrong, so we fail as usual.
What if I really want to be secure?
If you create a new SESSION_SECRET
ENV variable, all users of your app will be logged out. This means that as soon as they return, they’ll log in (updating their hashed password) and then get the newly-encrypted session cookie.
Okay, but what if I want to be really, really secure?
If you suspect that your database has been compromised, your best option would be to change your SESSION_SECRET
and in addition delete all existing passwords in the database, which would force everyone to create a new one. They could do this either by using the Forgot Password flow, or a new mechanism that you create. You should probably communicate this to them ahead of time so they don’t freak out when their favorite password (mypassword123) suddenly stops working.
What do you recommend?
According to a research paper that prompted this CVE, it could take $45,000 to crack a single hash created using the less secure CryptoJS algorithm. Unless you’re Facebook, Instagram, or a government agency, it seems unlikely that someone would spend that to get your login. We recommend just upgrading to the v6.3.3 release and then carry on as usual. Over time all of your users will automatically be transitioned to the new algorithm with no impact on their daily lives.
If you normally have short-lived sessions and your users are used to logging in every couple of days, then it probably wouldn’t be much of a nuisance to change your SESSION_SECRET
and log everyone out, as it would greatly accelerate the update of their hashed password in the database.