Micronaut TimeConverterRegistrar Memory Exhaustion via Accept-Language Header
Micronaut's `TimeConverterRegistrar` has an unbounded `formattersCache` that allows memory exhaustion via a crafted `Accept-Language` header, where an unauthenticated attacker can crash the JVM by sending requests with novel locale tags to `@Format`-annotated endpoints, growing the cache until heap memory is exhausted, affecting Micronaut applications with `micronaut-context` versions 4.3.0 and above, up to but not including 4.10.22.
Micronaut’s TimeConverterRegistrar component contains a vulnerability that can lead to denial-of-service (DoS). The formattersCache within TimeConverterRegistrar is an unbounded ConcurrentHashMap that caches DateTimeFormatter instances. The cache key is derived from the @Format annotation pattern concatenated with the locale obtained from the HTTP Accept-Language header. By sending HTTP requests with arbitrary BCP 47 private-use extensions in the Accept-Language header (e.g., en-x-a001, en-x-a002), an unauthenticated attacker can generate a large number of unique cache keys. This leads to uncontrolled memory consumption, eventually exhausting the available heap memory and causing the JVM to crash with an OutOfMemoryError. The vulnerability affects Micronaut applications that expose endpoints with @Format-annotated temporal parameters and exists in micronaut-context versions 4.3.0 and above, up to but not including 4.10.22. This is similar to GHSA-2hcp-gjrf-7fhc but affects a different cache.
Attack Chain
- An attacker sends an HTTP request to a Micronaut server.
- The request includes a crafted
Accept-Languageheader with a novel BCP 47 private-use extension (e.g.,en-x-attacker). - Micronaut’s
HttpHeaders.findAcceptLanguage()parses theAccept-Languageheader and extracts the locale usingLocale.forLanguageTag(). - The extracted locale is passed to
AbstractRouteMatch.newContext()and stored in theConversionContext. - The request is routed to an endpoint with a
@Format-annotated temporal parameter. TimeConverterRegistrar.getFormatter(pattern, context)is called to retrieve aDateTimeFormatterfor the given pattern and locale.- Since the locale is novel, a new
DateTimeFormatteris created and added to the unboundedformattersCachewith the concatenatedpattern + localeas the key. - The attacker repeats this process with many unique
Accept-Languagevalues, causing theformattersCacheto grow without bounds, leading to anOutOfMemoryErrorand crashing the JVM, resulting in denial of service.
Impact
Successful exploitation of this vulnerability allows an unauthenticated attacker to crash any Micronaut server that exposes an endpoint with a @Format-annotated temporal type parameter. The memory consumption grows linearly with the number of unique Accept-Language values sent by the attacker. Due to the large number of possible BCP 47 private-use extensions, attackers can easily exhaust server memory. This can lead to denial of service, disrupting legitimate users. The TimeConverterRegistrar is active in all Micronaut HTTP server applications by default.
Recommendation
- Apply the fix pattern used for GHSA-2hcp-gjrf-7fhc by replacing the unbounded
ConcurrentHashMapwith a boundedConcurrentLinkedHashMap. - Upgrade to
micronaut-contextversion 4.10.22 or later to receive the patched version. - Monitor web server logs for a high volume of requests with unique
Accept-Languageheaders using the provided Sigma rule. - Consider implementing rate limiting on requests with unique
Accept-Languageheaders to mitigate the risk of exploitation.
Detection coverage 3
Micronaut Excessive Unique Accept-Language Headers
mediumDetects a high volume of requests with unique Accept-Language headers, potentially indicating a memory exhaustion attack against Micronaut's TimeConverterRegistrar.
Micronaut Accept-Language Locale Parsing
lowDetects requests where the Accept-Language header is parsed, indicating potential locale-based vulnerabilities.
Micronaut endpoint with @Format annotation
infoDetects access to specific endpoints potentially susceptible to the TimeConverterRegistrar vulnerability based on cs-uri-query.
Detection queries are kept inside the platform. Get full rules →