1. 问题背景与危害分析
在Web应用安全领域,中间件版本信息泄露是一个看似微小却可能引发连锁反应的安全隐患。以Tomcat为例,默认配置下会在HTTP响应头、错误页面等位置暴露详细的版本信息(如Apache Tomcat/9.0.54)。这种信息泄露相当于在战场上主动向敌人展示自己的武器型号和弱点手册。
我曾参与过某金融系统的渗透测试,通过Shodan搜索引擎批量扫描暴露在公网的Tomcat服务,发现超过60%的实例存在版本信息泄露问题。攻击者获取版本信息后,通常会执行以下攻击链:
- 查询该版本的历史漏洞(如CVE-2020-1938 Ghostcat文件读取漏洞)
- 针对性地测试已知漏洞利用方式
- 结合其他信息(如服务器操作系统版本)构建攻击载荷
2. 版本信息泄露的常见途径
2.1 HTTP响应头泄露
默认配置下,Tomcat会在HTTP响应头中添加Server: Apache-Coyote/1.1和X-Powered-By: Servlet/3.1 JSP/2.3 (Tomcat/9.0)等信息。通过简单的curl命令即可获取:
bash复制curl -I http://example.com
2.2 错误页面泄露
当触发404/500等错误时,Tomcat默认错误页面会显示详细版本信息。例如访问不存在的URL:
code复制HTTP Status 404 – Not Found
Type Status Report
Message /notexist
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Apache Tomcat/9.0.54
2.3 Manager应用默认页面
未删除的/manager/html应用在未授权访问时,登录页面会暴露Tomcat版本信息。
3. 解决方案与实操步骤
3.1 修改Server头信息
编辑conf/server.xml文件,在<Connector>标签中添加server属性:
xml复制<Connector port="8080" protocol="HTTP/1.1"
server="Unknown" />
注意:不要设置为空字符串,某些扫描工具会将其识别为特征值
3.2 移除X-Powered-By头
在conf/web.xml中增加以下配置:
xml复制<filter>
<filter-name>httpHeaderSecurity</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>antiClickJackingEnabled</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>httpHeaderSecurity</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.3 自定义错误页面
- 在
webapps/ROOT/WEB-INF/web.xml中添加:
xml复制<error-page>
<error-code>404</error-code>
<location>/error.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.html</location>
</error-page>
- 创建自定义错误页面
webapps/ROOT/error.html:
html复制<!DOCTYPE html>
<html>
<head>
<title>Error</title>
</head>
<body>
<h1>An error occurred</h1>
<p>Please contact administrator</p>
</body>
</html>
3.4 禁用Manager应用(生产环境建议)
- 删除
webapps/manager目录 - 注释掉
conf/tomcat-users.xml中的相关角色配置
4. 进阶防护措施
4.1 使用反向代理隐藏
在Nginx配置中添加:
nginx复制server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_hide_header X-Powered-By;
proxy_hide_header Server;
}
}
4.2 编译时修改版本信息
对于安全要求极高的场景,可以重新编译Tomcat:
- 修改
java/org/apache/catalina/util/ServerInfo.properties文件 - 修改
server.info和server.number属性值 - 重新打包部署
5. 验证与测试方法
5.1 使用curl验证
bash复制# 检查Server头
curl -I http://example.com | grep Server
# 检查错误页面
curl http://example.com/notexist
5.2 使用Nmap扫描
bash复制nmap -sV --script=http-headers example.com -p 80,443
5.3 使用Burp Suite检查
通过Burp Proxy拦截响应,检查所有HTTP头字段和错误响应内容。
6. 常见问题与解决方案
6.1 修改配置后不生效
- 检查是否修改了正确的
server.xml(注意CATALINA_HOME和CATALINA_BASE的区别) - 确认Tomcat已完全重启(有时需要杀进程)
- 检查是否有多个
<Connector>标签需要修改
6.2 自定义错误页面显示异常
- 确保
web.xml中<location>路径正确 - 检查文件权限(特别是从Windows复制到Linux时)
- 清除浏览器缓存测试
6.3 反向代理配置问题
- Nginx的
proxy_hide_header对某些HTTP版本可能无效 - 确保没有其他中间件(如CDN)重新添加了这些头
- 使用
tcpdump抓包确认真实响应
7. 安全加固建议清单
- 定期更新:保持Tomcat版本更新,即使隐藏了版本号,旧版本仍有被漏洞利用的风险
- 最小化安装:删除docs、examples等非必要应用
- 访问控制:限制
/manager应用的访问IP - 日志监控:对频繁访问错误页面的IP进行告警
- WAF防护:配置Web应用防火墙规则,拦截包含
/manager/html等路径的请求
在实际生产环境中,我建议采用分层防御策略:先通过修改配置隐藏版本信息,再结合反向代理和WAF提供多重保护。同时要建立定期检查机制,因为版本信息可能通过其他意想不到的途径泄露(如某些JSP应用自带的调试信息)。