hacktricks/pentesting-web/h2c-smuggling.md

103 lines
9.5 KiB
Markdown
Raw Normal View History

2022-06-19 13:37:58 +00:00
# Upgrade Header Smuggling
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<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>
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
- Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
- Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
- Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
- **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
- **Partagez vos astuces de piratage en soumettant des PR au [repo hacktricks](https://github.com/carlospolop/hacktricks) et au [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
2022-04-28 16:01:33 +00:00
</details>
2022-06-19 13:37:58 +00:00
## H2C Smuggling <a href="#http2-over-cleartext-h2c" id="http2-over-cleartext-h2c"></a>
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
### HTTP2 sur texte clair (H2C) <a href="#http2-over-cleartext-h2c" id="http2-over-cleartext-h2c"></a>
2023-06-03 13:10:46 +00:00
Une connexion HTTP normale dure généralement seulement pendant la durée d'une seule requête. Cependant, H2C ou "**http2 sur texte clair**" est là où une connexion http transitoire normale est mise à niveau vers une connexion persistante qui utilise le protocole binaire http2 pour communiquer en continu au lieu d'une seule requête en utilisant le protocole http en texte clair.
2023-06-03 13:10:46 +00:00
La deuxième partie de la contrebande se produit lorsqu'un **proxy inverse est utilisé**. Normalement, lorsque des requêtes http sont effectuées vers un proxy inverse, le proxy gère la requête, traite une série de règles de routage, puis transfère la requête vers l'arrière-plan et renvoie ensuite la réponse. Lorsqu'une requête http inclut un en-tête `Connection: Upgrade`, comme pour une connexion websocket, le proxy inverse maintiendra la connexion persistante entre le client et le serveur, permettant la communication continue nécessaire pour ces protocoles. Pour une connexion H2C, le RFC exige que 3 en-têtes soient présents :
```
Upgrade: h2c
HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
Connection: Upgrade, HTTP2-Settings
```
2023-06-03 13:10:46 +00:00
Où se trouve la faille ? **Lors de la mise à niveau d'une connexion, le proxy inverse cessera souvent de traiter les demandes individuelles**, en supposant que une fois la connexion établie, son travail de routage est terminé. En utilisant H2C Smuggling, nous pouvons contourner les règles qu'un proxy inverse utilise lors du traitement des demandes telles que le routage basé sur le chemin, l'authentification ou le traitement WAF, à condition que nous puissions établir une connexion H2C en premier.
![](<../.gitbook/assets/image (454).png>)
2023-06-03 13:10:46 +00:00
### Proxies vulnérables <a href="#exploitation" id="exploitation"></a>
2022-06-19 13:37:58 +00:00
2023-06-03 13:10:46 +00:00
Notez dans l'explication de la vulnérabilité que le serveur proxy doit **transférer l'en-tête Upgrade**, et parfois l'en-tête **Connection** doit également être transféré avec succès.
2022-06-19 13:37:58 +00:00
2023-06-03 13:10:46 +00:00
Par défaut, les services suivants **transfèrent** les en-têtes **Upgrade** et **Connection** lors de la transmission par proxy, permettant ainsi la contrebande h2c dès la sortie de la boîte :
2022-06-19 13:37:58 +00:00
* HAProxy
* Traefik
* Nuster
2023-06-03 13:10:46 +00:00
Par défaut, ces services ne transfèrent pas les en-têtes Upgrade et Connection lors de la transmission par proxy, mais **peuvent être configurés de manière non sécurisée** (en passant des en-têtes Upgrade et Connection non filtrés) :
2022-06-19 13:37:58 +00:00
* AWS ALB/CLB
* NGINX
* Apache
* Squid
* Varnish
* Kong
* Envoy
* Apache Traffic Server
### Exploitation <a href="#exploitation" id="exploitation"></a>
2023-06-03 13:10:46 +00:00
Le billet de blog original souligne que tous les serveurs ne transféreront pas les en-têtes requis pour une mise à niveau de connexion H2C conforme. Cela signifie que les équilibreurs de charge tels que AWS ALB/CLB, NGINX et Apache Traffic Server, entre autres, **empêcheront une connexion H2C par défaut**. Cependant, à la fin du billet de blog, il mentionne que « tous les backends n'étaient pas conformes, et nous pouvions **tester avec la variante non conforme `Connection: Upgrade`, où la valeur `HTTP2-Settings` est omise de l'en-tête `Connection`** ».
2022-06-19 13:37:58 +00:00
{% hint style="danger" %}
2023-06-03 13:10:46 +00:00
Notez que même si l'URL de `proxy_pass` (le point final vers lequel le proxy transfère la connexion) pointait vers un **chemin** spécifique tel que `http://backend:9999/socket.io`, la connexion sera établie avec `http://backend:9999`, vous pouvez donc **contacter tout autre chemin à l'intérieur de ce point final interne en abusant de cette technique. Il n'est donc pas important qu'un chemin soit spécifié dans l'URL de proxy\_pass.**
2022-06-19 13:37:58 +00:00
{% endhint %}
2023-06-03 13:10:46 +00:00
En utilisant les outils [**https://github.com/BishopFox/h2csmuggler**](https://github.com/BishopFox/h2csmuggler) **et** [**https://github.com/assetnote/h2csmuggler**](https://github.com/assetnote/h2csmuggler), vous pouvez essayer de **contourner les protections imposées** par le proxy en établissant une connexion H2C et accéder aux ressources protégées par le proxy.
2023-06-03 13:10:46 +00:00
Suivez ce lien pour [**plus d'informations sur cette vulnérabilité dans Nginx**](../network-services-pentesting/pentesting-web/nginx.md#proxy\_set\_header-upgrade-and-connection).
2022-04-28 16:01:33 +00:00
2023-06-03 13:10:46 +00:00
## Contrebande de WebSocket
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
Similaire à la technique précédente, celle-ci **au lieu de créer un tunnel HTTP2** vers un point final accessible via un proxy, elle créera un **tunnel WebSocket** à la même fin, **contournant les limitations potentielles des proxies** et communiquant directement avec le point final :
2022-06-19 13:58:11 +00:00
2022-06-27 08:48:17 +00:00
![](<../.gitbook/assets/image (651) (2) (1).png>)
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
### Scénario 1
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
Nous avons un backend qui expose une **API WebSocket publique** et a également une **API REST interne non disponible** de l'extérieur. Un client malveillant veut accéder à l'API REST interne.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
À la **première** étape, le client envoie une **demande de mise à niveau** au proxy inverse, mais avec une **mauvaise version de protocole** dans l'en-tête `Sec-WebSocket-Version`. Le **proxy** ne valide pas l'en-tête `Sec-WebSocket-Version` et pense que la **demande de mise à niveau est correcte**. Ensuite, il traduit la demande vers le backend.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
À la deuxième étape, le backend envoie une **réponse avec le code d'état `426` car la version du protocole est incorrecte** dans l'en-tête `Sec-WebSocket-Version`. Cependant, **le proxy inverse ne vérifie pas** suffisamment la réponse du backend (y compris le code d'état) et **pense que le backend est prêt pour la communication WebSocket**. Ensuite, il traduit la demande vers le client.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
Enfin, le **proxy inverse pense** que la **connexion WebSocket est établie entre le client et le backend**. En réalité, il n'y a pas de connexion WebSocket - le backend a refusé la demande de mise à niveau. En même temps, le proxy inverse maintient la connexion TCP ou TLS entre le client et le backend en état ouvert. **Le client peut facilement accéder à l'API REST privée en envoyant une requête HTTP sur la connexion.**
2022-06-19 13:58:11 +00:00
![](https://github.com/0ang3el/websocket-smuggle/raw/master/img/2-4.png)
2023-06-03 13:10:46 +00:00
Il a été constaté que les reverse proxies suivants sont affectés :
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
* Varnish - l'équipe a refusé de corriger le problème décrit.
* Envoy proxy 1.8.0 (ou plus ancien) - dans les versions plus récentes, le mécanisme de mise à niveau a été modifié.
* Autres - À déterminer.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
### Scénario 2
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
La majorité des reverse proxies (par exemple NGINX) **vérifient le code d'état du backend** pendant la partie de poignée de main. Cela rend l'attaque plus difficile mais pas impossible.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
Observons le deuxième scénario. Nous avons un backend qui expose une API WebSocket publique et une API REST publique pour la vérification de l'état de santé et a également une **API REST interne non disponible** de l'extérieur. Un client malveillant veut accéder à l'API REST interne. NGINX est utilisé comme proxy inverse. L'API WebSocket est disponible sur le chemin `/api/socket.io/` et l'API de vérification de l'état de santé sur le chemin `/api/health`.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
L'API de vérification de l'état de santé est invoquée en envoyant une requête POST, le paramètre portant le nom `u` contrôle l'URL. Le backend atteint la ressource externe et renvoie le code d'état au client.
2022-06-19 13:58:11 +00:00
2023-06-03 13:10:46 +00:00
À la **première** étape, le client envoie une requête POST pour invoquer **l'API de vérification de l'état de santé mais avec un en-tête HTTP supplémentaire `Upgrade: websocket`**. NGINX pense qu'il s'agit d'une **demande de mise à niveau normale**, il ne recherche que l'en-tête `Upgrade` en ignorant les autres parties de la demande. Ensuite, le proxy traduit la demande vers le backend.
2022-06-19 13:37:58 +00:00
2023-06-03 13:10:46 +00:00
À la **deuxième** étape, le backend invoque l'API de vérification de l'état de santé. Il atteint la ressource externe contrôlée par des utilisateurs malveillants qui renvoie une **réponse HTTP avec le code d'état `101