补丁修了个寂寞:Apache Tomcat CVE-2026-34486漏洞完整复盘
2026年4月14日,Apache软件基金会发布了紧急安全公告,修复了Apache Tomcat中的一个高危漏洞。公告本身并无异常—— Tomcat作为最流行的Java应用服务器,月度安全更新本属常态。但这次修补的漏洞有些特殊:它并不是一个新发现的缺陷。
官方在修复CVE-2026-29146时,顺手引入了这个编号为CVE-2026-34486的新漏洞。安全修漏洞的过程中居然”按下葫芦浮起瓢”,这在业界并不常见。
故事要从头说起。
第一次修复:CVE-2026-29146
2026年1月,安全研究人员Uri Katz和Avi Lumelsky(来自Oligo Security公司)发现了一个令人不安的问题:Apache Tomcat的集群通信组件Tribes在启用加密时,默认使用了不安全的加密模式。
Apache Tomcat的Tribes框架用于在多节点集群中同步会话数据。默认监听TCP端口4000。企业部署Tomcat集群时,通常用Tribes在多台服务器之间同步HTTP会话、复制缓存数据。Tribes支持启用EncryptInterceptor,对集群间通信进行AES加密。
问题在于,EncryptInterceptor默认使用了CBC模式(AES-CBC)。这种模式存在一个经典缺陷——填充预言机攻击(Padding Oracle Attack)。攻击者可以拦截加密流量,通过观察服务器对不同填充格式的响应,逐步解密通信内容,甚至伪造消息。
这个消息很快得到了Apache官方的重视。2026年2月,官方发布了CVE-2026-29146的修复补丁,将EncryptInterceptor的默认配置从CBC改为GCM模式——后者对填充预言机攻击免疫。管理员需要升级到以下版本:
- Tomcat 11.0.21
- Tomcat 10.1.54
- Tomcat 9.0.117
从数字看,这只是一次常规的版本迭代。但问题就在这时埋下了。
回归漏洞:CVE-2026-34486
2026年3月,波兰安全公司striga.ai的研究员Bartlomiej Dmitruk在测试新补丁时发现了异常——即使服务器已经升级到修补后的版本,EncryptInterceptor的绕过仍然有效。
这不是配置问题,不是0day残留,而是新补丁引入的全新缺陷。
原来,CVE-2026-29146的修复涉及对EncryptInterceptor代码的改动。具体来说,修改了消息解密失败时的处理逻辑。原始代码的逻辑是:解密成功,传递解密后的消息;解密失败,静默丢弃消息。
修复后的代码变成了这样:
// EncryptInterceptor.java — 有缺陷的版本
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// 处理解密后的消息...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // 只记录错误日志
}
super.messageReceived(msg); // ← 问题:无论解密成功与否,都继续传递原始消息
}
这段代码的问题在于:catch块只记录了错误日志,但super.messageReceived(msg)调用在try-catch块之外执行。这意味着即使解密失败(抛出异常),未经处理的原始消息字节仍会被传递给下游的反序列化模块。
Tribes使用Java的XByteBuffer进行消息序列化。当消息传递给GroupChannel时,会调用ObjectInputStream.readObject()进行反序列化。攻击者只需要构造一个恶意序列化payload,发送到Tribes的4000端口,即可触发反序列化漏洞。
这是一个经典的”认证绕过+反序列化RCE”组合。攻击者不需要任何凭据,只需要能访问Tomcat的4000端口。
漏洞利用
漏洞的利用并不复杂。GitHub上已经有安全研究者公开了漏洞利用工具(404-src/CVE-2026-34486)。
攻击流程如下:
- 使用ysoserial生成CommonsCollections6链的序列化payload
- 将payload封装为Tribes协议帧
- 发送到目标的4000端口
- 服务器解密失败,继续传递原始数据
- 反序列化触发,执行任意命令
工具的使用非常简单:
python3 exp.py -t target-ip -p 4000 --rce "id"
# 输出: uid=0(root) gid=0(root) groups=0(root)
甚至可以获取交互式shell:
python3 exp.py -t target-ip -p 4000 --shell
唯一的攻击痕迹是日志中的一行错误:
SEVERE [Tribes-Task-Receiver[Catalina-Channel]-1]
org.apache.catalina.tribes.group.interceptors.EncryptInterceptor.messageReceived
Failed to decrypt message
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16
但这条日志通常被淹没在大量业务日志中,很难引起注意。
影响范围
受影响的版本包括:
- Apache Tomcat 11.0.0.M1 至 11.0.20
- Apache Tomcat 10.1.0.M1 至 10.1.53
- Apache Tomcat 9.0.0.M1 至 9.0.116
需要运行Tomcat集群且启用了EncryptInterceptor的组织需要立即升级。根据官方公告,受影响的主要是使用了Tomcat集群功能的企业——通常是中大型Java应用的部署场景。
除了CVE-2026-34486,官方同时修复了另一个”中等”严重程度的漏洞CVE-2026-34500,影响OCSP(在线证书状态协议)验证功能。该漏洞同样由早稻田大学的研究员Haruki Oyama发现。
写在最后
这是一次典型的” regression bug”——修复过程中引入的新漏洞。
安全漏洞的代码修复往往涉及多层逻辑改动。在修复CVE-2026-29146时,开发人员可能只是想”至少记录解密失败的消息”,却没有意识到这个看似无害的改动会将未经验证的数据引入反序列化链。
这种”善意”的改动酿成大祸,在安全历史上并非孤例。2014年OpenSSL的Heartbleed漏洞同样源于一个看似无害的特性——心跳扩展。
讽刺的是,即使这次回归漏洞被修复,Tribes模块的安全性问题仍然存在。加密模块被绕过后的反序列化链仍然畅通。企业需要重新审视是否应该依赖Tomcat自带的集群加密,还是引入更强的网络层安全方案。
参考资料