VYPR
Medium severity6.5NVD Advisory· Published Nov 25, 2024· Updated May 6, 2026

CVE-2024-10270

CVE-2024-10270

Description

A vulnerability was found in the Keycloak-services package. If untrusted data is passed to the SearchQueryUtils method, it could lead to a denial of service (DoS) scenario by exhausting system resources due to a Regex complexity.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.keycloak:keycloak-servicesMaven
< 24.0.924.0.9
org.keycloak:keycloak-servicesMaven
>= 25.0.0, < 26.0.626.0.6

Patches

1
5d6c91f3309d

EMBARGOED CVE-2024-10270 org.keycloak/keycloak-services: Keycloak Denial of Service (#35218)

https://github.com/keycloak/keycloakDouglas PalmerNov 22, 2024via ghsa
2 files changed · +80 18
  • services/src/main/java/org/keycloak/utils/SearchQueryUtils.java+68 18 modified
    @@ -19,36 +19,86 @@
     
     import java.util.HashMap;
     import java.util.Map;
    -import java.util.regex.Matcher;
    -import java.util.regex.Pattern;
     
     /**
      * @author Vaclav Muzikar <vmuzikar@redhat.com>
      */
     public class SearchQueryUtils {
    -    public static final Pattern queryPattern = Pattern.compile("\\s*(?:(?<name>[^\"][^: ]+|.)|\"(?<nameEsc>(?:\\\\.|[^\\\\\"])+)\"):(?:(?<value>[^\"][^ ]*)|\"(?<valueEsc>(?:\\\\.|[^\\\\\"])+)\")\\s*");
    -    public static final Pattern escapedCharsPattern = Pattern.compile("\\\\(.)");
     
         public static Map<String, String> getFields(final String query) {
    -        Matcher matcher = queryPattern.matcher(query);
             Map<String, String> ret = new HashMap<>();
    -        while (matcher.find()) {
    -            String name = matcher.group("name");
    -            if (name == null) {
    -                name = unescape(matcher.group("nameEsc"));
    +        char[] chars = query.trim().toCharArray();
    +        for (int i = 0; i < chars.length; i++) {
    +            boolean inQuotes = false;
    +            boolean internal = false;
    +            String name = "";
    +            while (i < chars.length && chars[i] != ':') {
    +                if (chars[i] == '\\') {
    +                    if (chars[i+1] == '\"') {
    +                        i++;
    +                    }
    +                    else if (chars[i+1] == '\\') {
    +                        i+=2;
    +                        continue;
    +                    }
    +                }
    +                else if (chars[i] == '\"') {
    +                        if(!inQuotes && name.length() > 0) {
    +                            internal = true;
    +                        }
    +                        else if(internal) {
    +                            internal = false;
    +                        }
    +                        else {
    +                            inQuotes = !inQuotes;
    +                            i++;
    +                            continue;
    +                        }
    +                }
    +                else if(chars[i] == ' ' && !inQuotes) {
    +                    break;
    +                }
    +                name += chars[i];
    +                i++;
                 }
    -
    -            String value = matcher.group("value");
    -            if (value == null) {
    -                value = unescape(matcher.group("valueEsc"));
    +            if(i == chars.length || chars[i] == ' ') {
    +                continue;
    +            }
    +            i++;
    +            inQuotes = false;
    +            internal = false;
    +            String value = "";
    +            while (i < chars.length) {
    +                if (chars[i] == '\\') {
    +                    if (chars[i+1] == '\"') {
    +                        i++;
    +                    }
    +                    else if (chars[i+1] == '\\') {
    +                        i+=2;
    +                        continue;
    +                    }
    +                }
    +                else if (chars[i] == '\"') {
    +                    if(!inQuotes && value.length() > 0) {
    +                        internal = true;
    +                    }
    +                    else if(internal) {
    +                        internal = false;
    +                    }
    +                    else {
    +                        inQuotes = !inQuotes;
    +                        i++;
    +                        continue;
    +                    }
    +                }
    +                else if(chars[i] == ' ' && !inQuotes) {
    +                    break;
    +                }
    +                value += chars[i];
    +                i++;
                 }
    -
                 ret.put(name, value);
             }
             return ret;
         }
    -
    -    public static String unescape(final String escaped) {
    -        return escapedCharsPattern.matcher(escaped).replaceAll("$1");
    -    }
     }
    
  • services/src/test/java/org/keycloak/utils/SearchQueryUtilsTest.java+12 0 modified
    @@ -23,6 +23,7 @@
     import java.util.Map;
     
     import static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.assertTrue;
     
     /**
      * @author Vaclav Muzikar <vmuzikar@redhat.com>
    @@ -78,4 +79,15 @@ private void testParseQuery(String query, String... expectedStr) {
     
             assertEquals(expected, actual);
         }
    +
    +    @Test
    +    public void testReDoS() {
    +        long start = System.currentTimeMillis();
    +        int count = 50000;
    +        for (int i = 0; i < count; i++) {
    +            SearchQueryUtils.getFields(" ".repeat(1443) + "\n\n".repeat(1443) + 0);
    +        }
    +        long end = System.currentTimeMillis() - start;
    +        System.out.println("took: " + end + " milliseconds");
    +    }
     }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

10

News mentions

0

No linked articles in our index yet.