Apache Tomcat Partial PUT漏洞学习
字数 2248 2025-08-29 22:41:24

Apache Tomcat Partial PUT漏洞与文件会话持久化漏洞分析

CVE-2025-24813: Partial PUT漏洞

漏洞描述

Apache Tomcat的Partial PUT原始实现使用基于用户提供的文件名和路径生成的临时文件,当处理不完整的PUT请求时,会将文件路径中的分隔符/替换为.。当应用使用了Tomcat的文件会话持久化功能并使用了默认的会话存储位置时,攻击者可以通过partial PUT请求将包含恶意序列化数据的文件上传至会话目录,并完成反序列化。

影响版本

  • Apache Tomcat 1.0.0-M1至11.0.1
  • Apache Tomcat 10.1.0-M1至10.1.33
  • Apache Tomcat 9.0.0.M1至9.0.97

利用条件

  1. DefaultServlet启用了写入功能(ReadOnly=False)
  2. 支持Partial PUT请求
  3. 应用程序开启了Tomcat基于文件的会话持久化功能,并采用默认的存储位置
  4. 应用程序存在能被用于反序列化的库

漏洞复现步骤

  1. context.xml中开启Session的持久化存储:
<Manager className="org.apache.catalina.session.PersistentManager">
    <Store className="org.apache.catalina.session.FileStore" directory="session"/>
</Manager>
  1. 开启DefaultServlet的默认写入功能:
<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>
  1. 如果Tomcat本地依赖中存在Jackson链,可以尝试上传反序列化文件

漏洞分析

  1. 在DefaultServlet处理doPut请求时,当readOnly为False且开启parseContentRange分块传输字段后,会进入executePartialPut方法

  2. executePartialPut中:

    • 从上下文获取临时目录对象
    • 将资源路径中的/替换为.
    • 以读写模式打开新创建的临时文件
    • 从请求输入流中读取数据(每次4096字节)
    • 将数据写入临时文件
  3. 临时目录默认位置:${CATALINA_BASE}/work/Catalina/${HOST_NAME}/${CONTEXT_PATH}

  4. 由于开启了Session持久化存储,session文件的默认存储点正好位于上述临时文件夹

  5. 当加载session时,会从临时文件夹中查找session命名的文件,通过流读取文件内容,最终通过readObjectData对内容进行反序列化,导致RCE

CVE-2024-50379: 文件大小写条件竞争漏洞

漏洞描述

由于MacOS和Windows平台的Tomcat在加载JSP文件时使用File.exists()检查文件是否存在,而平台不区分大小写,导致可以通过条件竞争方式加载xxx.Jsp文件并成功写入DefaultServlet中,可能导致服务器权限被接管。

影响版本

  • 1.0.0-M1 <= Apache Tomcat <= 11.0.1
  • 10.1.0-M1 <= Apache Tomcat <= 10.1.33
  • 9.0.0.M1 <= Apache Tomcat <= 9.0.97

利用条件

DefaultServlet启用了默认HTTP PUT写入功能,或存在任意文件上传漏洞。

漏洞分析

  1. Tomcat通过getResource方法安全访问Web应用资源:

    • 首先验证路径获取资源
    • 资源不存在则返回空资源对象
    • DirResourceSetWebResourceSet继承实现接口
  2. file方法中:

    • 对资源文件进行安全检查(阻止符号链接,检查文件合法性)
    • 通过normalize统一平台路径分隔符
  3. 关键问题:

    • 访问test.jsp时,file.getCanonicalPath()得到test.Jsp
    • getCanonicalPath是区分大小写的,但底层FindFirstFileWAPI不区分大小写
    • absPath获取到的是test.jsp,与canPath(test.Jsp)比较时因大小写差异返回空对象
  4. 当文件夹中不存在test.Jsp时,访问test.jsp

    • canPathabsPath都获取到test.jsp
    • 文件判断通过,返回文件
  5. 利用方式:

    • readonly=False时,并发执行PUT和GET方法
    • 由于没有锁机制,可能导致f.exists通过资源检查
    • 通过并发PUT xxx.Jsp和GET xxx.jsp,当PUT请求文件落地时,GET可能读取xxx.Jsp并交给JspServlet处理
  6. 修复方式:增加了锁机制,在write操作未完成时阻塞read操作

总结对比

  1. CVE-2025-24813

    • Partial PUT处理不完整PUT请求时替换文件路径分隔符
    • 利用session持久化机制,PUT上传文件到临时文件夹
    • 通过session完成反序列化
  2. CVE-2024-50379

    • MacOS/Windows平台因File.exists()检查及大小写忽略问题
    • 通过条件竞争加载xxx.Jsp文件写入DefaultServlet
    • GET xxx.jsp可能加载到xxx.Jsp并由JspServlet处理
  3. CVE-2017-12615

    • 构造特殊后缀名绕过检测
    • 让DefaultServlet处理请求上传JSP文件
    • 导致Webshell上传

参考

  • https://mp.weixin.qq.com/s/ewvMUC7CFNMmwexVLVOAzA
Apache Tomcat Partial PUT漏洞与文件会话持久化漏洞分析 CVE-2025-24813: Partial PUT漏洞 漏洞描述 Apache Tomcat的Partial PUT原始实现使用基于用户提供的文件名和路径生成的临时文件,当处理不完整的PUT请求时,会将文件路径中的分隔符 / 替换为 . 。当应用使用了Tomcat的文件会话持久化功能并使用了默认的会话存储位置时,攻击者可以通过partial PUT请求将包含恶意序列化数据的文件上传至会话目录,并完成反序列化。 影响版本 Apache Tomcat 1.0.0-M1至11.0.1 Apache Tomcat 10.1.0-M1至10.1.33 Apache Tomcat 9.0.0.M1至9.0.97 利用条件 DefaultServlet启用了写入功能(ReadOnly=False) 支持Partial PUT请求 应用程序开启了Tomcat基于文件的会话持久化功能,并采用默认的存储位置 应用程序存在能被用于反序列化的库 漏洞复现步骤 在 context.xml 中开启Session的持久化存储: 开启DefaultServlet的默认写入功能: 如果Tomcat本地依赖中存在Jackson链,可以尝试上传反序列化文件 漏洞分析 在DefaultServlet处理 doPut 请求时,当 readOnly 为False且开启 parseContentRange 分块传输字段后,会进入 executePartialPut 方法 在 executePartialPut 中: 从上下文获取临时目录对象 将资源路径中的 / 替换为 . 以读写模式打开新创建的临时文件 从请求输入流中读取数据(每次4096字节) 将数据写入临时文件 临时目录默认位置: ${CATALINA_BASE}/work/Catalina/${HOST_NAME}/${CONTEXT_PATH} 由于开启了Session持久化存储,session文件的默认存储点正好位于上述临时文件夹 当加载session时,会从临时文件夹中查找session命名的文件,通过流读取文件内容,最终通过 readObjectData 对内容进行反序列化,导致RCE CVE-2024-50379: 文件大小写条件竞争漏洞 漏洞描述 由于MacOS和Windows平台的Tomcat在加载JSP文件时使用 File.exists() 检查文件是否存在,而平台不区分大小写,导致可以通过条件竞争方式加载 xxx.Jsp 文件并成功写入DefaultServlet中,可能导致服务器权限被接管。 影响版本 1.0.0-M1 <= Apache Tomcat <= 11.0.1 10.1.0-M1 <= Apache Tomcat <= 10.1.33 9.0.0.M1 <= Apache Tomcat <= 9.0.97 利用条件 DefaultServlet启用了默认HTTP PUT写入功能,或存在任意文件上传漏洞。 漏洞分析 Tomcat通过 getResource 方法安全访问Web应用资源: 首先验证路径获取资源 资源不存在则返回空资源对象 DirResourceSet 从 WebResourceSet 继承实现接口 在 file 方法中: 对资源文件进行安全检查(阻止符号链接,检查文件合法性) 通过 normalize 统一平台路径分隔符 关键问题: 访问 test.jsp 时, file.getCanonicalPath() 得到 test.Jsp getCanonicalPath 是区分大小写的,但底层 FindFirstFileW API不区分大小写 absPath 获取到的是 test.jsp ,与 canPath ( test.Jsp )比较时因大小写差异返回空对象 当文件夹中不存在 test.Jsp 时,访问 test.jsp : canPath 和 absPath 都获取到 test.jsp 文件判断通过,返回文件 利用方式: 当 readonly=False 时,并发执行PUT和GET方法 由于没有锁机制,可能导致 f.exists 通过资源检查 通过并发PUT xxx.Jsp 和GET xxx.jsp ,当PUT请求文件落地时,GET可能读取 xxx.Jsp 并交给 JspServlet 处理 修复方式:增加了锁机制,在write操作未完成时阻塞read操作 总结对比 CVE-2025-24813 : Partial PUT处理不完整PUT请求时替换文件路径分隔符 利用session持久化机制,PUT上传文件到临时文件夹 通过session完成反序列化 CVE-2024-50379 : MacOS/Windows平台因 File.exists() 检查及大小写忽略问题 通过条件竞争加载 xxx.Jsp 文件写入DefaultServlet GET xxx.jsp 可能加载到 xxx.Jsp 并由 JspServlet 处理 CVE-2017-12615 : 构造特殊后缀名绕过检测 让DefaultServlet处理请求上传JSP文件 导致Webshell上传 参考 https://mp.weixin.qq.com/s/ewvMUC7CFNMmwexVLVOAzA