CVE-2026-43515 — Apache Tomcat 多集合安全约束授权绕过¶
发布于 2026-06-06
CVSS 9.1 CRITICAL
未经身份验证的攻击者可以通过发送利用约束评估逻辑缺陷的特定 HTTP 方法请求,在不提供任何凭据的情况下获取 Apache Tomcat 服务器上受保护的资源。
| Project | Apache Tomcat |
| 受影响组件 | java/org/apache/catalina/realm/RealmBase.java 中的 RealmBase.findSecurityConstraints() |
| Severity | CRITICAL |
| CVSS | v3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (9.1) |
| CWE | CWE-285 |
| 受影响版本 | 11.0.0-M1 – 11.0.21, 10.1.0-M1 – 10.1.54, 9.0.0.M1 – 9.0.117, 8.5.0 – 8.5.100(EOL,无官方修复),7.0.0 – 7.0.109(EOL,无官方修复) |
| 修复版本 | 11.0.22, 10.1.55, 9.0.118 |
| 安全公告 | GHSA-5m62-pw8w-7w9f |
1. 漏洞概述¶
Apache Tomcat 是 Apache 软件基金会维护的 Java Servlet 容器。该漏洞允许未经身份验证的网络攻击者,通过发送约束评估逻辑会静默忽略的 HTTP 方法请求,读取受 web.xml 中 <security-constraint> 保护的资源。
受影响版本为 9.0.0.M1 至 9.0.117、10.1.0-M1 至 10.1.54 以及 11.0.0-M1 至 11.0.21。漏洞于 2026 年 5 月 12 日公开披露,修复版本为 9.0.118、10.1.55 和 11.0.22。
根本原因¶
该缺陷位于 java/org/apache/catalina/realm/RealmBase.java 中的 RealmBase.findSecurityConstraints() 方法。当 web.xml 中的一个 <security-constraint> 包含多个 URL 模式匹配请求 URI 的 <web-resource-collection> 时,Tomcat 本应依次检查每个集合声明的 HTTP 方法并返回所有适用的约束。但修复前的代码在集合循环外部声明了 boolean matched 标志和 int pos 索引变量。一旦第一个匹配的集合将 matched 设为 true 并在 pos 中记录其索引,后续迭代便无法再更新 pos,因为条件判断 !matched 已为假。循环结束后,方法只查询 collection[pos].findMethod(method),所有后续同样匹配 URL 模式的集合都不再被检查其方法列表。
存在缺陷的代码(节选):
// BEFORE (buggy) — boolean matched / int pos declared OUTSIDE the j-loop
boolean matched = false;
int pos = -1;
for (int j = 0; j < collection.length; j++) {
String[] patterns = collection[j].findPatterns();
// ... skips non-extension patterns ...
for (int k = 0; k < patterns.length && !matched; k++) {
// extension-pattern matching logic ...
if (pattern.regionMatches(1, uri, dot, uri.length() - dot)) {
matched = true;
pos = j; // records only the FIRST matching collection
}
}
}
// Evaluated only collection[pos]; all later matching collections ignored
if (matched) {
found = true;
if (collection[pos].findMethod(method)) {
if (results == null) { results = new ArrayList<>(); }
results.add(constraints[i]);
}
}
补丁差异(在 9.x、10.x 和 11.x 分支的提交中完全相同):
- boolean matched = false;
- int pos = -1;
for (int j = 0; j < collection.length; j++) {
String[] patterns = collection[j].findPatterns();
// ... skips non-extension patterns ...
+ boolean matched = false;
for (int k = 0; k < patterns.length && !matched; k++) {
String pattern = patterns[k];
if (pattern.startsWith("*.")) {
// extension-pattern matching logic
if (pattern.regionMatches(1, uri, dot, uri.length() - dot)) {
matched = true;
- pos = j;
}
}
}
- }
- if (matched) {
- found = true;
- if (collection[pos].findMethod(method)) {
- if (results == null) { results = new ArrayList<>(); }
- results.add(constraints[i]);
+ if (matched) {
+ found = true;
+ if (collection[j].findMethod(method)) {
+ if (results == null) { results = new ArrayList<>(); }
+ results.add(constraints[i]);
+ }
}
}
修复方案将 boolean matched 移至 j(集合)循环内部,使其在每次迭代开始时重置为 false,同时删除了 pos 变量,改为直接使用循环索引 j,并将方法检查逻辑移入同一循环,使每个匹配的集合都能与请求的 HTTP 方法独立对比。
2. 漏洞环境¶
复现环境使用两个官方 Apache Tomcat Docker 镜像,以同级容器形式运行在私有桥接网络上:tomcat:10.1.54-jre17(10.1.x 最后一个受影响版本)作为攻击目标,tomcat:10.1.55-jre17(10.1.x 第一个修复版本)作为对比服务器。Tomcat 二进制文件直接使用官方镜像,未做修改,仅叠加了一个受保护的 Web 应用、一个 Realm 用户文件和一个生成动态密钥的入口脚本。
| 服务 | 角色 | 镜像 | 端口 |
|---|---|---|---|
vulnerable |
攻击目标——Tomcat 10.1.54 | tomcat:10.1.54-jre17 |
127.0.0.1:8080 |
patched |
已修复对比服务器——Tomcat 10.1.55 | tomcat:10.1.55-jre17 |
127.0.0.1:8081 |
下载环境包(env.zip)或单独浏览文件: env/Dockerfile、env/docker-compose.yml。
启动环境:
确认漏洞版本正在运行:
# 预期输出: Server number: 10.1.54.0
docker exec cve-2026-43515-tomcat-vulnerable sh -c 'catalina.sh version 2>/dev/null | grep "Server number"'
# 预期输出: Server number: 10.1.55.0
docker exec cve-2026-43515-tomcat-patched sh -c 'catalina.sh version 2>/dev/null | grep "Server number"'
确认受保护资源真正受到认证保护(需要认证的 GET 请求被拒绝):
漏洞 Web 应用中的 web.xml 包含以下触发该漏洞的安全约束配置:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected GET</web-resource-name>
<url-pattern>*.html</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<web-resource-collection>
<web-resource-name>Protected POST</web-resource-name>
<url-pattern>*.html</url-pattern>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
两个集合共享 *.html URL 扩展名模式。GET 列在第一个集合中,POST 列在第二个集合中,整个约束均要求 <auth-constraint> 中的 admin 角色。在存在缺陷的代码中,Tomcat 评估 POST 请求时仅查询第一个集合,发现其中只列出了 GET 而非 POST,于是将 POST 视为不受约束,放行未经身份验证的请求。
受保护资源 /protected/secret.html 中的 CVE-2026-43515-FLAG-<uuid> 密钥由入口脚本(env/config/entrypoint.sh)在每次容器启动时生成。该值不在构建时写入,因此事先无法预知,可证明资源确实被读取,而非被猜测。
3. 利用方法¶
前提条件¶
- 按第 2 节所述启动环境。
- 确认两个容器均报告
healthy,且未经身份验证的GET请求对受保护资源返回401(确认认证门控是真实的)。
步骤¶
1. 运行漏洞利用脚本。
脚本(exploit/run.sh)发送三个请求:控制用的 GET 请求(确认资源受认证保护)、绕过授权的 POST 请求(漏洞利用)、以及对已修复服务器发送相同 POST 请求(确认其拒绝该请求):
下载完整的漏洞利用包:exploit.zip。
2. 观察输出结果。
在存在漏洞的服务器上,输出如下:
[CONTROL] GET对:8080→HTTP/1.1 401(资源确实受到认证保护)。[EXPLOIT] POST对:8080→HTTP/1.1 200,包含完整受保护页面内容,其中有一行SECRET: CVE-2026-43515-FLAG-<uuid>。[EXPLOIT] Disclosed secret部分打印该SECRET:行——即绕过请求返回的实际内容,不含任何硬编码值。[NEGATIVE] POST对已修复的:8081→HTTP/1.1 401(密钥被拒绝)。
3. 通过独立的特权通道验证泄露的密钥。
漏洞利用脚本打印的是服务器返回的任意内容。唯一可信的证明方式,是将其泄露的值与真实的当前密钥对比,而该密钥需通过完全独立于漏洞利用 HTTP 路径的通道读取:
入口脚本在启动 Tomcat 之前将本次启动的密钥写入 /seed/secret_value,该文件归 root 所有,权限为 0600。漏洞利用脚本无法访问该文件,只能读取 HTTP 响应内容。两个值一致,即证明绕过攻击确实读取了受保护的内容。
已验证运行的观测证据¶
复现证据如下:
- 漏洞服务器版本:
Server number: 10.1.54.0 - 已修复服务器版本:
Server number: 10.1.55.0 - 控制用 GET 对
:8080→401(响应体中无密钥) - 绕过 POST 对
:8080→200,响应体包含:SECRET: CVE-2026-43515-FLAG-4356b3e6-d0f3-4c45-9c6d-730333e5dc8a - 相同 POST 对已修复的
:8081→401 - 特权通道(真实当前密钥):
CVE-2026-43515-FLAG-4356b3e6-d0f3-4c45-9c6d-730333e5dc8a - 漏洞利用泄露值与特权通道值完全一致。
为确认密钥确实是每次启动生成的动态值而非构建时固定写入,本次运行记录了连续两次启动,验证密钥在两次启动之间发生了变化:
- 第 1 次启动密钥:
CVE-2026-43515-FLAG-a2def6ba-7c53-4839-90e0-04c2e441a3b5 - 第 2 次启动密钥:
CVE-2026-43515-FLAG-4356b3e6-d0f3-4c45-9c6d-730333e5dc8a
对已修复 10.1.55 服务器运行相同的漏洞利用脚本返回 401,且其独立生成的密钥(CVE-2026-43515-FLAG-4d92cd84-f79d-4bd7-8fd5-cc686dcc4649)与漏洞容器的值不同,确认修复后的阴性对照是真实结果,而非巧合。
该绕过攻击 100% 可确定性触发。只要存在上述 web.xml 配置,漏洞每次均会触发,无需竞争条件、时序依赖或堆布局操作。
清理环境¶
测试完成后,停止容器并删除其卷:
4. 安全建议¶
修复方案¶
升级至以下修复版本之一:
| 分支 | 修复版本 |
|---|---|
| 11.x | 11.0.22 |
| 10.1.x | 10.1.55 |
| 9.x | 9.0.118 |
Tomcat 8.5.x 和 7.x 已停止维护,Apache 未为这些分支发布补丁。仍在运行这些版本的用户应尽快升级。
缓解措施与临时解决方案¶
如果无法立即升级,请逐一检查所有已部署 web.xml 中的 <security-constraint>。触发漏洞的具体模式是:单个 <security-constraint> 包含两个或多个 <web-resource-collection> 块,这些块共享相同的 URL 扩展名模式(如 *.html、*.jsp),但各自列出不同的 HTTP 方法。依赖此模式进行访问控制的应用程序,除第一个集合中列出的方法外,其余方法均未受到保护。
若可以修改 web.xml,有两种临时缓解方案:
- 将需要相同认证约束的所有方法合并到单个
<web-resource-collection>块中,使用共享的 URL 模式,并为每个受保护的方法添加一个<http-method>元素。 - 或者——如果目的是保护所有方法——完全删除
<http-method>元素;不含方法列表的集合将覆盖所有 HTTP 方法。
如果受保护资源位于其他访问控制层之后(WAF、反向代理、应用层认证检查),这些层可以降低实际暴露面,但不能修复容器层面的授权绕过。
注:NVD/GHSA CVSS 评分为 9.1 CRITICAL,但 Apache 官方安全页面将此漏洞评级为"Moderate"。实际影响取决于约束背后的资源性质;受保护资源若包含敏感数据,危害程度则较高。
参考资料¶
- GHSA-5m62-pw8w-7w9f(GitHub 安全公告) — 受影响/修复版本、CVSS、CWE、补丁提交链接
- NVD CVE-2026-43515 — CVSS 9.1 CRITICAL, CWE-285
- Apache Tomcat 安全公告 (11.x) — 受影响版本 11.0.0-M1 – 11.0.21,修复版本 11.0.22
- Apache Tomcat 安全公告 (10.x) — 受影响版本 10.1.0-M1 – 10.1.54,修复版本 10.1.55
- Apache Tomcat 安全公告 (9.x) — 受影响版本 9.0.0.M1 – 9.0.117,修复版本 9.0.118
- 11.x 补丁提交 (276087d) —
RealmBase.java修复 + 回归测试 - 10.x 补丁提交 (c621317) —
RealmBase.java修复 + 回归测试 - 9.x 补丁提交 (db919ff) —
RealmBase.java修复 + 回归测试 - Apache OSS-Security 公告 — 公开披露讨论串
- Apache 邮件列表讨论串 — 供应商公告讨论