gRPC Pentesting
gRPC uses Protocol Buffers (Protobuf) for serialization and HTTP/2 for transport. Testing requires tools that can understand the binary format and interact with the service definitions.
Service Discovery & Reflection
gRPC Reflection allows clients to query the server for the services it exposes.
Using grpcurl
Check if reflection is enabled and list services.
Check if reflection is enabled:
grpcurl -plaintext localhost:50051 listgrpcurl -plaintext localhost:50051 listList services:
grpcurl -plaintext localhost:50051 listgrpcurl -plaintext localhost:50051 listDescribe a service:
grpcurl -plaintext localhost:50051 describe grpc.reflection.v1alpha.ServerReflectiongrpcurl -plaintext localhost:50051 describe grpc.reflection.v1alpha.ServerReflectionWithout Reflection
If reflection is disabled, you need to find the .proto files. Look in mobile app packages, web assets, or public repositories. You can also try to reconstruct them from binary traffic using protoc --decode_raw.
Interacting with gRPC
Invoking Methods
Call methods using grpcurl or Postman.
grpcurl -plaintext -d '{"id": 1}' localhost:50051 com.example.UserService/GetUsergrpcurl -plaintext -d '{"id": 1}' localhost:50051 com.example.UserService/GetUserIntercepting Traffic
Burp Suite requires extensions to handle gRPC traffic effectively.
Burp-gRPC Extension
Allows decoding and encoding of Protobuf messages within Burp.
gRPC-UI
A web-based UI for interacting with gRPC services, similar to Swagger UI.
grpcui -plaintext localhost:50051grpcui -plaintext localhost:50051Protobuf Field Tampering
Protobuf fields are identified by field numbers, not names. If you can identify the encoding, you can inject fields the client would not normally send (undocumented fields, admin flags).
# Decode raw protobuf bytes to inspect field numbers
protoc --decode_raw < captured.bin
# Decode using .proto definition
protoc --decode=com.example.UserRequest user.proto < captured.bin
# Re-encode with added field (e.g., field 99 = admin flag)
echo '08 01 c0 06 01' | xxd -r -p | grpcurl -plaintext \
-d @ localhost:50051 com.example.UserService/GetUser# Decode raw protobuf bytes to inspect field numbers
protoc --decode_raw < captured.bin
# Decode using .proto definition
protoc --decode=com.example.UserRequest user.proto < captured.bin
# Re-encode with added field (e.g., field 99 = admin flag)
echo '08 01 c0 06 01' | xxd -r -p | grpcurl -plaintext \
-d @ localhost:50051 com.example.UserService/GetUserIntercepting gRPC in Burp
mitmproxy with the grpc addon for command-line interception.
Enum Value & Boundary Fuzzing
Protobuf enums are transmitted as integers. Sending values outside the defined enum range may trigger unhandled code paths, crashes, or privilege escalation via undefined behavior.
# Normal request with role=USER (enum value 0)
grpcurl -plaintext -d '{"user_id": 1, "role": 0}' localhost:50051 UserService/GetProfile
# Try enum value 1 (ADMIN), 2 (SUPERADMIN), 99 (undefined)
grpcurl -plaintext -d '{"user_id": 1, "role": 1}' localhost:50051 UserService/GetProfile
grpcurl -plaintext -d '{"user_id": 1, "role": 99}' localhost:50051 UserService/GetProfile
# Server-side streaming — test for resource exhaustion
grpcurl -plaintext -d '{"query": "", "page_size": 99999}' \
localhost:50051 DataService/StreamAll# Normal request with role=USER (enum value 0)
grpcurl -plaintext -d '{"user_id": 1, "role": 0}' localhost:50051 UserService/GetProfile
# Try enum value 1 (ADMIN), 2 (SUPERADMIN), 99 (undefined)
grpcurl -plaintext -d '{"user_id": 1, "role": 1}' localhost:50051 UserService/GetProfile
grpcurl -plaintext -d '{"user_id": 1, "role": 99}' localhost:50051 UserService/GetProfile
# Server-side streaming — test for resource exhaustion
grpcurl -plaintext -d '{"query": "", "page_size": 99999}' \
localhost:50051 DataService/StreamAllRemediation
Defense Strategies
- Disable gRPC Reflection in production environments.
- Enforce TLS (gRPC over HTTPS) to prevent eavesdropping.
- Implement authentication (e.g., mTLS, JWT) for all services.
- Validate all input fields defined in the Protobuf messages.