# REPRO-2026-00282: Apache Tomcat partial PUT session deserialization RCE ## Summary Status: published Severity: high Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00282 CVE: CVE-2025-24813 ## Package Name: Apache Tomcat Ecosystem: maven Affected: Unknown Fixed: Unknown ## Root Cause # RCA Report: Apache Tomcat Partial PUT Session Deserialization RCE (CVE-2025-24813) ## Summary A real Apache Tomcat runtime code-execution path was reproduced via the DefaultServlet partial PUT implementation present in Tomcat 10.1.34. With the documented non-default preconditions enabled (`readonly=false` on the DefaultServlet, partial PUT support, Tomcat `PersistentManager` plus `FileStore` session persistence, and a deserialization gadget class available to the web application), an unauthenticated HTTP client can upload a serialized session object with a `Content-Range` PUT to `/payload.session`. Tomcat 10.1.34 stores the attacker-controlled body as `work/Catalina/localhost/ROOT/.payload.session`; a follow-up request carrying `Cookie: JSESSIONID=.payload` causes Tomcat to deserialize that file and execute the attacker-controlled command. Tomcat 10.1.35, the fixed negative control, does not create the FileStore session file and does not execute the command. ## Impact - **Package/component affected**: Apache Tomcat 10.1.x, specifically DefaultServlet partial PUT handling interacting with `org.apache.catalina.session.PersistentManager` / `FileStore` session deserialization. - **Affected versions**: Official Tomcat 10 security notes list CVE-2025-24813 as affecting Apache Tomcat 10.1.0-M1 through 10.1.34 and fixed in 10.1.35. Equivalent 9.x and 11.x ranges are also covered by the upstream advisory, but this run tested the Tomcat 10.1 line only. - **Risk level and consequences**: High/Critical under the documented preconditions. A remote unauthenticated attacker can turn a writable DefaultServlet partial PUT into attacker-controlled session-file creation and then trigger Java deserialization in the web application classloader. The demonstrated consequence is command execution as the Tomcat process user. ## Impact Parity - **Disclosed/claimed maximum impact**: Code execution / RCE in Apache Tomcat from a remote HTTP entrypoint. - **Reproduced impact from this run**: Full code execution was demonstrated. The proof payload executed `/bin/sh -c id > bundle/repro/vuln_rce_marker.txt` from Tomcat deserialization, producing `uid=1000(vscode) gid=1000(vscode) groups=1000(vscode)`. - **Parity**: `full`. - **Not demonstrated**: The run did not demonstrate internet-scale exploitation against a default Tomcat installation. The exploit requires the known non-default preconditions: DefaultServlet writes enabled, file-backed session persistence, and a deserialization-capable application/library class. The proof uses a deliberately deployed minimal webapp gadget class to make the deserialization effect deterministic and safe. ## Root Cause Tomcat's vulnerable partial PUT implementation used a temporary/file-store name derived from the user-provided request path by replacing path separators with dots. When the DefaultServlet was writable, a `PUT /payload.session` request with a `Content-Range` header could write the attacker-controlled body to a file whose path overlapped Tomcat's default FileStore session location: `work/Catalina/localhost/ROOT/.payload.session`. When the application used `PersistentManager` with the default `FileStore`, Tomcat looked up session ID `.payload` as that same file. A subsequent request with `Cookie: JSESSIONID=.payload` caused Tomcat to load and deserialize the attacker-written object using the web application's classloader. If the application classpath contained a gadget that performs attacker-influenced behavior during deserialization, this became code execution. Upstream documents this as CVE-2025-24813 and states it was fixed in Apache Tomcat 10.1.35 by commit `f6c01d6577cf9a1e06792be47e623d36acc3b5dc`. ## Reproduction Steps 1. Reference script: `bundle/repro/reproduction_steps.sh`. 2. The script is self-contained for this bundle. It: - downloads official Apache Tomcat 10.1.34 and 10.1.35 binary tarballs if not already cached under the bundle; - compiles a minimal serializable webapp gadget class whose `readObject()` executes a supplied command; - configures both Tomcat instances with DefaultServlet `readonly=false`, `PersistentManager`, and `FileStore`; - deploys the gadget class and a session-enabled `index.jsp` into each ROOT webapp; - starts both real Tomcat servers on local HTTP ports; - sends real unauthenticated HTTP `PUT /payload.session` requests with `Content-Range: bytes 0-5/100`; - triggers session loading with `GET /index.jsp` and `Cookie: JSESSIONID=.payload`; - checks that the vulnerable Tomcat creates `bundle/repro/vuln_rce_marker.txt` while the fixed Tomcat does not create `bundle/repro/fixed_rce_marker.txt`. 3. Expected evidence: Tomcat 10.1.34 returns PUT `201`, trigger `500`, creates the FileStore session file and writes the `id` command output marker. Tomcat 10.1.35 returns PUT `201` for an ordinary webapp resource, trigger `200`, does not create the FileStore `.payload.session`, and does not create the marker. ## Evidence - Primary proof log: `bundle/logs/cve2025_24813_requests.log`. - Consecutive script run logs: `bundle/logs/repro_rce_run1.log`, `bundle/logs/repro_rce_run2.log`. - Vulnerable Tomcat server log: `bundle/logs/tomcat-10.1.34-catalina.out`. - Fixed Tomcat server log: `bundle/logs/tomcat-10.1.35-catalina.out`. - Runtime manifest: `bundle/repro/runtime_manifest.json`. - Code execution marker: `bundle/repro/vuln_rce_marker.txt`. Key evidence excerpt from the final run: ```text vulnerable-10.1.34 PUT /payload.session Content-Range status: 201 vulnerable-10.1.34 GET /index.jsp Cookie:JSESSIONID=.payload status: 500 fixed-10.1.35 PUT /payload.session Content-Range status: 201 fixed-10.1.35 GET /index.jsp Cookie:JSESSIONID=.payload status: 200 vulnerable work session created: true fixed work session created: false vulnerable marker: uid=1000(vscode) gid=1000(vscode) groups=1000(vscode) fixed marker: CONFIRMED: vulnerable Tomcat executed attacker-controlled command: uid=1000(vscode) gid=1000(vscode) groups=1000(vscode) ``` Environment details captured by the script include Apache Tomcat 10.1.34 and 10.1.35 startup logs, OpenJDK runtime information in `catalina.out`, and real HTTP request/response header artifacts under `bundle/logs/`. ## Recommendations / Next Steps - Upgrade affected Tomcat deployments to Apache Tomcat 10.1.35 or later for the 10.1 branch; apply the corresponding fixed release for 9.x or 11.x deployments. - Keep the DefaultServlet `readonly` setting at its safe default (`true`) unless writes are strictly required and strongly authenticated/authorized. - Disable partial PUT support if it is not required by the application. - Avoid file-based session persistence at the default FileStore location when it is not required; prefer safer session storage designs. - Treat application classpath deserialization gadgets as security-sensitive. Add Java serialization filters and remove libraries/classes that are unsafe during deserialization. - Regression-test that `Content-Range` PUTs cannot create files in `work/Catalina/.../..session` and that `JSESSIONID=.` cannot load attacker-written files. ## Additional Notes - **Idempotency**: Confirmed. `bundle/repro/reproduction_steps.sh` was executed twice after the final fix and exited 0 both times with the same vulnerable-vs-fixed divergence and command-execution marker. - **Negative controls**: Tomcat 10.1.35 was configured with the same webapp and operational preconditions, but the exploit did not create the FileStore session file and did not execute the command. - **Related cleared lead**: The previous attempt's Tomcat 10.1.55 security-constraint/DefaultServlet PUT bypass was extended toward JSP upload RCE, but direct `.jsp` and classic trailing-slash variants did not produce executable JSP upload on this current Tomcat path. The confirmed RCE path is therefore the partial PUT session deserialization chain against 10.1.34. ## Reproduction Details Reproduced: 2026-07-11T13:12:29.424Z Duration: 2554 seconds Tool calls: 240 Turns: Unknown Handoffs: 3 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00282 pruva-verify CVE-2025-24813 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00282&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00282/artifacts/bundle/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - NVD: https://nvd.nist.gov/vuln/detail/CVE-2025-24813 ## Artifacts - bundle/repro/rca_report.md (analysis, 7939 bytes) - bundle/repro/reproduction_steps.sh (reproduction_script, 12514 bytes) - bundle/repro/hypothesis_ledger.md (documentation, 6547 bytes) - bundle/artifact_promotion_manifest.json (other, 4559 bytes) - bundle/artifact_promotion_report.json (other, 4577 bytes) - bundle/logs/repro_run5.log (log, 912 bytes) - bundle/logs/repro_run6.log (log, 912 bytes) - bundle/repro/validation_verdict.json (other, 758 bytes) - bundle/repro/runtime_manifest.json (other, 1588 bytes) - bundle/logs/cve2025_24813_requests.log (log, 830 bytes) - bundle/logs/repro_rce_run2.log (log, 540 bytes) - bundle/repro/vuln_rce_marker.txt (other, 54 bytes) - bundle/logs/tomcat-10.1.34-catalina.out (other, 8553 bytes) - bundle/logs/tomcat-10.1.35-catalina.out (other, 8697 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00282 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00282/artifacts/bundle/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00282 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev