
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
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.
Ce reproducteur est fourni uniquement pour la recherche en sécurité et les tests autorisés, pour une vulnérabilité publiquement divulguée et corrigée. Ne l'utilisez pas contre des systèmes sans autorisation explicite.
| 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 |