hacktricks/pentesting-web/h2c-smuggling.md

111 lines
9.8 KiB
Markdown
Raw Normal View History

2023-06-05 18:33:24 +00:00
# Actualización de Header Smuggling
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
- ¿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**](https://github.com/sponsors/carlospolop)!
- Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
- Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
- **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
- **Comparte tus trucos de hacking enviando PR al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
</details>
## H2C Smuggling <a href="#http2-over-cleartext-h2c" id="http2-over-cleartext-h2c"></a>
### HTTP2 sobre texto claro (H2C) <a href="#http2-over-cleartext-h2c" id="http2-over-cleartext-h2c"></a>
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.
![](<../.gitbook/assets/image (454).png>)
### Proxies Vulnerables <a href="#exploitation" id="exploitation"></a>
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 <a href="#exploitation" id="exploitation"></a>
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**](https://github.com/BishopFox/h2csmuggler) **y** [**https://github.com/assetnote/h2csmuggler**](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**](../network-services-pentesting/pentesting-web/nginx.md#proxy\_set\_header-upgrade-and-connection).
## 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:
![](<../.gitbook/assets/image (651) (2) (1).png>)
### 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.**
![](https://github.com/0ang3el/websocket-smuggle/raw/master/img/2-4.png)
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.
![](https://github.com/0ang3el/websocket-smuggle/raw/master/img/3-4.png)
{% 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