Pentesting gRPC-Web

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Récapitulatif rapide du protocole et attack surface

  • Transport : gRPC‑Web implémente une variante compatible navigateur de gRPC over HTTP/1.1 ou HTTP/2 via un proxy (Envoy/APISIX/grpcwebproxy/etc.). Seuls les appels unary et server‑streaming sont pris en charge.
  • Content-Types que vous verrez :
  • application/grpc-web (trames binaires)
  • application/grpc-web-text (trames encodées en base64 pour le streaming HTTP/1.1)
  • Encodage des trames : chaque message est préfixé par un en‑tête gRPC de 5 octets (1‑octet flags + 4‑octets length). Dans gRPC‑Web, les trailers (grpc-status, grpc-message, …) sont envoyés à l’intérieur du body comme une trame spéciale : premier octet avec le MSB à 1 (0x80) suivi d’une longueur et d’un bloc d’en‑têtes au format HTTP/1.1.
  • En‑têtes de requête courants : x-grpc-web: 1, x-user-agent: grpc-web-javascript/…, grpc-timeout, grpc-encoding. Les réponses exposent grpc-status/grpc-message via des trailers/trames de body et souvent via Access-Control-Expose-Headers pour les navigateurs.
  • Middleware liés à la sécurité souvent présents :
  • Envoy grpc_web filter and gRPC‑JSON transcoder (HTTP<->gRPC bridge)
  • Nginx/APISIX gRPC‑Web plugins
  • Politiques CORS sur le proxy

Ce que cela signifie pour les attaquants :

  • Vous pouvez fabriquer des requêtes manuellement (binaire ou base64 text), ou laisser des outils les générer/encoder.
  • Des erreurs CORS sur le proxy peuvent permettre des appels gRPC‑Web cross‑site authentifiés (similaire aux problèmes classiques de CORS).
  • Les bridges de JSON transcoding peuvent exposer involontairement des méthodes gRPC comme des endpoints HTTP non authentifiés si les routes/auth sont mal configurées.

Tester gRPC‑Web depuis le CLI

Le plus simple : buf curl (parle gRPC‑Web nativement)

  • Lister les méthodes via reflection (si activé) :
# list methods (uses reflection)
buf curl --protocol grpcweb https://host.tld --list-methods
  • Appeler une méthode avec une entrée JSON, gérant automatiquement le framing et les en-têtes gRPC‑Web :
buf curl --protocol grpcweb \
-H 'Origin: https://example.com' \
-d '{"field":"value"}' \
https://host.tld/pkg.svc.v1.Service/Method
  • Si la reflection est désactivée, fournissez un jeu de schémas/descripteurs avec –schema ou pointez vers des fichiers .proto locaux. Voir buf help curl.

Brut avec curl (en-têtes manuels + corps encadré)

Pour le mode binaire (application/grpc-web), envoyez une charge utile encadrée (préfixe de 5 octets + protobuf message). Pour le mode texte, encodez la charge utile encadrée en base64.

# Build a protobuf message, then gRPC-frame it (1 flag byte + 4 length + msg)
# Example using protoscope to compose/edit the message and base64 for grpc-web-text
protoscope -s msg.txt | python3 grpc-coder.py --encode --type grpc-web-text | \
tee body.b64

curl -i https://host.tld/pkg.svc.v1.Service/Method \
-H 'Content-Type: application/grpc-web-text' \
-H 'X-Grpc-Web: 1' \
-H 'X-User-Agent: grpc-web-javascript/0.1' \
--data-binary @body.b64

Astuce : Forcer le mode base64/text avec application/grpc-web-text lorsque les intermédiaires HTTP/1.1 perturbent le streaming binaire.

Vérifier le comportement CORS (preflight + response)

  • Preflight:
curl -i -X OPTIONS https://host.tld/pkg.svc.v1.Service/Method \
-H 'Origin: https://evil.tld' \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type,x-grpc-web,x-user-agent,grpc-timeout'
  • Une configuration vulnérable reflète souvent un Origin arbitraire et renvoie Access-Control-Allow-Credentials: true, permettant des appels authentifiés cross‑site. Vérifiez aussi qu’Access-Control-Expose-Headers inclut grpc-status, grpc-message (de nombreux déploiements exposent ces en-têtes pour les client libs).

Pour des techniques génériques d’abus de CORS, consultez CORS - Misconfigurations & Bypass.

Manipuler les payloads gRPC‑Web

gRPC‑Web utilise Content-Type: application/grpc-web-text comme un flux de frames gRPC encapsulé en base64 pour la compatibilité avec les navigateurs. Vous pouvez décoder/modifier/encoder des frames pour falsifier des champs, inverser des flags ou injecter des payloads.

Utilisez l’outil gprc-coder (et son extension Burp) pour accélérer les allers-retours.

Manuel avec gGRPC Coder Tool

  1. Décoder le payload:
echo "AAAAABYSC0FtaW4gTmFzaXJpGDY6BVhlbm9u" | python3 grpc-coder.py --decode --type grpc-web-text | protoscope > out.txt
  1. Modifier le contenu du decoded payload
nano out.txt
2: {"Amin Nasiri Xenon GRPC"}
3: 54
7: {"<script>alert(origin)</script>"}
  1. Encoder le nouveau payload
protoscope -s out.txt | python3 grpc-coder.py --encode --type grpc-web-text
  1. Utiliser la sortie dans l’intercepteur Burp:
AAAAADoSFkFtaW4gTmFzaXJpIFhlbm9uIEdSUEMYNjoePHNjcmlwdD5hbGVydChvcmlnaW4pPC9zY3JpcHQ+

Manuel avec gRPC‑Web Coder Burp Suite Extension

Vous pouvez utiliser gRPC‑Web Coder Burp Suite Extension dans gRPC‑Web Pentest Suite qui est plus simple. Vous pouvez lire les instructions d’installation et d’utilisation dans son dépôt.

Analyse des fichiers JavaScript gRPC‑Web

Les web apps utilisant gRPC‑Web livrent au moins un bundle JS/TS généré. Reverse‑engineer ces bundles pour extraire les services, méthodes et structures des messages.

  • Essayez d’utiliser gRPC-Scan pour parser les bundles.
  • Cherchez des chemins de méthode comme /./, les numéros/types des champs de message, et des interceptors personnalisés qui ajoutent des auth headers.
  1. Téléchargez le fichier JavaScript gRPC‑Web
  2. Scannez-le avec grpc-scan.py:
python3 grpc-scan.py --file main.js
  1. Analyser les sorties et tester les nouveaux endpoints et services :
Output:
Found Endpoints:
/grpc.gateway.testing.EchoService/Echo
/grpc.gateway.testing.EchoService/EchoAbort
/grpc.gateway.testing.EchoService/NoOp
/grpc.gateway.testing.EchoService/ServerStreamingEcho
/grpc.gateway.testing.EchoService/ServerStreamingEchoAbort

Found Messages:

grpc.gateway.testing.EchoRequest:
+------------+--------------------+--------------+
| Field Name |     Field Type     | Field Number |
+============+====================+==============+
| Message    | Proto3StringField  | 1            |
+------------+--------------------+--------------+
| Name       | Proto3StringField  | 2            |
+------------+--------------------+--------------+
| Age        | Proto3IntField     | 3            |
+------------+--------------------+--------------+
| IsAdmin    | Proto3BooleanField | 4            |
+------------+--------------------+--------------+
| Weight     | Proto3FloatField   | 5            |
+------------+--------------------+--------------+
| Test       | Proto3StringField  | 6            |
+------------+--------------------+--------------+
| Test2      | Proto3StringField  | 7            |
+------------+--------------------+--------------+
| Test3      | Proto3StringField  | 16           |
+------------+--------------------+--------------+
| Test4      | Proto3StringField  | 20           |
+------------+--------------------+--------------+

grpc.gateway.testing.EchoResponse:
+--------------+--------------------+--------------+
|  Field Name  |     Field Type     | Field Number |
+==============+====================+==============+
| Message      | Proto3StringField  | 1            |
+--------------+--------------------+--------------+
| Name         | Proto3StringField  | 2            |
+--------------+--------------------+--------------+
| Age          | Proto3IntField     | 3            |
+--------------+--------------------+--------------+
| IsAdmin      | Proto3BooleanField | 4            |
+--------------+--------------------+--------------+
| Weight       | Proto3FloatField   | 5            |
+--------------+--------------------+--------------+
| Test         | Proto3StringField  | 6            |
+--------------+--------------------+--------------+
| Test2        | Proto3StringField  | 7            |
+--------------+--------------------+--------------+
| Test3        | Proto3StringField  | 16           |
+--------------+--------------------+--------------+
| Test4        | Proto3StringField  | 20           |
+--------------+--------------------+--------------+
| MessageCount | Proto3IntField     | 8            |
+--------------+--------------------+--------------+

grpc.gateway.testing.ServerStreamingEchoRequest:
+-----------------+-------------------+--------------+
|   Field Name    |    Field Type     | Field Number |
+=================+===================+==============+
| Message         | Proto3StringField | 1            |
+-----------------+-------------------+--------------+
| MessageCount    | Proto3IntField    | 2            |
+-----------------+-------------------+--------------+
| MessageInterval | Proto3IntField    | 3            |
+-----------------+-------------------+--------------+

grpc.gateway.testing.ServerStreamingEchoResponse:
+------------+-------------------+--------------+
| Field Name |    Field Type     | Field Number |
+============+===================+==============+
| Message    | Proto3StringField | 1            |
+------------+-------------------+--------------+

grpc.gateway.testing.ClientStreamingEchoRequest:
+------------+-------------------+--------------+
| Field Name |    Field Type     | Field Number |
+============+===================+==============+
| Message    | Proto3StringField | 1            |
+------------+-------------------+--------------+

grpc.gateway.testing.ClientStreamingEchoResponse:
+--------------+----------------+--------------+
|  Field Name  |   Field Type   | Field Number |
+==============+================+==============+
| MessageCount | Proto3IntField | 1            |
+--------------+----------------+--------------+

Pièges liés au bridging et au transcodage JSON

Beaucoup de déploiements placent un proxy Envoy (ou équivalent) devant le serveur gRPC :

  • Le filtre grpc_web traduit les POST HTTP/1.1 en gRPC HTTP/2.
  • Le gRPC‑JSON Transcoder expose les méthodes gRPC en tant qu’endpoints HTTP JSON lorsque des options .proto (google.api.http) sont présentes.

Du point de vue pentesting :

  • Essayez des appels HTTP JSON directs vers /./ avec application/json lorsque un transcoder est activé (les auth/route mismatches sont courants) :
curl -i https://host.tld/pkg.svc.v1.Service/Method \
-H 'Content-Type: application/json' \
-d '{"field":"value"}'
  • Vérifiez si les méthodes/paramètres inconnus sont rejetés ou transmis. Certaines configs transmettent les chemins non appariés upstream, contournant parfois l’auth ou la validation des requêtes.
  • Observez x-envoy-original-path et les en-têtes associés ajoutés par les proxies. Les upstreams qui leur font confiance peuvent être abusés si le proxy n’arrive pas à les assainir.

Références

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks