
Reproducteur de preuve de concept exécutable pour CVE-2026-101259, démontrant la divulgation de messages d'erreur dans les consommateurs camel-coap d'Apache Camel sur Spring Boot et Quarkus, ainsi que la vérification du correctif.
Reproducteur de preuve de concept exécutable pour la vulnérabilité Apache Camel où, lorsque le consommateur CoAP ne pouvait pas construire sa réponse une fois la route terminée, CamelCoapResource interceptait l'exception résultante et renvoyait son message au client CoAP comme charge utile d'une erreur 5.00 Internal Server Error :
} catch (Exception e) {
cexchange.respond(ResponseCode.INTERNAL_SERVER_ERROR, e.getMessage());
}
| Runtime | Répertoire | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-coap 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
Le consumer convertit le corps final du message en payload byte[], ainsi que les en-têtes CamelCoapMaxAge et
CamelCoapETag vers leurs types, après le retour de la route — et donc en dehors du
gestionnaire d'erreurs de la route. Un onException dans la route ne peut pas l'intercepter, car l'échec se produit dans le
consumer, et non dans la route.
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
Sur une version affectée (identique sur les deux runtimes) :
1) Converting the body to the byte[] payload fails once the route has completed
CoAP GET coap://127.0.0.1:5683/reading
response code : 5.00 (INTERNAL_SERVER_ERROR)
response payload : Error during type conversion from type: com.example.FailingBackendStream to the
required type: byte[] with value com.example.FailingBackendStream@5eede7d7 due to
java.io.IOException: connection to prod-db.internal:5432 reset while streaming
sensor_readings for node edge-gateway-07.dc2.internal
2) The CamelCoapMaxAge header cannot be converted to its type
CoAP GET coap://127.0.0.1:5683/reading-maxage
response code : 5.00 (INTERNAL_SERVER_ERROR)
response payload : Error during type conversion from type: java.lang.String to the required type:
java.lang.Long with value not-a-number due to java.lang.NumberFormatException:
For input string: "not-a-number"
3) A route that simply fails
CoAP GET coap://127.0.0.1:5683/reading-failing
response code : 2.05 (CONTENT)
response payload : partially built response
What a remote CoAP client learned from these responses:
the backend host and port, out of the cause's message : true
class names of the cause : true
the source and target types of the conversion : true
the string form of the offending value : true
a failed route answered with a SUCCESS code : true
>>> PROVEN: ...
Le message d'un tel échec nomme la classe de la valeur en cours de conversion, porte la forme
chaîne de la valeur, et se termine par le nom de classe et le message de la cause sous-jacente — ainsi un client CoAP distant lisait les noms de classe et de package, la forme chaîne de la valeur, et tout ce que porte la cause, ce qui en pratique peut inclure des chemins, des noms d'hôtes et des détails de connexion d'un backend. Le consommateur n'avait aucune option pour supprimer cela, contrairement aux consommateurs HTTP, qui offrent muteException à cette fin.
La sonde 3 constitue la seconde moitié du problème. L'exception levée par une route défaillante n'était pas envoyée du tout : le consommateur ne vérifiait pas si l'échange avait échoué, et répondait à un échec de route par 2.05 Content et quel que soit le corps que le message contenait à ce moment-là — un code de succès pour une route défaillante.
Une chose que ce reproducteur devait réussir : un corps pour lequel aucun convertisseur n'existe ne suffit pas.
getBody(byte[].class)renvoienulldans ce cas plutôt que de lever une exception, et le consommateur répond alors2.05avec une charge utile vide — aucune divulgation. La conversion doit échouer, et non être indisponible, c'est pourquoi la sonde 1 utilise un corps de flux qui lève une exception en cours de lecture. La sonde d'en-tête échoue dans l'autre sens, par une valeur de forme incorrecte.
Atteindre la divulgation nécessite une route dont un client distant peut rendre la réponse complétée non convertible, ce qui dépend de la façon dont la route est écrite. Rien ici n'est authentifié, et de simples requêtes GET CoAP sont tout ce que le client envoie.
| Propriété | Valeur |
|---|---|
| Composant | camel-coap (CamelCoapResource) |
| CWE | CWE-209 (Génération de message d'erreur contenant des informations sensibles) |
| Gravité | Moyenne |
| Vecteur d'attaque | Une requête CoAP vers un consommateur dont la réponse complétée ne peut être construite — un corps dont la conversion en byte[] échoue, ou un en-tête CamelCoapMaxAge / CamelCoapETag dont la conversion échoue |
| Impact | Un client CoAP distant lit les noms de classe et de package, la forme chaîne de la valeur et le message de la cause sous-jacente — en pratique des chemins, des noms d'hôtes et des détails de connexion au backend |
| Versions affectées | À partir de 4.0.0 avant 4.18.5, à partir de 4.19.0 avant 4.22.2 |
| Versions corrigées | 4.18.5, 4.22.2, 4.23.0 |
| JIRA | CAMEL-25087 |
| Crédit | Zhixi « Jace » Sun, chercheur indépendant en sécurité |
Avis : https://camel.apache.org/security/CVE-2026-101259.html
Le consommateur gagne une option muteException — sur les endpoints coap, coaps, coap+tcp et coaps+tcp
de la même manière — qui vaut true par défaut sur les trois lignes de version corrigées, de sorte que la mise à niveau suffit à elle seule
et qu'aucun changement de configuration n'est nécessaire. Le consommateur répond toujours 5.00 Internal Server Error, mais avec une
charge utile vide, et il signale désormais l'exception via le gestionnaire d'exceptions du consommateur, de sorte que la masquer
ne la cache pas à l'opérateur.
Il vérifie également si l'échange a échoué, et répond à un échec de route par 5.00 Internal Server Error
selon la même règle, là où il répondait auparavant 2.05 Content.
Corrigé sur main dans apache/camel#26994 (2245feac), rétroporté
vers camel-4.22.x dans #27046 (868d5604) et vers camel-4.18.x
dans #27048 (aaf5bbf8).
Définissez camel.version sur 4.22.2 et exécutez-le à nouveau. Vérifié sur 4.22.1 → 4.22.2 :
1) ... response code: 5.00 (INTERNAL_SERVER_ERROR) response payload : <empty>
2) ... response code: 5.00 (INTERNAL_SERVER_ERROR) response payload : <empty>
3) ... response code: 5.00 (INTERNAL_SERVER_ERROR) response payload : <empty>
>>> NOT reproduced: the error payload was empty.
La sonde 3 modifie également le code, passant de 2.05 Content à 5.00 Internal Server Error — l'échec de la route est désormais
traité comme un échec.