Deny list lower cases all passwords when loading from file

Closes #28381

We always lower case the inbound password before comparing against the deny list
yet the deny list may contain passwords that contain upper case letters. With
this change we will now convert passwords from the deny list into lower case
while loading, ensuring that more passwords match the deny list.

Signed-off-by: Christopher Miles <twitch@nervestaple.com>
This commit is contained in:
Christopher Miles 2024-04-04 13:14:47 -04:00 committed by Marek Posolda
parent dbd016d4ec
commit 1646315939
4 changed files with 43 additions and 2 deletions

View file

@ -103,7 +103,7 @@ Password cannot be already used by the user. {project_name} stores a history of
Password must not be in a blacklist file.
* Blacklist files are UTF-8 plain-text files with Unix line endings. Every line represents a blacklisted password.
* {project_name} compares passwords in a case-insensitive manner. All passwords in the blacklist must be lowercase.
* {project_name} compares passwords in a case-insensitive manner.
* The value of the blacklist file must be the name of the blacklist file, for example, `100k_passwords.txt`.
* Blacklist files resolve against `+${kc.home.dir}/data/password-blacklists/+` by default. Customize this path using:
** The `keycloak.password.blacklists.path` system property.

View file

@ -327,7 +327,7 @@ public class BlacklistPasswordPolicyProviderFactory implements PasswordPolicyPro
protected void insertPasswordsInto(BloomFilter<String> filter) throws IOException {
try (BufferedReader br = newReader(path)) {
br.lines().forEach(filter::put);
br.lines().map(String::toLowerCase).forEach(filter::put);
}
}

View file

@ -0,0 +1,37 @@
package org.keycloak.policy;
import org.junit.Assert;
import org.junit.Test;
import java.nio.file.Paths;
import static org.keycloak.policy.BlacklistPasswordPolicyProviderFactory.FileBasedPasswordBlacklist;
public class BlacklistPasswordPolicyProviderTest {
@Test
public void testUpperCaseInFile() {
FileBasedPasswordBlacklist blacklist =
new FileBasedPasswordBlacklist(Paths.get("src/test/java/org/keycloak/policy"), "short_blacklist.txt");
blacklist.lazyInit();
// all passwords in the deny list are in lower case
Assert.assertFalse(blacklist.contains("1Password!"));
}
@Test
public void testAlwaysLowercaseInFile() {
FileBasedPasswordBlacklist blacklist =
new FileBasedPasswordBlacklist(Paths.get("src/test/java/org/keycloak/policy"), "short_blacklist.txt");
blacklist.lazyInit();
Assert.assertTrue(blacklist.contains("1Password!".toLowerCase()));
}
@Test
public void testLowerCaseInFile() {
FileBasedPasswordBlacklist blacklist =
new FileBasedPasswordBlacklist(Paths.get("src/test/java/org/keycloak/policy"), "short_blacklist.txt");
blacklist.lazyInit();
Assert.assertTrue(blacklist.contains("pass1!word"));
}
}

View file

@ -0,0 +1,4 @@
pass1!word
1Password!
Password1!
!Password1