
Reproducer for CVE-2026-40860 — Apache Camel camel-jms/sjms/amqp JMS ObjectMessage unsafe deserialization (RCE)
Dieses Projekt demonstriert eine Java-Deserialisierungsschwachstelle im camel-jms-Komponente von Apache Camel
(und transitiv camel-sjms, camel-sjms2, camel-amqp, camel-activemq, camel-activemq6),
die als CVE-2026-40860 verfolgt wird. JmsBinding.extractBodyFromJms() deserialisiert die Nutzlast einer eingehenden
JMS ObjectMessage über ObjectMessage.getObject() ohne ObjectInputFilter, Klasse-Allow-List
oder Deny-List. Da dies immer dann ausgeführt wird, wenn mapJmsMessage=true (Standard) und Camel ein JMS-Consumer ist,
kann ein Angreifer, der eine manipulierte ObjectMessage in eine konsumierte Queue/ein Topic veröffentlichen kann, Remote-Code-Ausführung erreichen, wenn sich eine Gadget-Kette im Klassenpfad befindet.
Advisory: https://camel.apache.org/security/CVE-2026-40860.html
// JmsBinding.extractBodyFromJms(Exchange, Message) - betroffene Version
if (message instanceof ObjectMessage objectMessage) {
Object payload = objectMessage.getObject(); // <-- deserialisiert ohne ObjectInputFilter
if (payload instanceof DefaultExchangeHolder holder) {
...
}
return payload;
}
getObject() führt die ObjectInputStream.readObject() des JMS-Providers über den Nachrichtenrumpf aus. Camel fügt keine
eigene Klassenfilterung hinzu, sodass eine Gadget-Kette im Klassenpfad während der Deserialisierung ausgeführt wird.
Der Fix (4.14.7 / 4.18.2 / 4.20.0) fügt eine standardmäßige ObjectInputFilter-Allow-List hinzu
(java.**;javax.**;org.apache.camel.**;!*), anpassbar über die neue deserializationFilter-Endpoint-Option
oder den JVM-weiten -Djdk.serialFilter. Beachten Sie den Commit-Kommentar von Camel zum Fix:
Diese Prüfung läuft nachdem der JMS-Provider die Nutzlast bereits deserialisiert hat. Sie verhindert, dass unerwartete Klassen an die Route weitergegeben werden, kann aber eigenständig keine Gadget-Ketten stoppen, deren
readObject()imObjectInputStreamdes Providers ausgelöst wird. Vollständiger Schutz erfordert das Konfigurieren des eigenen Deserialisierungsfilters des JMS-Providers und/oder des JVM-weiten-Djdk.serialFilter.
Vollständiger Schutz also = Camel upgraden + Provider / JVM-Filter einschränken. Dieser PoC verwendet einen ActiveMQ
Client mit trustAllPackages=true (eine häufige reale Einstellung), sodass der Provider die Nutzlast deserialisiert;
bei einer betroffenen Camel-Version steht nichts mehr im Weg.
from("jms:queue:evil") // mapJmsMessage ist standardmäßig true
.log("Consumed: ${body.class.name}");
Bereits das Empfangen der ObjectMessage löst die Deserialisierung aus – der Routenrumpf ist irrelevant.
Der Opfer ist der Camel JMS-Consumer. Der Angreifer ist jeder Producer, der in die Queue veröffentlichen kann. Beide sprechen mit einem echten Apache ActiveMQ Artemis Broker, der in Docker läuft.
CVE-2026-40860/
├── pom.xml # camel-jms 4.18.1 + activemq-client 6.2.4 + commons-collections 3.2.1 (Gadget)
├── Dockerfile # startet die App (--add-opens nur zum Bauen des Gadgets)
├── docker-compose.yml # Artemis Broker (quay.io) + die Reproducer-App
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── JmsConfig.java # OpenWire ConnectionFactory (trustAllPackages=true) + jms-Komponente
│ ├── VictimRoute.java # Opfer: from("jms:queue:evil")
│ ├── Gadget.java # CommonsCollections6 Gadget, feuert während getObject()
│ └── ExploitController.java # Angreifer: veröffentlicht ObjectMessage(Gadget) in die Queue
└── resources/
└── application.properties
In einem echten Angriff werden die serialisierten Bytes offline vom Angreifer erzeugt (z. B. mit ysoserial); nur der Opfer benötigt die Gadget-Kette im Klassenpfad. Dieser PoC baut das Gadget aus Bequemlichkeit im gleichen Prozess, weshalb die JVM mit
--add-opens java.base/java.util=ALL-UNNAMEDläuft – ein Gadget-Konstruktionsdetail, nicht mit der Schwachstelle verbunden.
mvn clean package -DskipTests
docker compose up -d --build
Dies startet einen Artemis-Broker (quay.io/artemiscloud/activemq-artemis-broker) und die Reproducer-App,
die sich über OpenWire mit ihm verbindet.
curl -s http://localhost:8080/exploit/attack
# -> ObjectMessage in Queue 'evil' veröffentlicht.
# camel-jms Consumer hat ObjectMessage.getObject() aufgerufen -> Deserialisierung.
#
# >>> RCE Nachweis — /tmp/pwned existiert: true
docker exec cve-2026-40860 ls -la /tmp/pwned
docker compose down
Jeder Camel JMS Consumer (camel-jms, camel-sjms, camel-sjms2, camel-amqp, camel-activemq,
camel-activemq6), der von einem Ziel liest, in das ein Angreifer veröffentlichen kann – ein gemeinsam genutzter
Broker, ein Topic mit offenen Produzenten, eine Queue, die von einem nicht vertrauenswürdigen Upstream gespeist wird –
mit mapJmsMessage=true (Standard).
mapJmsMessage=true (Standard).ObjectMessage in das konsumierte Ziel einreihen.trustAllPackages=true oder ein Provider ohne
restriktiven Filter).commons-collections:3.2.1).Upgrade auf 4.14.7 / 4.18.2 / 4.20.0, und die Deserialisierung Ende-zu-Ende einschränken:
-Djdk.serialFilter=java.**;org.apache.camel.**;!* (oder die neue
deserializationFilter-Option des Endpunkts).trustedPackages, nicht
trustAllPackages=true verwenden).Bis zum Upgrade:
ObjectMessage-Nutzlasten bevorzugen; mapJmsMessage=false setzen, wo die rohe Nachricht akzeptabel ist.trustAllPackages=true für nicht vertrauenswürdige Ziele.-Djdk.serialFilter anwenden.Dieser Reproducer dient ausschließlich der Sicherheitsforschung und autorisierten Tests für eine öffentlich bekannt gegebene und behobene Schwachstelle. Verwenden Sie ihn nicht gegen Systeme ohne ausdrückliche Genehmigung.
| Eigenschaft | Wert |
|---|
| Komponenten | camel-jms (+ camel-sjms, camel-sjms2, camel-amqp, camel-activemq, camel-activemq6) |
| Betroffene Klasse | org.apache.camel.component.jms.JmsBinding#extractBodyFromJms → jakarta.jms.ObjectMessage#getObject() |
| CWE | CWE-502: Deserialisierung nicht vertrauenswürdiger Daten |
| Auswirkung | Remote-Code-Ausführung (RCE) |
| Auslöser | Camel JMS Consumer + mapJmsMessage=true (Standard) + eine ObjectMessage, die der Angreifer in die Warteschlange stellen kann |
| Betroffene Versionen | Von 3.0.0 vor 4.14.7, von 4.15.0 vor 4.18.2, von 4.19.0 vor 4.20.0 |
| Behobene Versionen | 4.14.7, 4.18.2, 4.20.0 |
| JIRA | CAMEL-23321 |
| Melder | Venkatraman Kumar (Securin) |