
Доказательство концепции эксплойта для уязвимости двойного освобождения памяти в Apache mod_http2 (CVE-2026-23918) с этапами разведки, эксплуатации и оценки риска удалённого выполнения кода (RCE).
Затронуто: Apache HTTP Server 2.4.66 с mod_http2 + Event MPM
Исправлено в: Apache 2.4.67 (mod_h2 v2.0.37)
CVSS 3.1: 8.8 HIGH — возможно неаутентифицированное удалённое выполнение кода
CWE: CWE-415 (Double Free)
mod_http2 в Apache 2.4.66 содержит ошибку двойного освобождения внутри h2_mplx.c:m_stream_cleanup(). Проблема возникает, когда клиент отправляет фрейм HEADERS, сразу за которым следует RST_STREAM на том же потоке. При правильном тайминге поток дважды помещается в массив очистки m->spurge. Когда mplx уничтожается, пул APR освобождается дважды, что повреждает кучу и вызывает SIGABRT или SIGSEGV.
Apache исправил это в mod_h2 v2.0.37, введя функцию add_for_purge(), которая выполняет простую проверку на дублирование, предотвращающую повторное добавление одного и того же потока.
// Уязвимый код (< v2.0.37)
APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream; // может произойти дважды
// Исправленный код (v2.0.37+)
static int add_for_purge(h2_mplx *m, h2_stream *stream) {
for (int i = 0; i < m->spurge->nelts; ++i)
if (APR_ARRAY_IDX(m->spurge, i, h2_stream*) == stream)
return FALSE;
APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream;
return TRUE;
}
По умолчанию скрипт выполняет трёхфазный конвейер на цели:
| Этап | Описание |
|---|---|
| 1 — Разведка | Определяет версию Apache, поддержку HTTP/2 через ALPN, тип MPM |
| 2 — Эксплуатация | Отправляет пакетные потоки HEADERS+RST_STREAM в потоках, пробует режимы inline и staged |
| 3 — Оценка RCE | Измеряет стабильность сбоя и оценивает уровень риска |
Оценка RCE вычисляется на основе трёх сигналов, которые можно определить удалённо. Первый — запущен ли Apache 2.4.66. Второй — используется ли MPM Event или Worker (mod_http2 отказывается запускаться с Prefork, поэтому если HTTP/2 работает, значит используется поточный MPM). Третий — насколько детерминирован сбой: сбой на первом раунде означает, что повреждение кучи контролируемо и воспроизводимо, а это необходимо для RCE.
pip install hpack requests
# Полный PoC для одной цели (поведение по умолчанию)
python poc.py -t 192.168.1.100
# Увеличение нагрузки: больше раундов, крупнее пакеты, больше потоков
python poc.py -t 192.168.1.100 -n 20 -b 500 -w 5
# Только пассивная проверка, ничего не отправляется на цель
python poc.py -t example.com --check-only
# Сканирование списка целей
python poc.py -l sites.txt -o results.json
# Пассивная проверка списка
python poc.py -l sites.txt --check-only
# Генерация Markdown-отчёта после выполнения
python poc.py -t target.com --report report.md
# одна цель на строку, комментарии игнорируются
192.168.1.100
example.com
example.com:8443
https://example.com
http://example.com:8080
Правильное исправление — обновление Apache до версии 2.4.67 или новее. Если нет возможности обновиться немедленно, отключение HTTP/2 полностью устраняет поверхность атаки:
# До
Protocols h2 http/1.1
# После (отключает HTTP/2)
Protocols http/1.1
Этот инструмент предназначен только для авторизованного тестирования безопасности и исследований. Убедитесь, что у вас есть явное письменное разрешение, прежде чем запускать его против любой цели. Автор не несёт ответственности за неправильное использование.
| Флаг | По умолчанию | Описание |
|---|
-t | — | Одна цель (имя хоста или IP) |
-l | — | Файл с целями, по одной на строку |
-p | 443 | Порт |
-n | 10 | Количество раундов эксплуатации |
-b | 200 | Пар HEADERS+RST за раунд |
-w | 3 | Параллельных соединений за раунд |
-d | 0.1 | Задержка между раундами в секундах |
-m | inline | Режим атаки: inline или staged |
--no-tls | — | Использовать h2c вместо TLS |
--check-only | — | Только пассивная разведка, без эксплуатации |
-o | — | Сохранить результаты в JSON-файл |
--report | — | Сгенерировать Markdown-отчёт |
-v | — | Подробный вывод |
| Уровень | Значение |
|---|
| CRITICAL | 2.4.66 подтверждён, HTTP/2 активен, обнаружен Event MPM, сбой детерминирован — немедленно установите патч |
| HIGH | 2.4.66 подтверждён, HTTP/2 активен, используется поточный MPM |
| MEDIUM | 2.4.66 обнаружен, но HTTP/2 или сбой ещё не подтверждены |
| LOW | Версия не совпадает или HTTP/2 не обнаружен |
| NONE | Уже исправлено до 2.4.67+ или не подвержено уязвимости |