9.8 KiB
Actualización de Header Smuggling
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
-
Descubre The PEASS Family, nuestra colección exclusiva de NFTs
-
Obtén el swag oficial de PEASS y HackTricks
-
Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
-
Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.
H2C Smuggling
HTTP2 sobre texto claro (H2C)
Una conexión HTTP normalmente dura solo durante la duración de una sola solicitud. Sin embargo, H2C o "http2 sobre texto claro" es donde una conexión http transitoria normal se actualiza a una conexión persistente que utiliza el protocolo binario http2 para comunicarse continuamente en lugar de una solicitud utilizando el protocolo http en texto plano.
La segunda parte del smuggling ocurre cuando se utiliza un proxy inverso. Normalmente, cuando se realizan solicitudes http a un proxy inverso, el proxy manejará la solicitud, procesará una serie de reglas de enrutamiento, luego reenviará la solicitud al backend y luego devolverá la respuesta. Cuando una solicitud http incluye un encabezado Connection: Upgrade
, como para una conexión websocket, el proxy inverso mantendrá la conexión persistente entre el cliente y el servidor, lo que permite la comunicación continua necesaria para estos protocolos. Para una conexión H2C, el RFC requiere que estén presentes 3 encabezados:
Upgrade: h2c
HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
Connection: Upgrade, HTTP2-Settings
¿Dónde está el error? Al actualizar una conexión, el proxy inverso a menudo dejará de manejar solicitudes individuales, asumiendo que una vez que se ha establecido la conexión, su trabajo de enrutamiento está hecho. Usando H2C Smuggling, podemos evitar las reglas que un proxy inverso usa al procesar solicitudes, como el enrutamiento basado en la ruta, la autenticación o el procesamiento de WAF, siempre que podamos establecer una conexión H2C primero.
Proxies Vulnerables
Tenga en cuenta que, según la explicación de la vulnerabilidad, el servidor proxy necesita reenviar el encabezado Upgrade, y a veces también es necesario reenviar el encabezado Connection con éxito.
Por defecto, los siguientes servicios sí reenvían Upgrade y Connection headers durante el proxy-pass, lo que permite la h2c smuggling de manera predeterminada:
- HAProxy
- Traefik
- Nuster
Por defecto, estos servicios no reenvían ambos encabezados Upgrade y Connection durante el proxy-pass, pero se pueden configurar de manera insegura (pasando encabezados Upgrade y Connection sin filtrar):
- AWS ALB/CLB
- NGINX
- Apache
- Squid
- Varnish
- Kong
- Envoy
- Apache Traffic Server
Explotación
La publicación original del blog señala que no todos los servidores reenviarán los encabezados necesarios para una actualización de conexión H2C compatible. Esto significa que los equilibradores de carga como AWS ALB/CLB, NGINX y Apache Traffic Server, entre otros, impedirán una conexión H2C por defecto. Sin embargo, al final de la publicación del blog, menciona que "no todos los backends eran compatibles, y podríamos probar con la variante no compatible Connection: Upgrade
, donde se omite el valor HTTP2-Settings
del encabezado Connection
".
{% hint style="danger" %}
Tenga en cuenta que incluso si la URL de proxy_pass
(el punto final al que el proxy reenvía la conexión) apuntaba a una ruta específica, como http://backend:9999/socket.io
, la conexión se establecerá con http://backend:9999
, por lo que puede contactar cualquier otra ruta dentro de ese punto final interno abusando de esta técnica. Por lo tanto, no importa si se especifica una ruta en la URL de proxy_pass.
{% endhint %}
Usando las herramientas https://github.com/BishopFox/h2csmuggler y https://github.com/assetnote/h2csmuggler, puede intentar evadir las protecciones impuestas por el proxy estableciendo una conexión H2C y acceder a los recursos protegidos por el proxy.
Siga este enlace para obtener más información sobre esta vulnerabilidad en Nginx.
Smuggling de Websocket
Similar a la técnica anterior, esta en lugar de crear un túnel HTTP2 a un punto final accesible a través de un proxy, creará un túnel Websocket con el mismo propósito, evadiendo las limitaciones potenciales de los proxies y hablando directamente con el punto final:
Escenario 1
Tenemos un backend que expone una API WebSocket pública y también tiene una API REST interna no disponible desde el exterior. Un cliente malintencionado quiere acceder a la API REST interna.
En el primer paso, el cliente envía una solicitud de actualización al proxy inverso, pero con una versión de protocolo incorrecta dentro del encabezado Sec-WebSocket-Version
. El proxy no valida el encabezado Sec-WebSocket-Version
y cree que la solicitud de actualización es correcta. Luego, traduce la solicitud al backend.
En el segundo paso, el backend envía una respuesta con el código de estado 426
porque la versión del protocolo es incorrecta dentro del encabezado Sec-WebSocket-Version
. Sin embargo, el proxy inverso no verifica suficientemente la respuesta del backend (incluido el código de estado) y cree que el backend está listo para la comunicación WebSocket. Luego, traduce la solicitud al cliente.
Finalmente, el proxy inverso cree que se ha establecido una conexión WebSocket entre el cliente y el backend. En realidad, no hay una conexión WebSocket: el backend rechazó la solicitud de actualización. Al mismo tiempo, el proxy mantiene la conexión TCP o TLS entre el cliente y el backend en estado abierto. El cliente puede acceder fácilmente a la API REST privada enviando una solicitud HTTP a través de la conexión.
Se descubrió que los siguientes proxies inversos se ven afectados:
- Varnish - el equipo se negó a solucionar el problema descrito.
- Envoy proxy 1.8.0 (o anterior) - en versiones más nuevas, el mecanismo de actualización ha cambiado.
- Otros - TBA.
Escenario 2
La mayoría de los proxies inversos (por ejemplo, NGINX) verifican el código de estado del backend durante la parte de handshake. Esto hace que el ataque sea más difícil pero no imposible.
Observemos el segundo escenario. Tenemos un backend que expone una API WebSocket pública y una API REST pública para la comprobación de salud y también tiene una API REST interna no disponible desde el exterior. Un cliente malintencionado quiere acceder a la API REST interna. Se utiliza NGINX como proxy inverso. La API WebSocket está disponible en la ruta /api/socket.io/
y la API de comprobación de salud en la ruta /api/health
.
La API de comprobación de salud se invoca enviando una solicitud POST, el parámetro con el nombre u
controla la URL. El backend alcanza el recurso externo y devuelve el código de estado al cliente.
En el primer paso, el cliente envía una solicitud POST para invocar la API de comprobación de salud pero con un encabezado HTTP adicional Upgrade: websocket
. NGINX cree que es una solicitud de actualización normal, solo busca el encabezado Upgrade
omitiendo otras partes de la solicitud. Luego, el proxy traduce la solicitud al backend.
En el segundo paso, el backend invoca la API de comprobación de salud. Alcanza el recurso externo controlado por usuarios malintencionados que devuelve una respuesta HTTP con el código de estado 101
. El backend traduce esa respuesta al proxy inverso. Dado que NGINX valida solo el código de estado, creerá que el backend está listo para la comunicación WebSocket. Luego, traduce la solicitud al cliente.
{% hint style="warning" %} Observe cómo este escenario es mucho más complejo de explotar, ya que debe poder contactar algún punto final que devuelva el código de estado 101. {% endhint %}
Finalmente, **NGINX cree que se ha establecido