According to https://passlib.readthedocs.io/en/stable/lib/passlib.hash.bcrypt_sha256.html#algorithm, to address the 72 byte limit of bcrypt, the algorithm executes
bcrypt(base64(sha-256(utf-8(password)))). Unfortunately, because the SHA-256 prehash is unsalted, the resulting bcrypt digest is vulnerable to breach correlation attacks.
To demonstrate this, suppose password breach 1 hashes passwords with
bcrypt(sha-256(password)), and breaches 2 and 3 just hashed passwords with
sha-256(password). All of the hashes from breaches 2 and 3 can be fed into bcrypt from breach 1 as
bcrypt(hash). Any successful hits, means the password cracker only need find the password from breaches 2 and 3, which means focusing on SHA-256 rather than spend the energy on bcrypt from breach 1. Basically, bcrypt was just removed from the workload.
This isn’t a theoretical attack. It’s used in practice right now by hobbyist and professional password crackers to make their workload as efficient as possible. A full presentation of breach correlation attacks can be found at BSides Vegas, 2018: https://www.youtube.com/watch?v=5su3_Py8iMQ.
The way to plug this vulnerability is to salt the prehash. This way, no correlated hits from breaches 2 and 3 will be successful in breach 1. This means that to discover the plaintext password in breach 1, the password cracker must focus their energy on cracking bcrypt directly.
The prehash salt doesn’t have to be unique per user, it doesn’t have to be random or unpredictable, and it doesn’t have to be updated per password change. The prehash salt can be a static pepper, such as the word “bcrypt”, your company name, or anything else. It need only change the resulting prehash, such that it won’t be found in other breaches.
One approach could be to
bcrypt(base64(sha-256(sha-256(“bcrypt”)||password)), cost, salt), while another would be to use an HMAC such as
bcrypt(base64(sha-256-hmac(password, “bcrypt”)), cost, salt).
This was recently brought up in the following Twitter thread (it goes deep, with many subthreads): https://twitter.com/AaronToponce/status/1224341295188983809