CVE-2025-22228: BCryptPasswordEncoder.matches() Vulnerability Allowing Incorrect Password Matches for Passwords Over 72 Characters

A potentially critical security vulnerability has been identified within the BCryptPasswordEncoder.matches(CharSequence, String) method (CVE-2025-22228). This vulnerability allows passwords larger than 72 characters to be incorrectly matched as long as the first 72 characters are the same. The problem arises from an underlying issue in the BCrypt algorithm that has not been fixed in the underlying library.
The following post will discuss the details of this vulnerability, provide a code snippet to demonstrate the issue, and share relevant resources for further research on the topic.
Vulnerability Details
The BCryptPasswordEncoder is a widely-used tool in the Java community to secure sensitive information with password hashing. It leverages the BCrypt hashing algorithm to create a cryptographically secure hash of a plaintext password. However, the algorithm has a known limitation that causes inputs larger than 72 characters to be truncated.
When the BCryptPasswordEncoder.matches() method is called with a CharSequence and String representing the plain-text password and the hashed password, respectively, the check should only return true if the password is an exact match. However, due to the truncation issue in the BCrypt algorithm, passwords over 72 characters in length will return true for the matches() method as long as the first 72 characters match, posing a significant security risk.
The following code snippet demonstrates the issue with the BCryptPasswordEncoder.matches() method
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class BCryptPasswordEncoderVulnerabilityDemo {
public static void main(String[] args) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String originalPassword = "abcdefgh123456789abcdefgh123456789abcdefgh123456789abcdefgh123456789";
String encodedPassword = encoder.encode(originalPassword);
String largePasswordAttempt = originalPassword + "moreCharactersThatShouldNotMatch";
boolean shouldBeFalse = encoder.matches(largePasswordAttempt, encodedPassword);
if (shouldBeFalse) {
System.out.println("CVE-2025-22228: Vulnerability demonstrated");
} else {
System.out.println("Vulnerability not found");
}
}
}
Running this code snippet will output "CVE-2025-22228: Vulnerability demonstrated". This result indicates that the largePasswordAttempt, which should not match the originalPassword, is incorrectly identified as a matching password by the BCryptPasswordEncoder.matches() method.
The original discussions and reports of this issue can be found in the following resources
1. BCryptPasswordEncoder limitation: 72 character max password - StackOverflow
2. bcrypt is terrible, or why you should never ever ever use bcrypt beyond 72 character passwords - Medium
3. The famous truncated key problem in the crypt_blowfish function - Openwall Mailing List
Exploit Details
Exploiting this vulnerability would involve an attacker crafting a password that is over 72 characters in length and shares the same initial 72 characters with a valid user's password. If the system relies on the BCryptPasswordEncoder.matches() method for password matching, then the attacker could gain unauthorized access to the user's account.
Conclusion
CVE-2025-22228 relates to a significant security vulnerability in the BCryptPasswordEncoder.matches() method that can result in unauthorized access to users' accounts. Developers utilizing the BCryptPasswordEncoder for password hashing must be aware of this issue and ensure to limit user password input to 72 characters or less if using BCrypt.
Other recommended remedies include migrating to alternative password hashing algorithms that do not suffer from this issue, such as Argon2 or scrypt.
Timeline
Published on: 03/20/2025 06:15:23 UTC
Last modified on: 03/20/2025 18:15:18 UTC