Pentesting gRPC-Web
Reading time: 9 minutes
tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:
HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
快速协议回顾与攻击面
- 传输:gRPC‑Web 通过代理 (Envoy/APISIX/grpcwebproxy/etc.) 在 HTTP/1.1 或 HTTP/2 上使用浏览器兼容的 gRPC 变体。仅支持 unary 和 server‑streaming 调用。
- 常见的 Content-Types:
- application/grpc-web (binary framing)
- application/grpc-web-text (base64-encoded framing for HTTP/1.1 streaming)
- 帧格式:每个消息前都有一个 5‑byte gRPC 头 (1‑byte flags + 4‑byte length)。在 gRPC‑Web 中,trailers (grpc-status, grpc-message, …) 被作为特殊帧发送在 body 内:首字节设置 MSB (0x80),后跟一个长度和一个 HTTP/1.1‑风格的 header block。
- 常见请求头:x-grpc-web: 1, x-user-agent: grpc-web-javascript/…, grpc-timeout, grpc-encoding。响应通过 grpc-status/grpc-message 在 trailers/body frames 中暴露,并且往往通过 Access-Control-Expose-Headers 供浏览器访问。
- 常见的与安全相关的中间件:
- Envoy grpc_web filter 和 gRPC‑JSON transcoder (HTTP<->gRPC bridge)
- Nginx/APISIX gRPC‑Web plugins
- 代理上的 CORS 策略
这对攻击者意味着:
- 你可以手工构造请求(binary 或 base64 文本),或让工具生成/编码它们。
- 代理上的 CORS 配置错误可能允许跨站点的、已认证的 gRPC‑Web 调用(类似传统的 CORS 问题)。
- JSON transcoding 桥如果 routes/auth 配置错误,可能会无意间将 gRPC 方法暴露为无需认证的 HTTP 端点。
从 CLI 测试 gRPC‑Web
最简单:buf curl(原生支持 gRPC‑Web)
- 通过 reflection 列出方法(如果已启用):
# list methods (uses reflection)
buf curl --protocol grpcweb https://host.tld --list-methods
- 使用 JSON 输入调用方法,自动处理 gRPC‑Web 帧封装和 headers:
buf curl --protocol grpcweb \
-H 'Origin: https://example.com' \
-d '{"field":"value"}' \
https://host.tld/pkg.svc.v1.Service/Method
- 如果 reflection 被禁用,请通过 --schema 提供 schema/descriptor set,或指向本地 .proto 文件。参见 buf help curl。
使用 curl 的原始方式(手动 headers + framed body)
对于二进制模式 (application/grpc-web),发送一个 framed payload(5‑byte 前缀 + protobuf message)。对于文本模式,base64‑encode 该 framed payload。
# 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
提示:当 HTTP/1.1 intermediaries 损坏 binary streaming 时,使用 application/grpc-web-text 强制 base64/text 模式。
检查 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'
- 易受攻击的配置通常会反射任意 Origin 并发送 Access-Control-Allow-Credentials: true,从而允许跨站点的已认证调用。还要检查 Access-Control-Expose-Headers 是否包含 grpc-status、grpc-message(许多部署会为客户端库暴露这些)。
For generic techniques to abuse CORS, check CORS - Misconfigurations & Bypass.
操作 gRPC‑Web payloads
gRPC‑Web 使用 Content-Type: application/grpc-web-text 作为 base64 封装的 gRPC frame 流以实现浏览器兼容性。你可以对 frames 进行 decode/modify/encode 来篡改字段、翻转标志或注入 payloads。
Use the gprc-coder tool (and its Burp extension) to speed up round‑trips.
使用 gGRPC Coder Tool 手动操作
- 对 payload 进行解码:
echo "AAAAABYSC0FtaW4gTmFzaXJpGDY6BVhlbm9u" | python3 grpc-coder.py --decode --type grpc-web-text | protoscope > out.txt
- 编辑解码后的 payload 内容
nano out.txt
2: {"Amin Nasiri Xenon GRPC"}
3: 54
7: {"<script>alert(origin)</script>"}
- 对新的 payload 进行编码
protoscope -s out.txt | python3 grpc-coder.py --encode --type grpc-web-text
- 在 Burp interceptor 中使用输出:
AAAAADoSFkFtaW4gTmFzaXJpIFhlbm9uIEdSUEMYNjoePHNjcmlwdD5hbGVydChvcmlnaW4pPC9zY3JpcHQ+
使用 gRPC‑Web Coder Burp Suite Extension 的手册
You can use gRPC‑Web Coder Burp Suite Extension in gRPC‑Web Pentest Suite which is easier. You can read the installation and usage instruction in its repo.
分析 gRPC‑Web JavaScript 文件
Web apps using gRPC‑Web ship at least one generated JS/TS bundle. Reverse them to extract services, methods, and message shapes.
- 尝试使用 gRPC-Scan 来解析 bundle。
- 查找像 /
. / 这样的 method paths、消息字段编号/类型,以及添加认证头的自定义拦截器。
- 下载 JavaScript gRPC‑Web 文件
- 使用 grpc-scan.py 扫描它:
python3 grpc-scan.py --file main.js
- 分析输出并测试新端点与新服务:
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 |
+--------------+----------------+--------------+
Bridging and JSON transcoding gotchas
许多部署会在 gRPC server 之前放置 Envoy(或类似)proxy:
- grpc_web filter 会将 HTTP/1.1 POSTs 转换为 HTTP/2 gRPC。
- gRPC‑JSON Transcoder 会在存在 .proto options (google.api.http) 时,将 gRPC 方法以 HTTP JSON endpoints 的形式暴露出来。
从 pentesting 的角度:
- 当 transcoder 启用时,尝试直接对 /
. / 发起 application/json 的 HTTP JSON 请求(auth/route 不匹配很常见):
curl -i https://host.tld/pkg.svc.v1.Service/Method \
-H 'Content-Type: application/json' \
-d '{"field":"value"}'
- 检查未知的方法/参数是被拒绝还是被透传。某些配置会将不匹配的路径转发到上游,偶尔会绕过 auth 或请求验证。
- 观察代理添加的 x-envoy-original-path 和相关 headers。信任这些头的上游在代理未能对其进行清理时可能会被滥用。
参考
- Hacking into gRPC‑Web Article by Amin Nasiri
- gRPC‑Web Pentest Suite
- gRPC‑Web protocol notes (PROTOCOL‑WEB.md)
tip
学习和实践 AWS 黑客技术:
HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:
HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
HackTricks