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
Usertable 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.
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 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.
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.
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.
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.
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.
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.