# BCrypt Hash Check

To assist with the mitigation steps for CVE-2022-xxxx, you can use this tool to check your database for hashes that need updating.

After you've integrated the application [with your database](#configuring-for-your-database), the tool works in two steps.

To demonstrate this a in-memory sample application is used.
On that sample application, you can run the `check` step, like so:

./mvnw spring-boot:run@check

This will check the sample database for any BCrypt hashes that need updating.

Then, you can run the `update` step, like so:

./mvnw spring-boot:run@update

This will attempt to update any vulnerable hashes it detects in the sample database.

The sample application uses the provided `VulnerabilityCheck` class to check and update each password hash.

### Configuring For Your Database

WARNING: Only proceed with these steps after having updated your application to use a number of rounds lower than 31.
OWASP currently recommends a value of 10 though on some high-powered systems values as high as 16 are used.

The tool ships with an in-memory sample for testing purposes.
You will need to replace it with classes of your own that integrate with your data.

To do this, first clone this repository.

Then, replace the code in the `sample` package with code that can access the password data in your application.
You may want to write code that checks existing passwords to see if they are vulnerable.
You will want to code that updates any affected hashes.
In both cases, you can use `VulnerabilityCheck` to check and update a given hash.

TIP: In writing the above code, take into consideration how many passwords you have to update.
Remember to take into account that the database connection can fail, computers can crash, memory can run out, and so on.
It is not advisable, for example, to bring millions of records at once into memory.

After updating the password hashes, you can now update to the latest Spring Security.
If you are using Spring Security's password update feature, then as users log in, their password will automatically be re-hashed to your newly configured rounds value.

### FAQ

Q: How do I know if my hashes are vulnerable?

A: They are vulnerable if they were hashed using Spring Security's `BCrypt` class with a work factor of 31.
You can confirm this by checking the password hashes in your system that are managed by Spring Security.
If they start with '{bcrypt}$2a$31', '{bcrypt}$2b$31', '{bcrypt}$2y$31', '{bcrypt}$2$31', '$2a$31', '$2b$31', '$2y$31', or '$2$31', then that password is vulnerable and needs to be updated.  

Q: How should I change my application?

A: OWASP recommends a work factor of 10 for BCrypt.
Some higher-powered systems will use a value as high as 16.
Every system is different and BCrypt is designed to be able to increase the work factor over time as needed.

Q: Where do I change my application?

A: You are likely setting the work factor by constructing a `BCryptPasswordEncoder` like so:

new BCryptPasswordEncoder(31)

It may appear in a bean definition like this:

public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(31);

You can look for that string and update it.
Note that the work factor could be driven in your application by an external property, meaning you'd want to change it in your external configuration instead.

Q: I've just updated Spring Security and now some or all logins and user registrations are hanging. What happened?

A: As of Spring Security 5.5.7+, 5.6.4+, 5.7.0+, password hashes indicating a work factor of 31 --
for example, starting with '{bcrypt}$2a$31', '{bcrypt}$2b$31', '{bcrypt}$2y$31', '{bcrypt}$2$31', '$2a$31', '$2b$31', '$2y$31', or '$2$31' -- will take 2-3 days to complete each hash computation.
To alleviate this, you will need to change Spring Security to use a lower number of rounds.
Then, use this tool to update the vulnerable password hashes.

Q: I've completed all three recommended steps (change BCryptPasswordEncoder configuration, update password hashes, and update Spring Security).
The modified password hashes aren't updating to my newly configured work factor.
What should I do?

Make sure that you have a bean of type `UserDetailsPasswordService` published.
This bean is what is used to update passwords to a new BCrypt log rounds.

Q: Why can't Spring Security simply update the vulnerable passwords at upgrade time without the need for this tool?

First, because with the latest Spring Security, password hashes with a work factor of 31 are correctly computed and thus take 2-3 days to complete each.
It's an impractical expectation to suppose that this is a reasonable cost for applications to incur.

Second, Spring Security only supports increasing the work factor (say from 10 to 12), not decreasing (say from 31 to 10).