diff --git a/README.adoc b/README.adoc index cff325480b6..a07ccefc493 100644 --- a/README.adoc +++ b/README.adoc @@ -65,3 +65,8 @@ https://help.github.com/articles/creating-a-pull-request[Pull requests] are welc == License Spring Security is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license]. + +=== Vulnerabilities Fixes By Nokia +* Fixing the below Vulnerabilities. + * https://spring.io/security/cve-2025-22228/ + * https://spring.io/security/cve-2025-22234/ diff --git a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java index 0f8d082fdf0..6eac349070a 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java +++ b/crypto/src/main/java/org/springframework/security/crypto/bcrypt/BCrypt.java @@ -610,7 +610,10 @@ private static String hashpw(byte passwordb[], String salt, boolean for_check) { char minor = (char) 0; int rounds, off; StringBuilder rs = new StringBuilder(); - + // FIX for CVE-2025-22228 (The Bypass) AND CVE-2025-22234 (The Timing Mitigation) + if (!for_check && passwordb.length > 72) { + throw new IllegalArgumentException("password cannot be more than 72 bytes"); + } if (salt == null) { throw new IllegalArgumentException("salt cannot be null"); } diff --git a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java index b3780847d91..7a1ff320cac 100644 --- a/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java +++ b/crypto/src/test/java/org/springframework/security/crypto/bcrypt/BCryptPasswordEncoderTests.java @@ -222,4 +222,36 @@ public void checkWhenNoRoundsThenTrue() { assertThat(encoder.matches("wrong", "$2a$00$9N8N35BVs5TLqGL3pspAte5OWWA2a2aZIs.EGp7At7txYakFERMue")).isFalse(); } + // FIX for CVE-2025-22228 (The Bypass) AND CVE-2025-22234 (The Timing Mitigation) + @Test + public void encodeWhenPasswordOverMaxLengthThenThrowIllegalArgumentException() { + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + String password72chars = "123456789012345678901234567890123456789012345678901234567890123456789012"; + encoder.encode(password72chars); + + String password73chars = password72chars + "3"; + assertThatIllegalArgumentException().isThrownBy(() -> encoder.encode(password73chars)); + } + + @Test + public void matchesWhenPasswordOverMaxLengthThenAllowToMatch() { + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + String password71chars = "12345678901234567890123456789012345678901234567890123456789012345678901"; + String encodedPassword71chars = "$2a$10$jx3x2FaF.iX5QZ9i3O424Os2Ou5P5JrnedmWYHuDyX8JKA4Unp4xq"; + assertThat(encoder.matches(password71chars, encodedPassword71chars)).isTrue(); + + String password72chars = password71chars + "2"; + String encodedPassword72chars = "$2a$10$oXYO6/UvbsH5rQEraBkl6uheccBqdB3n.RaWbrimog9hS2GX4lo/O"; + assertThat(encoder.matches(password72chars, encodedPassword72chars)).isTrue(); + + // Max length is 72 bytes, however, we need to ensure backwards compatibility + // for previously encoded passwords that are greater than 72 bytes and allow the + // match to be performed. + String password73chars = password72chars + "3"; + String encodedPassword73chars = "$2a$10$1l9.kvQTsqNLiCYFqmKtQOHkp.BrgIrwsnTzWo9jdbQRbuBYQ/AVK"; + assertThat(encoder.matches(password73chars, encodedPassword73chars)).isTrue(); + } + }