← Back to case studies
Case Study

RCE in Apache Tomcat via Partial PUT Path Equivalence

CVSS 9.8 Critical
Fixed March 10, 2025
Disclosed March 10, 2025
Repository apache/tomcat
GHSA-83qj-6fr2-vhqg — Path Equivalence: 'file.Name' (Internal Dot) leading to Remote Code Execution and/or Information disclosure and/or malicious content added to uploaded files via write-enabled Default Servlet in Apache Tomcat.

Under specific conditions (non-default config), an attacker could upload a malicious serialized session file, then trigger deserialization for full RCE — without any authentication.


🔴 PullLight — Critical Finding
This path construction is derived from user-supplied URL path — an attacker can use internal dot equivalence (..upload/..WEB-INF) to escape the intended upload directory.

The vulnerable code converts the request path to a temp filename via path.replace('/', '.'), which means /uploads/../../../sessions/SESSION_ID becomes ./uploads/../../../sessions/SESSION_ID — the filename itself encodes the path structure. Combined with file-based session persistence and a deserialization gadget on the classpath, this enables pre-auth RCE with a single crafted PUT request.
→ The fix replaces the path-based temp filename with File.createTempFile() — cryptographically random, attacker-uncontrollable. Plus explicit delete() in a finally block.

The patch replaces the dangerous pattern where user-supplied request path was converted to a temp filename by replacing all '/' with '.' — enabling path traversal via internal dot equivalence. The secure fix uses File.createTempFile("put-part-", null, tempDir) for a cryptographically random, attacker-uncontrollable temp filename, plus explicit temp file deletion in a finally block.

// Before: path.replace('/', '.') encodes user-supplied path into filename File tempDir = (File) getServletContext().getAttribute(ServletContext.TEMPDIR); String convertedResourcePath = path.replace('/', '.'); File contentFile = new File(tempDir, convertedResourcePath); // After: cryptographically random temp filename — attacker cannot predict or control File tempDir = (File) getServletContext().getAttribute(ServletContext.TEMPDIR); File contentFile = File.createTempFile("put-part-", null, tempDir); // Plus explicit cleanup (not just deleteOnExit()): } finally { if (tempContentFile != null) { tempContentFile.delete(); } }

PullLight catches this class of vulnerability automatically

More CVE Case Studies