oscerd/CVE-2026-40859
GitHub: oscerd/CVE-2026-40859
Apache Camel camel-netty-http / camel-vertx-http 组件 Java 反序列化漏洞(CVE-2026-40859)的 PoC 复现项目,演示了后端响应被篡改为恶意序列化对象后导致远程代码执行的攻击场景。
Stars: 0 | Forks: 0
# camel-netty-http / camel-vertx-http HTTP-Response Unsafe Deserialization 复现器 (CVE-2026-40859)
本项目演示了 Apache Camel 的 `camel-netty-http`
和 `camel-vertx-http` 组件中的一个 **Java 反序列化漏洞**,追踪编号为 **CVE-2026-40859**。当 Producer Endpoint 被配置为
`transferException=true`(或组件级别的 `allowJavaSerializedObject=true`)时,如果**后端 HTTP
响应**返回失败状态码且 `Content-Type: application/x-java-serialized-object`,其 body 将会被原始的 `java.io.ObjectInputStream`
并且**没有使用 `ObjectInputFilter`** 进行反序列化。如果攻击者
控制了 Camel Producer 通信的后端——例如被攻破的服务,或者在明文 HTTP 连接上进行中间人攻击——
就可以返回一个精心构造的序列化对象,如果 classpath 中存在 gadget chain,
就会在 Camel 宿主机上实现**远程代码执行**。
安全通告:https://camel.apache.org/security/CVE-2026-40859.html
## 漏洞概述
| 属性 | 值 |
|----------|-------|
| **组件** | `camel-netty-http`, `camel-vertx-http` (Producer 端) |
| **受影响类** | `org.apache.camel.component.netty.http.NettyHttpHelper#deserializeJavaObjectFromStream` (以及 `VertxHttpHelper#deserializeJavaObjectFromStream`) |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
| **影响** | 远程代码执行 (RCE) |
| **前置条件** | `transferException=true` (或 `allowJavaSerializedObject=true`) + `throwExceptionOnFailure=true` (默认) + 攻击者控制的后端 |
| **受影响版本** | 从 4.0.0 至 4.14.8 之前,从 4.15.0 至 4.18.3 之前,从 4.19.0 至 4.20.0 之前 |
| **修复版本** | 4.14.8, 4.18.3, 4.20.0 |
| **JIRA** | CAMEL-23324 |
| **报告者** | Venkatraman Kumar (Securin) |
## 技术细节
在收到非 2xx 的响应时,netty-http Producer(设置了默认的 `throwExceptionOnFailure=true`)会
通过 `populateNettyHttpOperationFailedException` 根据响应构建
一个异常。如果开启了 `transferException` 且响应包含序列化对象的 content type,它就会对 body 进行反序列化:
```
// NettyHttpHelper.populateNettyHttpOperationFailedException(...) - affected version
if (transferException) {
String contentType = response.headers().get(NettyHttpConstants.CONTENT_TYPE);
if (NettyHttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT.equals(contentType)) { // application/x-java-serialized-object
InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, response);
if (is != null) {
Object body = deserializeJavaObjectFromStream(is); // <-- sink
if (body instanceof Exception) {
return (Exception) body;
}
}
}
}
// NettyHttpHelper.deserializeJavaObjectFromStream(InputStream) - affected version
ObjectInputStream ois = new ObjectInputStream(is); // NO ObjectInputFilter
answer = ois.readObject(); // gadget fires here
```
Gadget 会在 `instanceof Exception` 检查**之前**的 `readObject()` 中执行——因此 Payload 甚至
都不必是一个 Exception。`camel-vertx-http` 在
`VertxHttpHelper.deserializeJavaObjectFromStream` 中存在相同的 Sink。
## 受害者路由
```
from("direct:call")
.to("netty-http://backend-host:PORT/path?transferException=true");
// throwExceptionOnFailure defaults to true
```
任何其后端响应为 `5xx` + `application/x-java-serialized-object` 的 Producer 调用都会触发该 Sink。
## 仓库结构 —— 攻击者与受害者
**受害者**是 Camel Producer(由它执行反序列化)。**攻击者**
控制它调用的后端。在这个独立的 PoC 中,两个角色都在同一个 JVM/Container 中运行:一个嵌入式的
原始 Socket HTTP 服务器(`MaliciousBackend`)扮演受攻击者控制的后端,而 Camel 路由
(`VictimRoute`)则是受害者。
```
CVE-2026-40859/
├── pom.xml # camel-netty-http 4.18.2 + commons-collections 3.2.1 (gadget)
├── Dockerfile # runs the app (with --add-opens, needed only to build the gadget)
├── docker-compose.yml
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── VictimRoute.java # victim: netty-http producer, transferException=true
│ ├── MaliciousBackend.java # attacker backend: 500 + serialized-object body on :9999
│ ├── Gadget.java # CommonsCollections6 gadget, fires during readObject()
│ └── ExploitController.java # /exploit/attack drives the producer call
└── resources/
└── application.properties
```
## 前置条件
- Java 17+ 和 Maven 3.8+
- Docker (用于运行复现程序)
## 复现步骤
### 步骤 1:构建并启动 Container
```
mvn clean package -DskipTests
docker compose up -d --build
```
### 步骤 2:触发反序列化 (RCE)
```
curl -s http://localhost:8080/exploit/attack
# -> producer 抛出了 ...NettyHttpOperationFailedException (预期)
# # >>> RCE 证明 — /tmp/pwned 存在:true
```
### 步骤 3:验证
```
docker exec cve-2026-40859 ls -la /tmp/pwned
```
### 清理
```
docker compose down
```
## 攻击向量
任何配置了 `transferException=true`(或
`allowJavaSerializedObject=true`)且与攻击者可以控制或拦截的后端进行通信的 camel-netty-http / camel-vertx-http **Producer**:
- 在未加密(`http://`)的 Producer 连接上进行**中间人攻击**,替换响应内容。
- **被攻破或恶意的后端**服务直接返回精心构造的响应。
## 利用条件
1. Producer 设置了 `transferException=true`(或组件设置了 `allowJavaSerializedObject=true`)。
2. `throwExceptionOnFailure=true`(默认值)。
3. 攻击者控制/可拦截的后端返回 `5xx` + `application/x-java-serialized-object`。
4. **Classpath 中存在 Gadget 库**(此处为 `commons-collections:3.2.1`)。
## 修复建议
升级到 **4.14.8 / 4.18.3 / 4.20.0**。该修复使用默认的
`ObjectInputFilter` 允许列表(`java.**;javax.**;org.apache.camel.**;!*`)对这两个 Helper 进行了限制,并可通过新增的
`deserializationFilter` Endpoint 选项或 JVM 级别的 `-Djdk.serialFilter` 系统属性进行自定义。
## 缓解措施
在升级之前:
1. 在与不受信任或网络可达的后端通信的 Producer 上,**切勿启用** `transferException=true` / `allowJavaSerializedObject=true`。
2. 对 Producer 连接使用 **TLS (`https`)**,以防响应在传输过程中被替换。
3. 如果确实需要该选项,请设置明确的允许列表:
`-Djdk.serialFilter=java.**;org.apache.camel.**;!*`。
4. 从 Classpath 中**移除 Gadget 库**(升级/移除 commons-collections 3.x 及类似库)。
## 免责声明
本复现程序仅用于**安全研究和授权测试**,针对的是**已公开
披露并已修复**的漏洞。未经明确许可,请勿将其用于任何系统。
标签:Apache Camel, GHAS, Java安全, JS文件枚举, XXE攻击, 反序列化漏洞, 域名枚举, 漏洞复现, 版权保护, 编程工具, 请求拦截, 远程代码执行