
Базовый образ Docker с обратно портированным исправлением проверки заголовка Host для CVE-2025-12543 в Undertow 1.4.x, обеспечивающий безопасное развертывание приложений WildFly 11.
Этот репозиторий предоставляет базовый Docker-образ, построенный на WildFly 11.0.0.Final с бэкпортированным исправлением для CVE-2025-12543 — критической уязвимости проверки заголовка Host в Undertow.
Образ предназначен для передачи коллегам в качестве базового. Они могут развернуть своё .war-приложение и standalone.xml поверх него.
| Поле | Детали |
|---|
| CVE ID | CVE-2025-12543 |
| Компонент | io.undertow:undertow-core |
| Серьёзность | Критическая (CVSS 9.6) |
| Затронутые версии | Все версии < 2.2.39 (включая 1.4.x) |
| Исправлено в | Undertow 2.2.39 / 2.3.22 |
| Версия WildFly 11 | undertow-core-1.4.18.Final — затронута |
Undertow неправильно проверяет заголовок Host во входящих HTTP-запросах. Запросы, содержащие некорректные или вредоносные заголовки Host, обрабатываются без отклонения, что позволяет:
Другие пользователи всё ещё используют WildFly 11, и в настоящее время нет ресурсов или планов на обновление. Исправление было бэкпортировано непосредственно в JAR-файл Undertow 1.4.18.Final.
.
├── Dockerfile # Основное описание образа
├── README.md
├── wildfly-dist-11.0.0.Final.tar.gz # Дистрибутив WildFly 11
├── reports/
│ ├── result-20260401-0230.txt # Отчёт сканирования CVE, выявивший уязвимость
│ └── wildfly_11.0.0.Final_*.txt # Дополнительные отчёты сканирования
└── patch/
├── src/
│ ├── HostHeaderHandler.java # Бэкпортированное исправление — новый класс обработчика
│ ├── HttpReadListener_only.java # Декомпилированный и пропатченный исходный код HttpReadListener (справочно)
│ └── PatchHttpReadListener.java # Инструмент для патчинга байт-кода с помощью Javassist
├── build.sh # Скрипт сборки — пересобирает пропатченный JAR с нуля
├── undertow-core-1.4.18.Final.jar # Оригинальный (не пропатченный) JAR — сохранён для справки
└── undertow-core-1.4.18.Final-patched.jar # Пропатченный JAR, внедряемый в образ
DockerfileСтроит конечный образ. Он:
bitnamilegacy/java:1.8.432-7-debian-12-r2 (OpenJDK 1.8.0_432) в качестве базового/opt/jboss/wildflyundertow-core-1.4.18.Final.jar на пропатченную версиюstandalone.sh -b 0.0.0.0 (привязка ко всем интерфейсам)patch/undertow-core-1.4.18.Final-patched.jarПропатченный JAR Undertow. Он идентичен оригиналу, за исключением двух изменений:
io/undertow/server/handlers/HostHeaderHandler.class (и его внутренние классы)io/undertow/server/protocol/http/HttpReadListener.class — внедряет HostHeaderHandler в конвейер запросовpatch/src/HostHeaderHandler.javaБэкпортированный обработчик проверки заголовка Host. Портирован из PR Undertow #1857 (UNDERTOW-2656).
Все константы (IP4_EXACT, IP6_EXACT, таблицы символов) являются самодостаточными — без зависимости от API, добавленных в Undertow 2.x. При каждом HTTP-запросе проверяется:
400 Bad Requestpatch/src/PatchHttpReadListener.javaОдноразовый патчер байт-кода с использованием Javassist. Он загружает HttpReadListener из оригинального JAR и заменяет:
// Было
Connectors.executeRootHandler(connection.getRootHandler(), exchange);
// Стало
Connectors.executeRootHandler(
HostHeaderHandler.WRAPPER.wrap(connection.getRootHandler()),
exchange
);
Это автоматически внедряет HostHeaderHandler в каждый HTTP-запрос без необходимости полной перекомпиляции HttpReadListener (который зависит от сложных внутренних классов и внутренностей xnio).
patch/src/HttpReadListener_only.javaДекомпилированный исходный код оригинального HttpReadListener из Undertow 1.4.18.Final, используемый в качестве справки для определения точки внедрения. Пропатченная версия этого исходного кода также сохранена для целей аудита.
reports/result-20260401-0230.txtОтчёт сканирования CVE (сгенерирован 2026-04-01), который выявил CVE-2025-12543 в undertow-core-1.4.18.Final по пути:
/opt/jboss/wildfly/modules/system/layers/base/io/undertow/core/main/undertow-core-1.4.18.Final.jar
Отчёт сканирования (result-20260401-0230.txt) подтвердил, что undertow-core-1.4.18.Final подвержен CVE-2025-12543 (CVSS 9.6).
Исправление находится в PR Undertow #1857, объединённом в main (2026-01-09) и бэкпортированном в ветки 2.2.x и 2.3.x. Исправление добавляет HostHeaderHandler.java и встраивает его в HttpReadListener для проверки заголовка Host в каждом запросе.
Undertow 1.4.x → 2.2.x — это переход на мажорную версию с ломающими изменениями API. WildFly 11 тесно связан с Undertow 1.4.x через JBoss Modules. Простая замена JAR приведёт к ClassNotFoundException / NoSuchMethodError при запуске.
HostHeaderHandler.javaНаписать самодостаточную версию HostHeaderHandler.java, совместимую с Undertow 1.4.18.Final:
IP4_EXACT, IP6_EXACT) — недоступны в NetworkUtils версии 1.4.xexchange.isHostIncludedInRequestURI() — недоступен в HttpServerExchange версии 1.4.xСкомпилировать с classpath Undertow 1.4.18 + xnio внутри образа WildFly:
javac -cp undertow-core-1.4.18.Final.jar:xnio-api-3.5.4.Final.jar:jboss-logging-3.3.1.Final.jar \
-d out HostHeaderHandler.java
HttpReadListener через JavassistДекомпилировать HttpReadListener с помощью Procyon, чтобы найти точку внедрения:
Connectors.executeRootHandler(this.connection.getRootHandler(), httpServerExchange);
находится в handleEventWithNoRunningRequest().
Поскольку HttpReadListener имеет анонимные внутренние классы ($1, $2, $3), на которые нельзя сослаться из декомпилированного исходного кода, полная перекомпиляция невозможна. Вместо этого используйте Javassist (PatchHttpReadListener.java) для инструментирования байт-кода напрямую — заменив вызов executeRootHandler, чтобы обернуть корневой обработчик с помощью HostHeaderHandler.WRAPPER.
java -cp javassist.jar:undertow-core-1.4.18.Final.jar:out \
PatchHttpReadListener undertow-core-1.4.18.Final.jar out/
Скопировать оригинальный JAR и внедрить пропатченные/новые файлы классов:
cp undertow-core-1.4.18.Final.jar undertow-core-1.4.18.Final-patched.jar
jar uf undertow-core-1.4.18.Final-patched.jar \
-C out io/undertow/server/handlers/HostHeaderHandler.class \
-C out "io/undertow/server/handlers/HostHeaderHandler\$Wrapper.class" \
-C out "io/undertow/server/handlers/HostHeaderHandler\$1.class" \
-C out io/undertow/server/protocol/http/HttpReadListener.class
Добавить COPY для пропатченного JAR и заменить оригинал внутри образа:
COPY patch/undertow-core-1.4.18.Final-patched.jar /tmp/
RUN cp /tmp/undertow-core-1.4.18.Final-patched.jar \
/opt/jboss/wildfly/modules/system/layers/base/io/undertow/core/main/undertow-core-1.4.18.Final.jar
docker build -t wildfly:11.0.0.Final-patched .
Проверка:
# Корректный заголовок Host — должен вернуть 200
curl -v -H "Host: localhost:8080" http://localhost:8080/
# Недопустимые символы в Host — должен вернуть 400 Host Header Bad Characters
curl -v -H "Host: evil<script>" http://localhost:8080/
# Дублирующиеся заголовки Host — должен вернуть 400 Bad Request
# Примечание: curl внутренне дедуплицирует заголовки Host, поэтому для этого теста требуется сырой TCP-запрос
exec 3<>/dev/tcp/localhost/8080; \
printf "GET / HTTP/1.1\r\nHost: localhost\r\nHost: evil.com\r\nConnection: close\r\n\r\n" >&3; \
sleep 1; head -1 <&3; exec 3>&-
# Порт вне диапазона — должен вернуть 400 Host Header Malformed Port
curl -v -H "Host: localhost:99999" http://localhost:8080/
| Запрос | Ожидаемый результат | Фактический результат |
|---|---|---|
Host: localhost:8080 (корректный) | 200 OK | ✓ |
Host: evil<script> (недопустимые символы) | 400 Host Header Bad Characters | ✓ |
Два заголовка Host: (дубликат, сырой TCP) | 400 Bad Request | ✓ |
Host: localhost:99999 (некорректный порт) | 400 Host Header Malformed Port | ✓ |
HostДо этого патча опция WildFly REQUIRE_HOST_HTTP11 по умолчанию имела значение false, что означало, что HTTP/1.1 запросы без заголовка Host молча принимались.
После этого патча HostHeaderHandler строго соблюдает RFC 7230 — все HTTP/1.1 запросы без заголовка Host отклоняются с 400 No Host Header, независимо от настройки REQUIRE_HOST_HTTP11.
Кого это может затронуть:
GET / HTTP/1.1 без заголовка HostЧто делать:
Убедитесь, что все HTTP/1.1 клиенты включают заголовок Host. Это уже требуется по RFC 7230, и любые стандартные HTTP-библиотеки (curl, Java HttpClient и т.д.) делают это автоматически. Затронуты только несоответствующие или очень старые пользовательские клиенты.
# Теперь это будет отклонено с 400:
GET /health HTTP/1.1
Connection: close
# Это корректно и будет работать:
GET /health HTTP/1.1
Host: your-server:8080
Connection: close
Если вам нужно заново сгенерировать patch/undertow-core-1.4.18.Final-patched.jar в новом окружении (например, предварительно собранный JAR недоступен), используйте предоставленный скрипт сборки.
Требования: JDK 8, curl, доступ в интернет к Maven Central.
cd patch
bash build.sh
Скрипт выполнит:
HostHeaderHandler.javaPatchHttpReadListener.java для патча байт-кода HttpReadListener через Javassistundertow-core-1.4.18.Final-patched.jarПосле завершения можно продолжить обычную сборку docker build.
Примечание:
wildfly-dist-11.0.0.Final.tar.gzне включён в этот репозиторий (превышает лимит GitHub в 100 МБ). Загрузите его с Maven Central перед сборкой:https://repo1.maven.org/maven2/org/wildfly/wildfly-dist/11.0.0.Final/wildfly-dist-11.0.0.Final.tar.gz
docker build -t wildfly:11.0.0.Final-patched .
docker run -d -p 8080:8080 wildfly:11.0.0.Final-patched
Коллеги могут смонтировать или расширить образ своим развёртыванием:
FROM wildfly:11.0.0.Final-patched
COPY standalone.xml /opt/jboss/wildfly/standalone/configuration/standalone.xml
COPY myapp.war /opt/jboss/wildfly/standalone/deployments/