CISA 在 8 月 4 日把 CVE-2026-34486 加进了 KEV 名单,整改期限只给到 8 月 7 日——三天。这类公告的格式一般是"某组件某洞已在野利用",但这一个的 Apache 原文里有一句话,读起来方向完全相反:
An error in the fix for CVE-2026-29146 allowed the EncryptInterceptor to be bypassed.
翻译成人话:上一个洞的补丁,把加密拦截器修成了摆设。 当年 4 月 9 日这两个 CVE 是一起公开的,29146 是那个被修的,"修出问题"的是 34486,CVSS 7.5,Apache 自己标 Important。
补丁只挪了一行,方向就反了
10.1 分支的修复提交(55f3eb91,作者 Mark Thomas)标题写得很克制:Better error handling - partial revert of 607ebc0。改动只有一行——把一句调用从 catch 外面挪进了 try 里面:
public void messageReceived(ChannelMessage msg) {
try {
...解密...
super.messageReceived(msg); // 修好之后:解密成功才往下传
} catch (GeneralSecurityException gse) {
log.error(sm.getString("encryptInterceptor.decrypt.failed"), gse);
}
}带洞的那一版是反过来的:
try {
...解密...
} catch (GeneralSecurityException gse) {
log.error(...); // 只记一条日志
}
super.messageReceived(msg); // 然后消息照旧往下走,明文结果就是:任何一条解不开的集群消息,记一条 error,然后原封不动交给下一个拦截器,最后进到 channel 里。加密这个动作从"必须通过"降级成了"能过就过,不能过也过"。
上一个洞(CVE-2026-29146)是 EncryptInterceptor 默认用 CBC、天生吃 padding oracle。2 月 22 日有人报,要修;11.0.19 的发布投票还没过,所以能下载到的第一个带修复的版本就是 11.0.20(3 月 20 日)。也就是说,这个 fail-open 只存在于 11.0.20 / 10.1.53 / 9.0.116 这三个点版本里——专门为安全升级而升上去的人,正好落在这上面。
绕过的不是加密,是门禁
Tribes 是 Tomcat 自带的集群通信组件,成员之间传的是 Java 序列化的消息。EncryptInterceptor 的定位不是"集群鉴权",而是"集群消息加密"——顺手把陌生人塞进来的序列化字节挡在门外。
把这一层变成 fail-open,效果不是"攻击者看到密文",而是:集群端口上任何一条明文构造的序列化消息,都能被成员节点当成正常集群消息反序列化。 KEV 那条记录里直接写了它可以和 CVE-2025-24813 串起来用。
有人在真打,分工还写得很清楚
Unit 42 在 7 月 30 日发过一份报告,讲一个说中文的攻击者(别名 knaithe / KnYuan):用 DeepSeek 挂 Hermes Agent 框架当"自主操作员",自己上 FOFA 找目标、按攻击面排序、去 GitHub 扫热门 PoC,再用 Telegram 下指令。报告里点了 7 个 CVE,前后试了 460 多个目标。
Tomcat 这条在报告里不属于自主那条线,而是在 "Manual Campaigns" 一节。原文一句话:"Java deserialization reverse shell attempts against nine Apache Tomcat servers (CVE-2026-34486)";表 2 里这一行的执行方式标的是 Manual。
这个细节比"AI 自己打进来了"值钱:AI 负责找,人负责打。 扫目标、筛版本、下 PoC 这一层已经压到几分钟;最后那一下反序列化反弹 shell,还是人连着打的。也就是说,AI 把"哪些机器值得手动打"这份清单做得非常便宜了——你被扫到、被挑中的概率变了,攻击手法一个没变。
影响面窄,但窄得很扎心
- 只有三个点版本:11.0.20、10.1.53、9.0.116。不是区间,只有它们带着那个半截补丁。
- 前提是开了 Cluster/Tribes。
server.xml里没有<Cluster>的单机实例不受影响,这点得说清楚,别一看 Tomcat 就全员加班。 - 8.5 分支早 EOL 了,不在这次名单里——但它连 29146 的修复版本都没进(官方修复列表里没有 8.5),等于 padding oracle 那个洞一直挂着。还在 8.5 上的,该安排挪了。
真正难受的是第三层:开了集群、又按官方推荐加了 EncryptInterceptor 的,恰好是最把集群端口当"不可信网络"的那批运维。他们升得最快,踩得最准。
自查四条
# 1. 版本号(命中这三个点版本,就是"现在就处理"级别)
$CATALINA_HOME/bin/version.sh | grep -i "Server version"
# 2. 有没有开集群、加没加加密拦截器
grep -nE "<Cluster|<Interceptor|EncryptInterceptor" $CATALINA_HOME/conf/server.xml
# 3. 集群端口在不在听(Tribes 默认 4000)
ss -tlnp | grep 4000
# 4. 从非集群成员的机器探一下
nc -zv <本机IP> 4000第 4 条才是判级依据:4000 只对集群成员开放、外面探不通,风险就落到"能升就升";如果是 0.0.0.0:4000 且公网可达,今天就得动,因为绕过之后直接接的是反序列化。
怎么修
升级,重启。修复版本:
| 分支 | 修复版本 | 发布 |
|---|---|---|
| 11.0 | 11.0.21 | 2026-04-04 |
| 10.1 | 10.1.54 | 2026-04-02 |
| 9.0 | 9.0.117 | 2026-04-03 |
但别停在这三个号上。同一块 EncryptInterceptor 后面还出了两个:CVE-2026-55955(文档说有重放保护,实际没有,11.0.23 修)、CVE-2026-59084("安全配置要求文档写不清楚",11.0.24 修)。后一个是 Low,但它说明了一件事——这个拦截器配错了不会报错。所以直接升到本分支最新版更省心。
一时动不了集群的,先做减法:
- 4000 只放集群成员 IP(安全组 / iptables),用上面第 4 条从非成员机验证,结果应该是 timeout。
- 不需要会话复制的应用,把
<Cluster>整段去掉——省下的不只是 CPU。 - 别把 EncryptInterceptor 当边界。它管的是集群消息加密,不管端口鉴权;官方 7 月专门发了个 CVE 说这块文档写得不清楚,说的就是同一个误解。
值得记一笔的东西
这个 CVE 本身没什么新鲜的:三个点版本、七个月前就修完了。它值得记的是来历——修安全漏洞的补丁,自己开了一个洞。
上一个洞的修法("解密失败别让节点挂掉")出发点是对的。问题出在"消息继续往下传"这一步放在了异常处理的保护范围之外:降级路径没有人测,fail-closed 就悄悄变成了 fail-open。
同类的事今年不是第一次:GitLab 那个满分洞,也是补丁打完洞还在;再往前,Ivanti 那三个洞是串起来用的,中间一环同样是"防护组件没按预期失败"。看一个补丁,除了确认"修没修上",还得看"修不上的时候它会怎么退"。
评论