HTTP/2 Bomb: как один ноутбук кладёт nginx, Apache и IIS за секунды
HTTP/2 Bomb: как один ноутбук кладёт nginx, Apache и IIS за секунды
3 июня 2026 года компания Calif опубликовала HTTP/2 Bomb — эксплойт для удалённого DoS против nginx, Apache httpd, Microsoft IIS, Envoy и Cloudflare Pingora. Никакого ботнета не нужно: обычный домашний компьютер с каналом 100 Мбит/с кладёт уязвимый сервер за секунды. Против Apache httpd и Envoy один клиент потребляет и удерживает 32 ГБ памяти сервера примерно за 20 секунд.
Атаку нашёл не человек — её нашёл OpenAI Codex. Исследователь Quang Luong дал модели задание проанализировать кодовую базу популярных HTTP/2-серверов на предмет потенциально опасных сочетаний известных техник. Codex скомбинировал два приёма, каждый из которых известен сообществу уже больше десяти лет, и получил атаку, которую ни один из разработчиков затронутых серверов не предусмотрел.
Для nginx уязвимость закрыта в версии 1.29.8 (mainline) и в 1.30.0+ (stable). Если вы уже обновились до 1.30.2 по итогам прошлых CVE — nginx-rift и CVE-2026-9256 — ваш сервер защищён. Для Apache httpd выпущен патч mod_http2 v2.0.41, CVE-2026-49975. IIS, Envoy и Cloudflare Pingora на момент публикации патчей не имеют.
ЧТО ТАКОЕ HTTP/2 BOMB
Представьте библиотекаря, который умеет запоминать книги: вы называете книгу один раз, он кладёт её на полку, а дальше вы можете ссылаться на неё одним словом — и он каждый раз достаёт полную копию. HTTP/2 HPACK работает так же: отправитель один раз помещает заголовок в динамическую таблицу, а дальше ссылается на него одним байтом. Получатель при каждой ссылке материализует полную структуру заголовка в памяти. Экономия трафика при нормальной работе. Проблема — когда заголовок маленький, а ссылок тысячи.
HTTP/2 (RFC 9113) добавляет управление потоком: получатель объявляет размер окна, и отправитель не может передавать данные сверх этого окна, пока не получит WINDOW_UPDATE. Критично здесь то, что клиент контролирует окно для ответов сервера. Это означает, что клиент может удерживать сервер с открытым стримом сколь угодно долго, периодически отправляя минимальные WINDOW_UPDATE чтобы не допустить закрытия по таймауту. HTTP/2 Bomb комбинирует оба механизма: быстро накачать память через HPACK и не дать ей освободиться через Window Stall.
КАК РАБОТАЕТ ОШИБКА
Первая часть — HPACK Indexed Reference Bomb. Атакующий помещает один заголовок в динамическую таблицу, а затем в рамках одного запроса отправляет тысячи однобайтовых индексных ссылок на него. Каждая ссылка стоит атакующему один байт в сети, но заставляет сервер аллоцировать полную структуру заголовка. Коэффициент усиления зависит от реализации:
| Сервер | Усиление | Результат в демо |
|-------------------------------------|------------|---------------------|
| Envoy 1.37.2 | ~5 700:1 | ~32 ГБ за ~10 с |
| Apache httpd 2.4.67 | ~4 000:1 | ~32 ГБ за ~18 с |
| nginx 1.29.7 | ~70:1 | ~32 ГБ за ~45 с |
| Microsoft IIS (Windows Server 2025) | ~68:1 | ~64 ГБ за ~45 с |
Важно понять почему обычная защита не сработала. Предыдущие HPACK-бомбы (CVE-2016-6581) клали большое значение в таблицу и многократно ссылались на него. Серверы научились ограничивать суммарный декодированный размер заголовков. HTTP/2 Bomb идёт в другую сторону: заголовок почти пустой, а усиление приходит от per-entry накладных расходов самого аллокатора вокруг каждой записи. Лимит на декодированный размер не срабатывает, потому что декодировать почти нечего.
Вторая часть — HTTP/2 Window Stall. Атакующий объявляет нулевое окно управления потоком для ответа сервера. Сервер не может завершить передачу ответа, не закрывает стрим, не освобождает память. Чтобы соединение не истекло по таймауту, атакующий периодически досылает минимальные WINDOW_UPDATE кадры — сервер видит активность и продолжает держать стрим живым. В результате вся аллоцированная память остаётся закреплённой всё то время, пока атакующий поддерживает соединение.
Вместе эти два приёма создают ситуацию когда память аллоцируется быстро и не освобождается никогда. В реальной атаке, по замечанию Calif, убивать процесс через OOM нецелесообразно — убитый воркер просто перезапустится чистым. Эффективнее держать давление на память чуть ниже порога OOM-killer, загнать машину в swap и ждать пока каждый запрос на сервере не начнёт деградировать.
КАК ЭТО ЭКСПЛУАТИРУЕТСЯ
Apache и Envoy имеют лимит на количество заголовочных полей — казалось бы, защита. Но спецификация RFC 9113 §8.2.3 явно разрешает разбивать заголовок Cookie на отдельные поля по одному куску на поле. И ни Apache, ни Envoy не считали эти куски против своего лимита. Обход элегантный: заходи через черёд входа, который специально оставили открытым в самом стандарте.
В Envoy каждый кусок cookie дописывается в буфер — жирное 4 КБ значение, указанное 32 000 раз, даёт усиление ~3 600:1 по логическому соотношению, а измеренное RSS-отношение доходит до ~5 700:1 на одном стриме с учётом накладных расходов аллокатора. Apache httpd при каждом новом куске пересобирает всю склеенную строку cookie заново, оставляя каждую старую копию живой до очистки стрима — поэтому даже пустое значение cookie даёт ~4 000:1.
PoC-скрипты, Docker-лаборатории и подробные writeup’ы для каждого сервера опубликованы на GitHub (califio/publications/tree/main/MADBugs/http2-bomb). Commit-to-exploit путь короткий — Calif прямо предупреждают, что любая современная языковая модель способна превратить публичные диффы патчей в рабочий эксплойт.
РЕАЛЬНАЯ ЦЕПОЧКА АТАКИ
Атакующий открывает HTTP/2-соединение к серверу — никакой аутентификации, никаких предварительных знаний о конфигурации не нужно. Устанавливает динамическую таблицу HPACK, помещая один заголовок. Затем в одном запросе отправляет тысячи однобайтовых ссылок на него — сервер аллоцирует структуры, атакующий тратит байты. Одновременно объявляет нулевое окно для ответа сервера, не давая ни одному стриму завершиться.
При коэффициенте усиления nginx 70:1 и канале 100 Мбит/с атакующий способен генерировать нагрузку ~7 Гбит/с в памяти сервера — без какого-либо ботнета. Apache и Envoy с усилением 4 000–5 700:1 достигают 32 ГБ за 10–20 секунд на типичных VPS. Сервер не падает сразу — он деградирует: новые запросы начинают обрабатываться всё медленнее, пока не перестают обрабатываться совсем.
По данным Shodan, более 880 000 сайтов поддерживают HTTP/2 и работают на одном из затронутых серверов. Многие за CDN — что существенно снижает риск — но прямые инсталляции без проксирования открыты напрямую.
ТАЙМЛАЙН
В апреле 2026 года команда Calif раскрыла уязвимость команде nginx. Разработчики отреагировали на следующий день, импортировав директиву max_headers из freenginx и выпустив nginx 1.29.8. Коммит: 365694160a85229a7cb006738de9260d49ff5fa2. Директива max_headers с дефолтом 1000 вошла и в stable-ветку: nginx 1.30.0 вышел в апреле 2026 с этой же защитой.
27 мая 2026 года Calif раскрыли уязвимость команде Apache. Stefan Eissing исправил её в тот же день, заставив заголовки cookie учитываться против лимита LimitRequestFields. Коммит: 47d3100b252dc6668a9e46ae885242be9eeca9cd. Уязвимости присвоен номер CVE-2026-49975.
3 июня 2026 года Calif опубликовали полный writeup, PoC-скрипты и Docker-лаборатории. Одновременно они раскрыли, что именно публичные диффы патчей помогли им обнаружить уязвимость в IIS, Envoy и Pingora — AI-модель прочитала коммиты и самостоятельно нашла аналогичные паттерны в других серверах. Microsoft, Envoy и Cloudflare уведомлены, патчей на момент публикации нет.
КАК ЭТО ПЕРЕЖИЛО ДЕСЯТЬ ЛЕТ
HPACK Bomb как концепция существует с 2016 года — CVE-2016-6581, Cory Benfield. Slowloris-подобное истощение через HTTP/2 — тоже 2016 год, CVE-2016-8740 и CVE-2016-1546. В 2025 году Gal Bar Nahum получил усиление ~4 000:1 против Apache httpd через CVE-2025-53020. Все эти техники публичны, задокументированы, закрывались отдельными патчами.
Проблема в том, что каждый раз закрывался конкретный вектор, а не корневая причина. Серверы научились ограничивать суммарный декодированный размер заголовков — и именно поэтому новая атака работает через усиление на уровне per-entry накладных расходов, а не через размер значений. RFC 7541 содержит целый раздел §7.3 «Memory Consumption» с предупреждением о том, что атакующий может попытаться истощить память через HPACK. Раздел объясняет что HPACK ограничивает таблицу через SETTINGS_HEADER_TABLE_SIZE и считает проблему решённой. Но когда пять независимых реализаций читают этот раздел и всё равно оказываются уязвимы — дефект в спецификации, а не в реализациях.
Автор writeup Calif добавляет личный контекст: в 2012 году он участвовал в открытии атаки CRIME на HTTP-сжатие заголовков, а потом был привлечён к рецензированию исправления — которое стало HPACK. Перечитав свои заметки того времени, он обнаружил: он ни разу не рассматривал эту атаку. Был слишком сосредоточен на CRIME и пропустил бомбу.
ПОЧЕМУ ЭТО ВАЖНО
Для nginx-администраторов это третья критическая уязвимость за несколько месяцев — после nginx-rift и CVE-2026-9256 (nginx-poolslip, CVSS 9.2). Если вы обновились до 1.30.2 по итогам тех CVE через официальный репозиторий nginx.org — директива max_headers уже есть в вашей сборке и работает с дефолтом 1000. Если вы всё ещё на Ubuntu-пакете 1.24.0 — вы уязвимы сразу ко всем трём.
Эта атака принципиально отличается от традиционного DDoS. Традиционный DDoS требует полосы пропускания: чтобы забить 1 Гбит/с канал сервера, нужно генерировать 1 Гбит/с трафика. HTTP/2 Bomb с коэффициентом 70:1 для nginx позволяет создать эквивалент 7 Гбит/с нагрузки на память с канала 100 Мбит/с. Для Apache с усилением 4 000:1 — 400 Гбит/с эквивалент с того же домашнего подключения. Cloudflare и другие CDN за счёт своей инфраструктуры значительно снижают риск, но прямые инсталляции без проксирования открыты напрямую.
Отдельного внимания заслуживает то, как была найдена атака. Оба примитива публичны больше десяти лет. Что сделал Codex — прочитал кодовую базу серверов, распознал что два приёма компонуются, и построил комбинированную атаку. Это очевидно после того как видишь результат — и при этом, насколько можно судить, ни один человек не собрал эту комбинацию против данных серверов раньше.
ОБНОВЛЕНИЕ
Сначала — понять свою ситуацию. Проверить версию nginx и наличие защиты:
nginx -v
nginx -T | grep max_headers
Если версия 1.30.0+ (stable) или 1.29.8+ (mainline) — защита уже есть. Если grep ничего не показал — директива не задана явно, но дефолт 1000 работает автоматически с этих версий. Если версия ниже — читайте дальше.
Сценарий 1: репозиторий nginx.org уже подключён. Проверьте что будет установлено и обновляйте:
apt-cache policy nginx
В строке Candidate: должно быть 1.30.x с origin nginx.org. Если так — обновляйте:
apt update && apt install nginx
Сценарий 2: всё ещё на Ubuntu-пакете 1.24.0. Подключаем репозиторий nginx.org. GPG-ключ — через pipe с dearmor, как указывает официальная документация nginx.org:
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Проверьте fingerprint — не пропускайте этот шаг:
gpg --dry-run --quiet --no-keyring \
--import --import-options import-show \
/usr/share/keyrings/nginx-archive-keyring.gpg
Ожидаемые fingerprint’ы (проверьте актуальные на nginx.org/en/pgp_keys.html):
8540A6F18833A80E9C1653A42FD21310B49F6B46
573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
9E9BE90EACBCDE69FE9B204CBCDCD8A38D88A2B3
Если не совпадают — удалите файл немедленно. Если совпадают — добавьте репозиторий (stable 1.30.x) и pinning:
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
https://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
cat > /etc/apt/preferences.d/nginx << 'EOF'
Package: nginx*
Pin: origin nginx.org
Pin-Priority: 900
EOF
apt update && apt install nginx
При установке apt спросит про конфигурационный файл — выбирайте N, оставляйте свою версию конфига. После обновления проверьте:
nginx -v && nginx -t && systemctl reload nginx
Это обновление закрывает сразу три уязвимости: nginx-rift, CVE-2026-9256 и HTTP/2 Bomb.
Сценарий 3: dnf-системы (RHEL, Rocky Linux, AlmaLinux). Процедура аналогична Ubuntu — подключить репозиторий nginx.org через nginx.org/en/linux_packages.html, используя dnf вместо apt.
Apache httpd. Ситуация сложнее — патч в standalone mod_http2 v2.0.41 не вошёл в основной httpd 2.4.x, официального apt-пакета нет. Самый безопасный путь прямо сейчас — отключить HTTP/2:
# В httpd.conf или конфиге виртуального хоста
Protocols http/1.1
apachectl configtest
systemctl reload apache2
curl -I --http2 https://example.com 2>&1 | grep -i "HTTP/"
Если ответ HTTP/1.1 — HTTP/2 отключён. Если хотите установить mod_http2 v2.0.41 сохранив HTTP/2 — инструкция по сборке в README репозитория github.com/icing/mod_h2. Как только патч войдёт в основной релиз httpd — переходите на штатный пакет.
Для всех серверов — дополнительная мера. Ограничить память на воркер. Воркер убитый OOM-killer и перезапущенный чистым — лучше чем машина в swap под контролем атакующего:
# /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitAS=2G
systemctl daemon-reload && systemctl restart nginx
IIS, Envoy, Cloudflare Pingora — патчей нет. Отключить HTTP/2 или проксировать через nginx 1.30.x.
ВЫВОДЫ
HTTP/2 Bomb — это не новая техника, это новая комбинация старых техник, которую никто не собрал десять лет. Один домашний компьютер, 100 Мбит/с, несколько секунд — и ваш сервер деградирует под нагрузкой эквивалентной сотням гигабит.
Если вы на nginx 1.30.2 — вы уже защищены, ничего делать не нужно. Если нет — обновление до 1.30.2 через репозиторий nginx.org закрывает сразу три актуальные уязвимости: nginx-rift, CVE-2026-9256 и HTTP/2 Bomb. Одна команда, три проблемы.
