
Reprodutor para CVE-2026-40859 — Apache Camel camel-netty-http / camel-vertx-http: desserialização insegura de corpos de resposta HTTP no lado do produtor (RCE)
Este projeto demonstra uma vulnerabilidade de desserialização Java nos componentes camel-netty-http
e camel-vertx-http do Apache Camel, rastreada como CVE-2026-40859. Quando um endpoint produtor é
configurado com transferException=true (ou com allowJavaSerializedObject=true no nível do componente),
uma resposta HTTP do backend com status de falha e Content-Type: application/x-java-serialized-object
tem seu corpo desserializado com um java.io.ObjectInputStream puro e sem ObjectInputFilter. Um
atacante que controle o backend com o qual o produtor Camel se comunica — um serviço comprometido ou um
homem-no-meio (man-in-the-middle) em uma conexão HTTP sem criptografia — pode retornar um objeto
serializado especialmente criado e, se houver uma cadeia de gadgets no classpath, obter execução remota
de código no host Camel.
Comunicado de segurança: https://camel.apache.org/security/CVE-2026-40859.html
Não explorável na configuração padrão —
transferExceptiontem como padrãofalse. O PoC a habilita, como faria uma aplicação que deseja propagação remota de exceções.
Em uma resposta não-2xx, o produtor netty-http (com throwExceptionOnFailure=true, o padrão) constrói
uma exceção a partir da resposta por meio de populateNettyHttpOperationFailedException. Se
transferException estiver ativado e a resposta trouxer o tipo de conteúdo de objeto serializado, ele
desserializa o corpo:
// 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
O gadget é executado dentro de readObject(), antes da verificação instanceof Exception — portanto,
o payload nem precisa ser uma exceção. camel-vertx-http tem o mesmo sink em
VertxHttpHelper.deserializeJavaObjectFromStream.
from("direct:call")
.to("netty-http://backend-host:PORT/path?transferException=true");
// throwExceptionOnFailure defaults to true
Qualquer chamada de produtor cujo backend responda 5xx + application/x-java-serialized-object aciona o
sink.
A vítima é o produtor Camel (é ele quem realiza a desserialização). O atacante controla o backend
que ele chama. Neste PoC autocontido, ambos os papéis são executados na mesma JVM/container: um servidor
HTTP embutido baseado em raw socket (MaliciousBackend) faz o papel do backend controlado pelo atacante,
e a rota Camel (VictimRoute) é a vítima.
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
Em um ataque real, os bytes serializados são produzidos offline pelo atacante (por exemplo, com ysoserial); apenas a vítima precisa da cadeia de gadgets em seu classpath. Este PoC constrói o gadget em processo por conveniência, razão pela qual a JVM é iniciada com
--add-opens java.base/java.util=ALL-UNNAMED— essa flag é um detalhe de construção do gadget, não relacionado à vulnerabilidade.
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
# -> producer threw ...NettyHttpOperationFailedException (expected)
#
# >>> RCE proof — /tmp/pwned exists: true
docker exec cve-2026-40859 ls -la /tmp/pwned
docker compose down
Qualquer produtor camel-netty-http / camel-vertx-http configurado com transferException=true (ou
allowJavaSerializedObject=true) que se comunique com um backend que um atacante possa controlar ou
interceptar:
http://) substitui a resposta.transferException=true (ou allowJavaSerializedObject=true no componente).throwExceptionOnFailure=true (o padrão).5xx + application/x-java-serialized-object.commons-collections:3.2.1).Atualize para 4.14.8 / 4.18.3 / 4.20.0. A correção restringe ambos os helpers com uma allow-list
padrão do ObjectInputFilter (java.**;javax.**;org.apache.camel.**;!*), personalizável por meio da nova
opção de endpoint deserializationFilter ou da propriedade de sistema da JVM -Djdk.serialFilter.
Até a atualização:
transferException=true / allowJavaSerializedObject=true em produtores que se
comuniquem com backends não confiáveis ou acessíveis pela rede.https) para conexões de produtor, de modo que as respostas não possam ser substituídas
em trânsito.-Djdk.serialFilter=java.**;org.apache.camel.**;!*.Este reprodutor é fornecido apenas para pesquisa de segurança e testes autorizados, para uma vulnerabilidade divulgada publicamente e corrigida. Não o use contra sistemas sem permissão explícita.
| Propriedade | Valor |
|---|
| Componentes | camel-netty-http, camel-vertx-http (lado produtor) |
| Classe Afetada | org.apache.camel.component.netty.http.NettyHttpHelper#deserializeJavaObjectFromStream (e VertxHttpHelper#deserializeJavaObjectFromStream) |
| CWE | CWE-502: Desserialização de Dados Não Confiáveis |
| Impacto | Execução Remota de Código (RCE) |
| Pré-condição | transferException=true (ou allowJavaSerializedObject=true) + throwExceptionOnFailure=true (padrão) + backend controlado pelo atacante |
| Versões Afetadas | De 4.0.0 até antes de 4.14.8, de 4.15.0 até antes de 4.18.3, de 4.19.0 até antes de 4.20.0 |
| Versões Corrigidas | 4.14.8, 4.18.3, 4.20.0 |
| JIRA | CAMEL-23324 |
| Relator | Venkatraman Kumar (Securin) |