
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 Header Injection Reproducer (CVE-2026-48205)Данный проект демонстрирует внедрение заголовков сообщений в компоненте camel-dns Apache Camel, зарегистрированное как
CVE-2026-48205. Производители DNS считывают свои параметры операции — резолвер для запроса, имя/домен для
поиска, тип/класс записи и поисковый термин — из заголовков Exchange, чьи постоянные значения
(DnsConstants.DNS_SERVER, DNS_NAME, DNS_DOMAIN, DNS_TYPE, DNS_CLASS, TERM) представляли собой простые строки
dns.server, dns.name, dns.domain, dns.type, dns.class и term. Поскольку эти имена не начинаются с
префикса Camel / camel, HttpHeaderFilterStrategy — который блокирует только пространство заголовков Camel на границе HTTP —
пропускал их из входящего HTTP-запроса напрямую в Exchange.
В маршруте, который соединяет HTTP-потребитель (например, platform-http) с производителем dns:, любой HTTP-клиент может
таким образом установить заголовок dns.server, чтобы заставить производитель dig построить SimpleResolver, указывающий на
контролируемый атакующим DNS-сервер — подделку запроса на стороне сервера через DNS, благодаря которой атакующий наблюдает
запрашиваемое имя и может возвращать отравленные ответы — а также может установить dns.name / dns.domain для разрешения произвольных
внутренних имен хостов (разведка внутренней сети).
Уведомление: https://camel.apache.org/security/CVE-2026-48205.html
Исправление переименовывает заголовки в
CamelDnsServer/CamelDnsName/ и т.д., так что они фильтруются на границе HTTP, как и все остальные управляющие заголовки Camel. Та же группа, что и CVE-2025-27636, CVE-2026-46454 и CVE-2026-47323.
// DnsConstants (затронутая 4.18.2) — имена управляющих заголовков — это простые строки без префикса Camel:
public static final String DNS_SERVER = "dns.server";
public static final String DNS_NAME = "dns.name";
// DnsDigProducer.process (затронутая 4.18.2) — цель резолвера берется прямо из заголовка:
String server = exchange.getIn().getHeader(DnsConstants.DNS_SERVER, String.class);
SimpleResolver resolver = new SimpleResolver(server); // <-- контролируемый атакующим DNS-сервер
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) — запрос отправляется на сервер атакующего
Исправление (4.14.8 / 4.18.3 / 4.21.0, CAMEL-23574) переименовывает значения в соглашение CamelDns*.
from("platform-http:/lookup")
.setHeader("dns.name", constant("example.com"))
.setHeader("dns.type", constant("A"))
.setHeader("dns.class", constant("IN"))
.to("dns:dig"); // без dns.server -> резолвер по умолчанию (предполагается)
Маршрут выполняет dig для фиксированного имени через резолвер по умолчанию. Атакующий добавляет единственный заголовок dns.server, и
запрос перенаправляется на его DNS-сервер. (dns.server в нижнем регистре, поэтому он переживает нормализацию заголовков контейнера сервлетов — platform-http достаточно.)
Всё работает в одном автономном контейнере: маршрут жертвы, поддельный DNS-сервер атакующего (UDP 53) и драйвер атакующего.
CVE-2026-48205/
├── pom.xml # camel-platform-http + camel-dns 4.18.2
├── Dockerfile
├── docker-compose.yml # единый автономный сервис
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java
│ ├── FakeDnsServer.java # DNS-сервер атакующего на UDP 53 (записывает перенаправленный запрос)
│ ├── VictimRoute.java # platform-http:/lookup -> dns:dig
│ └── ExploitController.java # атакующий: вставляет 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) Легитимный запрос (без заголовка dns.server) — резолвер по умолчанию ===
DNS-сервер атакующего был запрошен: false
=== 2) Вставленный dns.server=127.0.0.1 (SSRF через DNS) ===
DNS-сервер атакующего был запрошен: true
наблюдаемое имя запроса: example.com.
>>> Доказательство внедрения заголовка / SSRF — неаутентифицированный HTTP-клиент перенаправил DNS-запрос
>>> маршрута на контролируемый атакующим сервер через заголовок dns.server: true
Теперь DNS-сервер атакующего видит имя запроса жертвы (и мог бы вернуть отравленный ответ). Направление
dns.server на реальный внутренний DNS-резолвер или установка dns.name на внутренние имена хостов позволяет провести разведку
внутренней сети.
Обновиться до 4.14.8 / 4.18.3 / 4.21.0 (CAMEL-23574). После обновления маршруты, управляющие DNS-операциями через
заголовки, должны использовать CamelDnsServer / CamelDnsName / и т.д.
До обновления удалите заголовки dns.* и term из любого ненадёжного входящего трафика перед производителем dns: и
устанавливайте DNS-сервер и параметры поиска из доверенного источника в маршруте.
Данный репродуктор предоставлен только для исследований безопасности и авторизованного тестирования в отношении публично раскрытой и исправленной уязвимости. Не используйте его против систем без явного разрешения.
| Свойство | Значение |
|---|
| Компонент | camel-dns |
| Затронутый класс | org.apache.camel.component.dns.DnsDigProducer — new SimpleResolver(getHeader("dns.server")) |
| CWE | CWE-20 (Некорректная проверка входных данных) / CWE-918 (Подделка запроса на стороне сервера) |
| Воздействие | Перенаправление DNS-запроса маршрута на контролируемый атакующим сервер (наблюдение имен, возврат отравленных ответов); перебор внутренних имен хостов |
| Предварительные условия | Маршрут соединяет HTTP-потребитель с производителем dns:; неаутентифицированный доступ, если потребитель не требует аутентификации |
| Затронутые версии | С 4.0.0 до 4.14.8, с 4.15.0 до 4.18.3, с 4.19.0 до 4.21.0 |
| Исправленные версии | 4.14.8, 4.18.3, 4.21.0 |
| JIRA | CAMEL-23574 (PR apache/camel#23411) |
| Автор | Yu Bao (PayPal) |