Tomcat 安全加固是 Java Web 应用上线前必须完成的环节:Tomcat 长期占据 Web 中间件攻击面榜首,默认配置下的管理后台、AJP 端口与反序列化组件一旦暴露,攻击者即可直接获取服务器权限。本文从部署规范、连接器配置、反序列化防护三个层面给出可复制的加固方案。
适用场景
以下场景直接适用本方案:
- 自建或云主机上部署的 Tomcat 8.5 / 9 / 10 生产实例
- 通过 Nginx 反向代理对外提供 HTTP 服务的 Java Web 应用
- 等保测评或安全验收前需要完成中间件基线加固
- 曾出现反序列化攻击告警、需要紧急封堵的应用
前置条件
- 具备 Tomcat 所在服务器的 root 或 sudo 权限
- Tomcat 已配置
CATALINA_HOME环境变量(本教程默认/opt/tomcat) - 应用当前可正常访问,方便加固后回归验证
原理说明
Tomcat 的风险点集中在三处:
- 管理后台:默认启用的 manager / host-manager 应用若未加访问控制,攻击者可爆破默认账号(tomcat/tomcat、admin/admin),登录后上传 WAR 包即等于拿下服务器。
- AJP 协议:8009 端口走 AJP 二进制协议,历史上 Ghostcat(CVE-2020-1938)可通过该端口读取任意文件甚至执行命令。当前多数业务已不需要 AJP。
- 反序列化:若应用依赖含
ObjectInputStream的组件(如老版本 Commons-Collections 3.x),攻击者构造恶意序列化数据即可触发 RCE,典型如 CVE-2017-12617 的 PUT 方法写文件链。
操作步骤
1. 最小化安装与权限隔离
# 以非 root 专用用户运行,禁止使用 tomcat 目录属主为 root
useradd -r -s /sbin/nologin -d /opt/tomcat tomcat
chown -R tomcat:tomcat /opt/tomcat
# 删除默认文档与示例应用,缩小攻击面
rm -rf /opt/tomcat/webapps/examples /opt/tomcat/webapps/docs /opt/tomcat/webapps/ROOT
# 移除管理后台应用(如确需保留,参见步骤 2 单独加固)
rm -rf /opt/tomcat/webapps/manager /opt/tomcat/webapps/host-manager
2. 管理后台强访问控制
若必须保留 manager,先修改 conf/tomcat-users.xml 使用强口令,再在 conf/server.xml 中为管理应用单独加 Valve 访问限制:
<Context path="/manager" privileged="true">
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="192.168.1.0/24|127.0.0.1"
denyStatus="403"/>
</Context>
同时建议将管理端口与应用端口分离,仅内网可访问。
3. 禁用 AJP 并收紧连接器
# 注释或删除 conf/server.xml 中 8009 端口监听
<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/> -->
# 仅保留 HTTP/1.1 连接器,并加上请求限制
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="200" acceptCount="100"
connectionTimeout="20000"
maxHttpHeaderSize="8192"
server="None"/>
关键项说明:server=”None” 隐藏版本号;maxHttpHeaderSize 限制请求头大小,防头注入;maxThreads / acceptCount 控制并发,防资源耗尽。
4. 反序列化漏洞防护
反序列化 RCE 的根因多数是 不安全的第三方依赖,按优先级处理:
# 1) 升级至已修复版本:8.5.100+ / 9.0.99+ / 10.1.31+(含 CVE-2026-34486 修复)
cd /opt/tomcat/bin && ./version.sh | grep "Server version"
# 2) 扫描并升级高风险依赖(重点检查 commons-collections 3.2.1 及以下版本)
grep -R "commons-collections" /opt/tomcat/lib /your-app/WEB-INF/lib
# 3) 全局禁用 PUT/DELETE 写文件通道(CVE-2017-12617 修复项)
# 在 conf/web.xml 中为 DefaultServlet 增加:
<init-param>
<param-name>readonly</param-name>
<param-value>true</param-value>
</init-param>
5. Nginx 前置防护
# 仅暴露 80/443,8080 与 8009 不对外
server {
listen 443 ssl;
server_name app.example.com;
# 拦截常见扫描路径
location ~* ^/(manager|host-manager|WEB-INF) {
deny all;
return 403;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
配置验证
# 验证 8009 已关闭
ss -tlnp | grep 8009 # 应无输出
# 验证后台被外部拒绝
curl -s -o /dev/null -w "%{http_code}
" http://your-ip:8080/manager/html # 403
# 验证版本信息已隐藏
curl -sI http://your-ip:8080/ | grep -i server # 应为 Server: None
# 验证反序列化依赖已修复
java -jar ysoserial.jar CommonsCollections1 "id" | base64 | head -c 50 | grep -q . && echo "依赖审计请用 OWASP Dependency-Check 复检"
常见问题(FAQ)
Q1:禁用 AJP 后应用报错无法访问?
现代 Spring Boot 内嵌 Tomcat 与纯 HTTP 反代场景都不依赖 AJP。若确有内部模块走 AJP,可保留但必须:绑定 127.0.0.1(address="127.0.0.1")、升级至修复版本、限制 secretRequired 并配置共享密钥。
Q2:升级 Tomcat 版本会影响现有应用吗?
小版本升级(如 8.5.x → 8.5.y)通常兼容,但跨大版本(9 → 10)因 Jakarta EE 命名空间变更(javax.* → jakarta.*)可能不兼容,需先在测试环境验证。反序列化漏洞修复优先升级依赖包而非整体升级。
Q3:如何快速发现已存在的后门 WAR?
对比 webapps 目录文件时间戳与部署记录,重点检查近期新增的 .war 文件;用 unzip -l xxx.war 查看是否含 shell.jsp、cmd.jsp 等可疑文件,并检查 catalina.out 中的异常部署日志。
总结
Tomcat 安全加固的核心是「默认最小、显式收紧」:删除非必要应用、隔离管理入口、关闭 AJP、升级反序列化依赖,再叠加 Nginx 前置过滤。完成以上五步后,Tomcat 的主要高危入口均已封堵。建议将本清单纳入 CI 发布流程,每次发版自动执行安全基线检查。