资讯动态

Tomcat CVE-2025-24813漏洞解析:触发条件、自查方法与修复加固

发布时间:2026/10/20 9:42:50 来源:尧图企业网站定制
这两天在各安全群和漏洞平台里被反复刷屏的就是 Tomcat 的这个编号CVE-2025-24813国内目录里对应 CNVD-2025-04973。一眼扫到“远程代码执行”、再看到 Critical 级别的定级绝大多数人的第一反应都是赶紧查版本、找补丁、约变更窗口。我的建议是先花十分钟把这个漏洞的触发条件捋清楚再决定是连夜升级还是走临时缓解——因为它并不是一个“默认配置就能打穿”的漏洞不同环境下实际风险差别很大。这个漏洞最有意思的地方就在这里同样是高危定级有的业务环境几乎可以说是在裸奔有的环境却因为配置收敛得好而影响有限。做 Java 老项目的、还在跑低版本 Tomcat 的、开放过文件上传或者 PUT 写接口的服务是这轮排查的重点对象。本文我不打算堆砌公告原文而是按我自己排查漏洞时的思路把漏洞背景、原理拆解、自查方法、升级步骤和长期加固完整过一遍希望能帮你省点时间。1. 漏洞通告怎么看先说结论和影响1.1 这个漏洞“能干什么”先讲危害。CVE-2025-24813 本质上是远程代码执行攻击者一旦利用成功就能在 Tomcat 进程的权限下执行任意命令通俗说就是“拿到了一台服务器的控制权”。后续能干的事情就多了反弹一个shell、往应用目录写webshell、读取应用配置和数据库密码、横向探测内网路径都很成熟。不过它和那种“只要暴露了端口就能打”的漏洞不太一样。它的利用依赖于几个前置条件同时成立公告和后续分析基本都指向两个场景一是 Tomcat 在处理部分 PUT 请求时存在缺陷配合可写配置绕过校验进而覆盖或写入恶意文件二是 Session 持久化采用了非默认的存储配置攻击者可以把伪造的序列化数据放到特定目录触发反序列化攻击。打个比方这就好比储物间的门锁本身没坏但管理员把备用钥匙挂在了门口又恰好没有反锁。单个条件单独看可能不算致命组合在一起就成了能进入房间的通道。1.2 受影响版本与修复版本对照尤其要注意版本覆盖面很广从老分支一路铺到较新的分支。官方公告里列出的影响范围和修复版本可以对照看这里我把它们整理成表格方便你直接对照现有环境受影响分支受影响版本范围修复版本Tomcat 11.0.x11.0.0-M1 至 11.0.411.0.5 及以上Tomcat 10.1.x10.1.0-M1 至 10.1.4010.1.41 及以上Tomcat 9.0.x9.0.0.M1 至 9.0.999.0.100 及以上Tomcat 8.5.x8.5.5 至 8.5.1008.5.101 及以上如果线上环境正好落在这些区间里别急着焦虑继续往下看触发条件如果手里的版本已经超出上面的范围比如 9.0.101、10.1.42 这些基本可以确认补丁层面已经覆盖。还有一个很多人忽略的点如果你用的发行版自带 Tomcat比如从系统软件源安装的那么修复版本号可能会和官方编号有差异要同步关注系统维护方的安全公告。另外提一句一些集成部署方式也要一并检查比如在宿主机上装了原生 Tomcat、在容器镜像里内置 Tomcat、通过自动化运维平台分发的版本这些环境的版本管理经常出现“某个环境忘了升级”的盲区。2. 漏洞原理拆解不是 Tomcat“默认就能打”2.1 先捋一下 Tomcat 处理写请求的机制要理解这个漏洞得先知道 Tomcat 默认是怎么处理 HTTP 请求的。Tomcat 内置了一个叫 DefaultServlet 的组件专门负责处理静态资源的读取。对于 GET 和 HEAD 请求它负责把文件内容返回给客户端对于 PUT 和 DELETE 这些写请求它在默认情况下其实是拒绝的因为有一个关键属性readonly默认是true。只有在两种情况下这条防线才会失效第一种有人把readonly改成了false通常是业务需要支持文件上传、附件管理、页面静态化等第二种应用的 web.xml 或代码里重新声明了 DefaultServlet覆盖了默认配置。这些在老项目里太常见了尤其是早期做内容管理的系统几乎都会打开写权限。而 partial PUT 是 HTTP 协议里的一种“断点续传”式写法客户端通过Content-Range头告诉服务器“我要从文件的第几个字节开始写”Tomcat 也实现了这个能力。问题恰恰发生在 partial PUT 和条件头的组合处理上。2.2 Partial PUT 与条件头比较缺陷正常情况下当客户端发来一个带Content-Range的 PUT 请求时Tomcat 需要先判断文件当前的版本和客户端预期是否一致依赖的是一组协议头If-Match、If-Unmodified-Since、Range等。如果目标文件的 ETag 和你带过来的值不匹配或者文件更新时间和If-Unmodified-Since冲突服务器应当返回 412 状态码拒绝写入。受影响的版本里Tomcat 对这组条件头的组合判断出现了不一致。部分请求在逻辑上应该被拒绝实际却走进了“允许写入”的分支于是范围写入被放行。攻击者利用这一点可以对服务器上已经存在的文件发起局部覆盖不需要完整替换整个文件。这个问题的实际影响取决于能写到什么位置、能覆盖什么文件。如果应用部署目录下存在 JSP、JS、配置文件这类可被解析的资源攻击者把恶意内容追加或覆盖进去再通过浏览器触发访问代码就可能在服务端执行。需要注意的是这个利用链路通常要求攻击者知道目标文件的相对路径所以实际操作中往往会配合信息泄露、目录遍历或已知的默认路径来定位目标文件。2.3 Session 持久化与反序列化链路第二类场景和 Session 持久化有关。Tomcat 支持把用户的 Session 保存到磁盘由 PersistentManager 管理。如果配置了 FileStoreSession 会以 Java 序列化对象的形式写进某个目录。问题在于如果这个存储目录落在攻击者能写入的范围内比如恰好是 web 应用的某个上传目录攻击者上传一个精心构造的“Session 文件”Tomcat 在重新加载 Session 时会调用 Java 的readObject反序列化从而触发 gadget 链最终执行系统命令。这条链路里有两个必要条件一是应用本身存在任意文件写入能力比如前面说的 PUT 写权限或普通上传点二是 Session 持久化使用了非默认的FileStore配置。对于大多数跑默认配置的 Tomcat 来说第二个条件默认不成立这也是为什么说它不是“默认就能打”的原因。但换个角度看很多内部系统为了重启后不丢登录状态确实会开启持久化这类配置一旦暴露就比较容易中招。2.4 为什么说“利用条件苛刻”又“不得不防”坦白说两个场景都需要一定的前置条件用“苛刻”来形容并不夸张。但安全评估不能只看概率还要看结果。这类漏洞一旦被综合利用结果是直接获得命令执行权限属于最严重的风险等级扫描器和漏洞情报平台也一定会把它标记为重点关注对象。而且实际环境里的配置千奇百怪有人只开了 Session 持久化没限制目录权限有人给 DefaultServlet 开了写权限却不知道还有人用的是集成了旧版 Tomcat 的中间件。这些情况平时不会有人注意到等漏洞情报发出来再回头查往往都能发现一两个隐蔽的弱配置。所以公告出来后技术团队第一件事永远是盘点资产和配置不要跟风“全量升级”也别直接躺平先评估再说。3. 自查与处置如何确认自己的环境是否受影响3.1 三步自查一分钟定位风险先说版本号怎么查。如果你能登录服务器直接执行$CATALINA_HOME/bin/version.sh或者看$CATALINA_HOME/RELEASE-NOTES文件都能拿到具体版本。如果是容器化部署可以用docker inspect查看镜像的历史版本号或者进入容器查看。注意某些发行版会通过系统包管理工具安装 Tomcat这种情况下版本号以系统包管理工具里显示的版本为准。第二步查配置。重点打开conf/web.xml找 DefaultServlet 的声明看readonly参数的值是不是false再打开conf/context.xml或应用的META-INF/context.xml看有没有配置Manager和FileStore以及dir属性指向哪里。这步是判断漏洞能否被利用的关键只看版本是不够的。第三步查日志。这一步主要是确认有没有已经被探测的痕迹结合下面的日志观察点来做。3.2 Access Log 里的蛛丝马迹Tomcat 的访问日志默认位于logs/目录下文件名一般形如localhost_access_log.2025-03-*.txt。如果没有开启访问日志那么这一段对你可能就不适用不过也建议先确认下是不是真的没开。我排查时常用的两个过滤思路一是看有没有异常的 PUT 或 PATCH 请求尤其是带Content-Range头的二是看有没有对 JSP 文件、WEB-INF 目录、Session 存储路径的非常规访问。可以用类似下面的命令快速过滤grep -iE (PUT|PATCH) logs/localhost_access_log.*.txt | tail -100 grep -iE content-range logs/localhost_access_log.*.txt | tail -50看到日志里有少量零星的尝试可能是扫描器在探测如果频率很高、来源 IP 分散说明已经进入了自动化攻击阶段。这时候不仅要补丁还得考虑IP层面的封禁和更严格的访问控制。3.3 版本升级和补丁安装实操如果确认需要升级不要直接在生产环境上用安装包覆盖解压风险太大。我习惯的流程是这样的备份把整个 Tomcat 目录完整备份一份特别是conf/目录里的所有配置文件。如果条件允许最好在虚拟机或容器里做一个快照。下载新版本包从 Tomcat 官网或企业内部镜像源获取对应修复版本确保下载包的校验值正确。比对配置把旧版本的server.xml、web.xml、context.xml、setenv.sh等文件与新版默认配置做 diff把自定的内容迁移过去。灰度启动在预发环境或一台测试机器上启动新版本重点验证应用会话保持、静态资源访问、上传下载功能这几个受影响面。切换和回退确认没问题后把生产流量切过去同时保留旧版本目录至少观察一个业务周期确保没有隐藏问题再清理。升级过程中有一点容易踩坑新版 Tomcat 对最低 JDK 版本是有要求的比如较新的 11.0.x 通常需要 JDK 17 以上。如果生产环境还在用 Java 8硬升 Tomcat 可能启动都起不来这种时候要么选择分支内更高版本要么同步升级 JDK但要评估几套老应用的兼容性。不能不做兼容测试就直接上。4. 临时缓解措施与长期加固建议4.1 先把手动写权限关掉如果因为变更窗口、应用兼容性等原因暂时无法升级先把最关键的开关关上。操作上就是确认conf/web.xml里 DefaultServlet 的readonly参数为trueservlet servlet-namedefault/servlet-name servlet-classorg.apache.catalina.servlets.DefaultServlet/servlet-class init-param param-namedebug/param-name param-value0/param-value /init-param init-param param-namelistings/param-name param-valuefalse/param-value /init-param init-param param-namereadonly/param-name param-valuetrue/param-value /init-param load-on-startup1/load-on-startup /servlet注意几个细节如果应用自身的WEB-INF/web.xml里也声明了 DefaultServlet应用的配置会覆盖全局配置两边都要查readonly参数改完后必须重启 Tomcat 才生效如果业务确实需要支持文件写入不要简单地把readonly改回false更好的做法是用独立的 Servlet 处理上传并限定上传目录、文件类型和大小。4.2 Session 持久化能不开就不开要开就挪到隔离目录再看 Session 持久化。如果应用不需要重启后保持登录态直接不配置PersistentManager是最省心的。如果确实需要改造方式也很明确把FileStore的dir配置到 webapps 之外的目录比如/var/lib/tomcat-sessions并保证该目录只有 Tomcat 运行账户可读写。在conf/context.xml里类似这样的配置需要调整Manager classNameorg.apache.catalina.session.PersistentManager Store classNameorg.apache.catalina.session.FileStore directory/var/lib/tomcat-sessions / /Manager核心思路是把 Session 存储目录从攻击者能写入的 web 可访问目录中挪出去。同时建议给该目录设置权限为 700 或 750避免其他低权限账户读取到 Session 文件。更进一步的做法是在应用里实现序列化过滤但因为涉及业务代码改动一般留给长期计划来做。4.3 WAF、防火墙和边界控制升级之前可以在边界设备上做一层拦截。对 Tomcat 对外开放的端口用 WAF 或自研网关过滤包含Content-Range头的 PUT/PATCH 请求对管理后台、文件上传接口做来源 IP 限制不允许公网直接访问。从网络层面看Tomcat 服务本身不应该直接暴露到公网前面应该有一层反向代理或负载均衡代理层可以做 HTTP 方法白名单。如果业务只需要 GET 和 POST直接用配置把 PUT、DELETE、PATCH 全拦掉能挡住相当一部分漏洞利用尝试。日志监控也要跟上可以把刚才那两个 grep 命令变成定时脚本发现有异常就自动推送到告警群。不要只在漏洞爆发时看日志这类监控常态化之后成本很低但收益很高。4.4 长期加固清单临时措施只能扛一时长期来看还是要回到系统化加固。列一份我给自己维护的环境准备的清单基本都是常规但容易漏掉的内容建立 Tomcat 版本台账记录每个环境的版本号、补丁状态和最后升级时间。每次新漏洞公告发布后对照版本台账做一次影响面分析而不是等扫描器反应。收紧 DefaultServlet 的写权限业务需要时优先使用独立 Servlet 处理上传。统一 Session 持久化配置规范默认关闭确实需要开启则存储目录必须在 webapps 之外。关闭 Tomcat 的目录列表功能删除默认自带的管理端和示例应用。以低权限系统账户运行 Tomcat避免用 root 启动服务。定期从发行渠道同步安全公告包括系统自带 Tomcat 的仓库更新。对上传功能做内容校验不保留可执行文件扩展名上传后的文件名做随机化处理。这些条目大部分不依赖本次漏洞的临时修复而是日常基线的一部分。一次漏洞处理顺手把这些都补上后续同类问题出现时排查成本就会低很多。5. 常见问题与实操心得5.1 问题排查速查表这轮处理过程中群里讨论最多的几个问题我整理成了速查表方便照着做常见问题可能原因处理办法扫描报告显示受影响但版本不在列表内扫描器识别的是识别特征或HTTP头版本不一定准确以本机实际运行版本和官方公告为准人工复核补丁升级后应用启动失败JDK版本不兼容或配置迁移缺失检查JDK版本要求逐项比对server.xml、web.xml配置readonly改为true后上传功能报错业务真的依赖PUT写权限用独立上传接口替代限定目录和文件类型新镜像部署后发现还是旧版本镜像仓库未同步修复版本更新基础镜像并重新构建建立镜像版本校验流程日志里出现大量Content-Range请求已被扫描或试探在WAF层封禁来源IP检查是否有真实写入行为排查这个问题时最容易犯的错是只对照版本号不看配置。我见过有团队把版本升级完了但应用的web.xml里还是旧的readonlyfalse等于白升。所以自查环节一定要把“版本配置日志”三件事全部查完再下结论。5.2 我踩过和见过的几个坑最后分享几个实际案例给同行提个醒。第一个坑是“只升主版本”。以前有个项目排查别的漏洞时升级只看了主版本号是对的结果小版本还是旧的关键修复根本没打进去。Tomcat 的修复版本往往在小版本里比如 9.0.99 到 9.0.100 这种跳号一不小心就看漏。建议把版本台账精确到主.次.修订三个数字都要记录。第二个坑是“改配置没重启”。有次在测试环境调readonly改完文件没重启当时测试请求还能写进去误以为配置没生效折腾了半天才发现是没重启。Tomcat 的很多配置在启动时一次性加载不是改了就立即生效。同理重启后一定要确认进程启动时间。第三个坑是“只靠WAF不升级”。有团队觉得加了拦截规则就等于处理完漏洞了结果几个月后换了新环境WAF规则没同步旧版本照旧跑又被扫描器揪出来。WAF 是缓解手段版本升级才是根治手段两者不能互相替代。第四个坑是“镜像仓库没更新”。开发环境升级到修复版本了但CI流水线里的基础镜像还是旧的每次新应用部署都会把漏洞环境再造出来。这提醒我基础镜像的版本管理必须纳入安全审查范围不能只在某一台机器上修。我在处理这类漏洞时的一个体会是漏洞情报出来后第一时间影响面评估永远是第一位版本、配置、暴露面三条线同时查。只要平时把资产清单和版本台账维护好几分钟就能出结论没维护好就只能一台台登服务器非常痛苦。这轮排查完之后建议顺手把本次的处理过程沉淀成一份内部排查文档下个类似漏洞出来照着走就行。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑