
Уязвимость CVE-2024-27316 в nghttp2
CVE-2024-27316 — уязвимость типа «отказ в обслуживании» (DoS) в библиотеке nghttp2, используемой для реализации HTTP/2. Уязвимость позволяет злоумышленнику вызвать исчерпание памяти на сервере через специально сформированные HTTP-заголовки. В статье представлен детальный разрыв механизма эксплуатации, анализ эксплоита на Go, а также практические рекомендации по защите.
Описание уязвимости
Уязвимость возникает из-за некорректной обработки длинных цепочек HTTP-заголовков. При превышении лимита заголовков nghttp2 пытается сгенерировать ответ HTTP 413
, буферизируя данные. Однако атакующий может отправлять бесконечные заголовки через фреймы CONTINUATION, что приводит к неограниченному росту буфера и краху сервера.
Затронутые версии
Уязвимы все версии Apache HTTP Server с 2.4.17 по 2.4.58 (включительно).
Технический анализ
HTTP/2 и фреймы CONTINUATION
В HTTP/2 заголовки могут разбиваться на несколько фреймов:
-
HEADERS: Начальный фрейм с частью заголовков.
-
CONTINUATION: Последующие фреймы, продолжающие передачу заголовков.
Сервер собирает все фреймы в единый буфер. Если злоумышленник отправляет бесконечные фреймы CONTINUATION без флага END_HEADERS
, буфер растёт до исчерпания памяти.
Уязвимый код в nghttp2
В исходном коде nghttp2 обработка CONTINUATION-фреймов выглядит так (упрощённо):
while (frame.type == CONTINUATION) {
append_to_buffer(frame.data);
if (frame.flags & END_HEADERS) break;
}
Если флаг END_HEADERS
не установлен, цикл продолжается, что и эксплуатируется в атаке.
Разбор эксплоита на Go
Ключевые элементы кода
-
Генерация зловредных заголовков:
-
Функция
makeRandHeader
создаёт длинные заголовки с уникальными именами/значениями, используя HPACK-сжатие для обхода ограничений на размер.
hfield := hpack.HeaderField{ Name: fmt.Sprintf("a...%d", i), // Длина > 512 байт Value: fmt.Sprintf("i...%d", i), }
-
Сжатие HPACK уменьшает размер данных, но сервер распаковывает их в память, что усугубляет нагрузку.
-
-
Отправка CONTINUATION-фреймов:
for { buf_out := makeRandHeader(i) framer.WriteContinuation(1, false, buf_out) // END_HEADERS = false }
-
Бесконечный цикл отправки фреймов без флага
END_HEADERS
.
-
-
Многопоточная атака:
for i := 0; i < *threads; i++ { go DoS(*target, *tls) // 2048 горутин по умолчанию }
-
Параллельные соединения увеличивают нагрузку на сервер.
-
Почему это работает?
-
Каждый CONTINUATION-фрейм заставляет сервер выделять память под заголовки.
-
Отсутствие лимита на число фреймов в уязвимой реализации nghttp2 приводит к экспоненциальному расходу памяти.
Условия успешной эксплуатации
-
Сервер использует nghttp2 ≤ 1.56.0.
-
Поддержка HTTP/2 (проверить можно через
curl -v --http2
). -
Сетевой доступ к серверу (открытые порты 443/80).
Стратегия защиты
1. Обновление nghttp2
-
Для Linux (apt):
sudo apt update && sudo apt upgrade libnghttp2-dev
-
Проверить версию:
nghttp2 --version
2. Ограничение размера заголовков
-
Nginx:
http2_max_header_size 4k; # Лимит на размер распакованных заголовков http2_max_requests 1000; # Лимит на число запросов в соединении
-
Apache:
LimitRequestFields 50 # Максимум 50 заголовков LimitRequestFieldSize 4096 # Максимальный размер одного заголовка
3. Мониторинг и WAF
-
Настроить алерты на аномальное число HTTP/2-соединений (например, через Prometheus+Grafana).
-
Использовать WAF (Cloudflare, ModSecurity) для блокировки подозрительных фреймов.
4. Тестирование на уязвимость
-
Инструменты:
-
h2spec: Проверка соответствия HTTP/2 спецификации.
-
CVE-2024-27316 PoC: Запуск тестового эксплоита в staging-среде.
-
Заключение
CVE-2024-27316 демонстрирует риски, связанные с обработкой HTTP/2-трафика. Для защиты критически важно:
-
Обновить nghttp2 до версии 1.57.0+.
-
Внедрить строгие лимиты на размер и число заголовков.
-
Мониторить аномальную активность в реальном времени.
Уязвимость уже используется в атаках!
