API Security
🔥 Advanced
API8

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:

bash
grpcurl -plaintext localhost:50051 list
grpcurl -plaintext localhost:50051 list

List services:

bash
grpcurl -plaintext localhost:50051 list
grpcurl -plaintext localhost:50051 list

Describe a service:

bash
grpcurl -plaintext localhost:50051 describe grpc.reflection.v1alpha.ServerReflection
grpcurl -plaintext localhost:50051 describe grpc.reflection.v1alpha.ServerReflection

Without 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.

bash
grpcurl -plaintext -d '{"id": 1}' localhost:50051 com.example.UserService/GetUser
grpcurl -plaintext -d '{"id": 1}' localhost:50051 com.example.UserService/GetUser

Intercepting 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.

bash
grpcui -plaintext localhost:50051
grpcui -plaintext localhost:50051

Protobuf 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).

bash
# 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/GetUser

Intercepting gRPC in Burp

Install the blackboxprotobuf Burp extension to decode and re-encode Protobuf messages inline. Set the proxy to intercept HTTP/2 traffic and configure the target app to trust your Burp CA. Alternatively, use 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.

bash
# 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/StreamAll

Authentication & mTLS Testing

gRPC services often use mTLS or JWT metadata for authentication. Test for missing or weak enforcement.

JWT in gRPC Metadata

gRPC uses metadata headers (similar to HTTP headers) for auth tokens. Test if the service validates them.

bash
# Call with valid JWT in metadata
grpcurl -plaintext \
  -H "Authorization: Bearer eyJhbGciOi..." \
  -d '{"user_id": 1}' localhost:50051 UserService/GetProfile

# Call WITHOUT auth — does it still work?
grpcurl -plaintext -d '{"user_id": 1}' localhost:50051 UserService/GetProfile

# Tampered JWT (change role claim)
grpcurl -plaintext \
  -H "Authorization: Bearer TAMPERED_TOKEN" \
  -d '{"user_id": 1}' localhost:50051 UserService/GetProfile
# Call with valid JWT in metadata
grpcurl -plaintext \
  -H "Authorization: Bearer eyJhbGciOi..." \
  -d '{"user_id": 1}' localhost:50051 UserService/GetProfile

# Call WITHOUT auth — does it still work?
grpcurl -plaintext -d '{"user_id": 1}' localhost:50051 UserService/GetProfile

# Tampered JWT (change role claim)
grpcurl -plaintext \
  -H "Authorization: Bearer TAMPERED_TOKEN" \
  -d '{"user_id": 1}' localhost:50051 UserService/GetProfile

mTLS Certificate Testing

If mTLS is required, test whether the server validates the client certificate properly.

bash
# Connect with client certificate
grpcurl -cert client.crt -key client.key -cacert ca.crt \
  target:443 list

# Test with self-signed cert (should be rejected)
openssl req -x509 -newkey rsa:2048 -keyout fake.key -out fake.crt -days 1 -nodes -subj "/CN=attacker"
grpcurl -cert fake.crt -key fake.key -cacert ca.crt \
  target:443 list

# Test without any cert (should fail if mTLS enforced)
grpcurl -cacert ca.crt target:443 list
# Connect with client certificate
grpcurl -cert client.crt -key client.key -cacert ca.crt \
  target:443 list

# Test with self-signed cert (should be rejected)
openssl req -x509 -newkey rsa:2048 -keyout fake.key -out fake.crt -days 1 -nodes -subj "/CN=attacker"
grpcurl -cert fake.crt -key fake.key -cacert ca.crt \
  target:443 list

# Test without any cert (should fail if mTLS enforced)
grpcurl -cacert ca.crt target:443 list

Metadata Injection

gRPC metadata headers can be target vectors for injection if the server processes them as database queries or commands.

bash
# Inject SQL via metadata  
grpcurl -plaintext \
  -H "X-User-Id: 1' OR 1=1--" \
  -d '{}' localhost:50051 UserService/ListUsers

# Inject via gRPC deadline metadata (unusual vector)
grpcurl -plaintext \
  -H "grpc-timeout: 999999999n" \
  -d '{"query": "*"}' localhost:50051 DataService/Search
# Inject SQL via metadata  
grpcurl -plaintext \
  -H "X-User-Id: 1' OR 1=1--" \
  -d '{}' localhost:50051 UserService/ListUsers

# Inject via gRPC deadline metadata (unusual vector)
grpcurl -plaintext \
  -H "grpc-timeout: 999999999n" \
  -d '{"query": "*"}' localhost:50051 DataService/Search

Service Mesh Considerations

In Kubernetes environments, gRPC services are often behind service meshes like Istio or Linkerd. Test whether sidecar proxies properly enforce authorization policies.

bash
# If you have pod access, try calling services directly (bypassing mesh)
# Find service IPs
kubectl get svc -A | grep grpc

# Direct call bypassing Istio sidecar
grpcurl -plaintext SERVICE_IP:50051 list

# Check if AuthorizationPolicy is enforced
# Try accessing admin services from non-admin namespace pods
# If you have pod access, try calling services directly (bypassing mesh)
# Find service IPs
kubectl get svc -A | grep grpc

# Direct call bypassing Istio sidecar
grpcurl -plaintext SERVICE_IP:50051 list

# Check if AuthorizationPolicy is enforced
# Try accessing admin services from non-admin namespace pods

Remediation

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.
  • Validate enum values server-side — reject undefined values instead of falling through to default behavior.
  • Use service mesh authorization policies (Istio AuthorizationPolicy, Linkerd ServerAuthorization) for defense in depth.
  • Strip or sanitize gRPC metadata headers before passing to backend logic.
🎯

gRPC Security Practice

Practice gRPC service enumeration, Protobuf tampering, and authentication bypass.

🔧
gRPC Damn Vulnerable App Custom Lab hard
Reflection enumerationField tamperingEnum fuzzing
Open Lab
📦
HackTheBox — gRPC Challenges Hack The Box hard
Proto file reconstructionAuth bypassmTLS testing
Open Lab