Tomcat漏洞修复升级——被遗忘的中间件安全

Tomcat漏洞修复升级------被遗忘的中间件安全

安全通告来了

等保测评报告下发。

高危漏洞:Tomcat 多个漏洞,包括:

  • CVE-2024-XXXX:Tomcat 信息泄露
  • CVE-2024-YYYY:Tomcat 请求走私
  • 总计:45个漏洞需要修复

修复方案:从 Tomcat 8 升级到 Tomcat 9.0。

听起来很简单?但我们在政务系统上跑了6年的 Tomcat 8,上面挂了 30+ 个应用,直接升级?

没那么简单。

第一次升级

目标

Tomcat 8.5 → Tomcat 9.0.x

问题1:过滤器不兼容

复制代码
严重: Exception starting filter [encodingFilter]
java.lang.AbstractMethodError

原因:Tomcat 9 重构了 Filter 接口,旧版过滤器不兼容。

解决 :重写自定义过滤器,不再继承旧版 BaseFilter,直接实现 javax.servlet.Filter 接口。

java 复制代码
// 旧代码(Tomcat 8)
public class EncodingFilter extends BaseFilter {
    public void doFilter(ServletRequest req, ServletResponse res, 
                         FilterChain chain) {
        req.setCharacterEncoding("UTF-8");
        chain.doFilter(req, res);
    }
}

// 新代码(Tomcat 9)  
public class EncodingFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res,
                         FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding("UTF-8");
        chain.doFilter(req, res);
    }
}

问题2:server.xml 配置变更

Tomcat 9 废弃了部分配置项:

xml 复制代码
<!-- Tomcat 8 旧配置 -->
<Connector port="8080" protocol="HTTP/1.1"
           URIEncoding="UTF-8"
           compression="on"
           compressableMimeType="text/html,text/xml,text/plain" />
           
<!-- Tomcat 9 新配置 -->           
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           URIEncoding="UTF-8"
           compression="on"
           compressibleMimeType="text/html,text/xml,text/plain" />

注意compressableMimeType 改成了 compressibleMimeType(拼写修正)。

问题3:TLS 协议变更

Tomcat 9 默认禁用 TLS 1.0/1.1,只启用 TLS 1.2/1.3。

但我们的旧客户端只支持 TLS 1.0。

xml 复制代码
<!-- 兼容旧客户端 -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           SSLEnabled="true"
           sslProtocols="TLSv1.2,TLSv1.1,TLSv1"
           ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,...">

教训:安全升级不能一刀切,需要考虑生态兼容性。

第二次升级

背景

漏洞扫描又来了,这次报了 45个漏洞

目标:Tomcat 8.5 → Tomcat 9.0.x(再次尝试)

新问题:编码问题

复制代码
tomcat9 编码问题

现象:页面中文乱码。

排查

  1. 检查 URI 编码:URIEncoding="UTF-8" 已配置
  2. 检查请求体编码:request.setCharacterEncoding("UTF-8") 已调用
  3. 检查 Tomcat 9 默认编码:Tomcat 9 默认使用 UTF-8,但旧应用使用 ISO-8859-1

根因 :Tomcat 8 默认 URI 编码是 ISO-8859-1,Tomcat 9 改成了 UTF-8

java 复制代码
// Tomcat 8 行为
request.getParameter("name")  // 如果传的是中文,可能乱码

// Tomcat 9 行为  
request.getParameter("name")  // 默认 UTF-8 解码

解决 :显式配置 URIEncoding="UTF-8",并排查所有应用层编码处理。

降级

回滚记录

复制代码
tomcat9有内容不兼容,降级到tomcat7.99

原因:某个第三方组件只在 Tomcat 8 上验证过,Tomcat 9 上出现类加载器问题。

复制代码
java.lang.NoClassDefFoundError: javax/ws/rs/ext/MessageBodyReader

根因:Tomcat 9 使用新的模块化类加载器,旧组件的 META-INF/services 机制失效。

决策:降级到 Tomcat 8.5(即日志中的 "7.99",实际是 8.5)。

经验:中间件升级要考虑全链路兼容性,特别是第三方闭源组件。

第三次修复

最新记录

复制代码
tomcat安全漏洞整改

这次换了个策略------不升级大版本,只打补丁

补丁方案------详细操作步骤

第一步:确认当前版本

bash 复制代码
${CATALINA_HOME}/bin/version.sh
# 确认当前为 Tomcat 8.5.xx

第二步:下载当前大版本的最新patch

去 Tomcat 官网下载当前 8.5.x 的最新版本:

bash 复制代码
wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.100/bin/apache-tomcat-8.5.100.tar.gz

第三步:只替换二进制文件,不动应用

bash 复制代码
# 停止Tomcat
${CATALINA_HOME}/bin/shutdown.sh

# 备份(全量备份保底)
cp -r ${CATALINA_HOME} ${CATALINA_HOME}_bak_$(date +%Y%m%d)

# 只替换bin、lib目录,不动webapps、conf、logs
cp -r apache-tomcat-8.5.100/bin/* ${CATALINA_HOME}/bin/
cp -r apache-tomcat-8.5.100/lib/* ${CATALINA_HOME}/lib/

# 启动
${CATALINA_HOME}/bin/startup.sh

webapps 目录不动(里面是应用),conf 里的 server.xmlweb.xml 等尽量保留原有配置。

第四步:安全加固配置

版本升级只是第一步,配置加固同样重要:

4.1 关闭 AJP 连接器(AJP 是漏洞重灾区,如 CVE-2020-1938 "Ghostcat"):

xml 复制代码
<!-- conf/server.xml ------ 注释掉AJP -->
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->

<!-- 隐藏版本号 -->
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="UTF-8"
           server="Apache"  />

4.2 删除默认应用(防止暴露版本信息和后台入口):

bash 复制代码
rm -rf ${CATALINA_HOME}/webapps/docs
rm -rf ${CATALINA_HOME}/webapps/examples
rm -rf ${CATALINA_HOME}/webapps/manager
rm -rf ${CATALINA_HOME}/webapps/host-manager

4.3 安全响应头(conf/web.xml 或应用 Filter):

xml 复制代码
<filter>
    <filter-name>HttpHeaderSecurityFilter</filter-name>
    <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>xssProtectionEnabled</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>antiClickJackingEnabled</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>blockContentTypeSniffingEnabled</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

4.4 禁用目录列表 (conf/web.xml,listings 设为 false

4.5 限制 HTTP 方法(只允许 GET/POST,禁止 PUT、DELETE、TRACE、OPTIONS):

xml 复制代码
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Restricted Methods</web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>TRACE</http-method>
        <http-method>OPTIONS</http-method>
    </web-resource-collection>
    <auth-constraint />
</security-constraint>

第五步:验证

bash 复制代码
# AJP是否关闭
netstat -tlnp | grep 8009  # 应该无输出

# 版本号是否隐藏
curl -I http://localhost:8080/

# 目录列表是否禁用
curl http://localhost:8080/some-nonexistent-path/  # 应返回403/404

# 漏洞扫描
# 用安全扫描工具(Nessus/OpenVAS)重新扫描确认漏洞已修复

性能综合评估:patch版本升级后,启动时间、内存占用、响应时间、并发能力均无明显变化------patch版本本质上只改了 bug 修复,不影响性能。

升级版本 vs 安全加固效果对比

措施 解决的问题 效果
升级到最新patch 修复已知CVE 覆盖大量历史漏洞
关闭AJP AJP协议漏洞 消除最危险的攻击面
隐藏版本号 信息泄露 增加攻击难度
删除默认应用 信息泄露、管理入口暴露 减少攻击面
安全响应头 XSS、点击劫持 防御常见Web攻击
禁用目录列表 敏感文件暴露 防止源码/配置泄露
限制HTTP方法 不安全方法 减少攻击向量

为什么最终选择打补丁而不是升级?

方式 升级大版本 打补丁
风险 高(API不兼容) 低(接口不变)
时间 2-3天(含回归测试) 2-3小时
效果 彻底修复 临时修复
长期维护 差(后续还有漏洞)

现实选择:业务不能停,只能选低风险方案。

线程限制问题

除了漏洞,Tomcat 还有性能相关的问题:

Tomcat 最大线程限制

复制代码
人脸识别离线版本测试及压力测试、接口定义、tomcat最大线程限制

场景:人脸认证服务部署在 Tomcat 上,并发认证时响应变慢。

排查:Tomcat 默认最大线程数 200,活体检测算法处理慢(300ms/次),当并发超过 200 时,请求排队。

优化

xml 复制代码
<Connector port="8080" protocol="HTTP/1.1"
           maxThreads="500"
           acceptCount="100"
           maxConnections="1000"
           connectionTimeout="30000" />

教训:中间件默认配置是按通用场景设计的,特定业务需要针对性调优。

升级操作手册

1. 准备工作

bash 复制代码
# 1. 备份当前配置
cp -r $CATALINA_HOME/conf $BACKUP_DIR/tomcat-conf-$(date +%Y%m%d)
cp -r $CATALINA_HOME/webapps $BACKUP_DIR/tomcat-webapps-$(date +%Y%m%d)
cp -r $CATALINA_HOME/lib $BACKUP_DIR/tomcat-lib-$(date +%Y%m%d)

# 2. 记录当前版本
$CATALINA_HOME/bin/version.sh

# 3. 导出所有配置项
$CATALINA_HOME/bin/catalina.sh configtest 2>&1

2. 配置文件迁移清单

yaml 复制代码
# Tomcat 升级配置迁移清单
files_to_migrate:
  - conf/server.xml
  - conf/web.xml
  - conf/context.xml
  - conf/catalina.properties
  - conf/logging.properties
  - bin/setenv.sh (自定义JVM参数)
  
check_items:
  - 自定义阀门(Valve)兼容性
  - JNDI数据源配置
  - Realm配置
  - 连接器(Connector)配置
  - 类库冲突检查

3. 应用兼容性检查清单

yaml 复制代码
app_compatibility:
  servlet_api: 3.1 → 4.0
  jsp_api: 2.3 → 2.4
  el_api: 3.0 → 4.0
  websocket_api: 1.1 → 2.0
  
breaking_changes:
  - javax.servlet → jakarta.servlet (Tomcat 10+)
  - 默认URI编码变更
  - 类加载器行为变更
  - JSP编译方式变更

4. 回滚方案

yaml 复制代码
rollback_plan:
  condition: "任一应用出现兼容性问题"
  steps:
    1. 停止Tomcat服务
    2. 恢复备份的conf目录
    3. 恢复备份的webapps目录
    4. 恢复备份的lib目录
    5. 启动旧版本Tomcat
    6. 验证所有应用正常
  rollback_time: < 30分钟

漏洞修复清单

漏洞数 修复方式 耗时 结果
10+ 升级到9.0 3天 部分应用兼容性问题
45 升级到9.0 2天 编码问题,需修复
- 降级到8.5 1天 第三方组件不兼容
若干 打补丁 3小时 完成修复

经验教训

1. 中间件升级要"慢"

  • 不要跳版本:8 → 9,中间最好验证 8.5 最新补丁版
  • 不要全量:先升级一个非核心应用试水
  • 不要限期:留够回归测试时间

2. 兼容性测试要"全"

需要测试的方面:

  1. 所有应用:30+个应用逐个验证
  2. 所有功能:登录、查询、导出、打印
  3. 所有第三方:报表引擎、工作流引擎、消息中间件
  4. 所有客户端:浏览器版本、操作系统、手机型号

3. 漏洞修复要"快"

  • 等保要求:高危漏洞 7天内 修复
  • 中危漏洞:30天内 修复
  • 低危漏洞:90天内 修复

4. 架构优化要"远"

长期来看,更好的方案是:

yaml 复制代码
long_term_plan:
  # 方案1:使用嵌入式Tomcat(Spring Boot)
  - 应用自带Tomcat,独立升级
  - 每个应用互不影响
  
  # 方案2:使用Nginx反向代理 + 多版本Tomcat
  - Nginx统一入口
  - 不同应用使用不同Tomcat版本
  
  # 方案3:迁移到云原生
  - 容器化部署
  - 中间件独立升级
  - 蓝绿发布

最后的话

Tomcat 就像家里的水管------平时没人关注,但一旦漏水,整个房子都要遭殃。

Tomcat 升级的三大悖论

  1. 安全悖论:越早升级越安全,但越早升级兼容性越差
  2. 维护悖论:越老的版本漏洞越多,但越老的版本越稳定
  3. 管理悖论:漏洞修复要求快,但政务系统变更要求慢

最终建议

  • 生产环境:大版本不动,只打安全补丁
  • 测试环境:逐步验证新版本
  • 新项目:直接用 Spring Boot 嵌入式 Tomcat
  • 旧项目:等系统重构时一并升级
相关推荐
xian_wwq1 小时前
【学习笔记】探讨大模型应用安全建设系列——顶层规划:如何推动公司级大模型安全建设-1
笔记·学习·安全·ai
闵孚龙1 小时前
Claude Code 权限系统全解析:AI Agent 安全治理、权限模式、规则匹配、沙箱防护与企业落地实战
人工智能·安全
枫叶丹41 小时前
【HarmonyOS 6.0】Device Security Kit安全审计阻断功能深度解析
开发语言·安全·华为·harmonyos
JiaWen技术圈2 小时前
Web 安全防护 介绍
运维·nginx·安全
Paranoid-up2 小时前
安全启动和安全固件更新(SBSFU)12: 调试 / 移植
安全·iap·安全启动·安全升级·sbsfu
@insist1232 小时前
信息安全工程师-操作系统安全通用基础与七大核心机制
安全·软考·信息安全工程师·软件水平考试
闵孚龙2 小时前
AI Agent 提示注入防御全解析:Unicode 清洗、MCP 安全、Claude Code 权限治理与纵深防御
人工智能·安全
蚰蜒螟2 小时前
深入剖析 OpenJDK 17 解释器中的安全点(Safepoint)进入与退出机制
java·开发语言·安全
txg6662 小时前
网络安全领域简报(2026年5月9日—5月16日)
安全·web安全