The Ultimate Guide to gRPC Pentesting: Breaking Binary Protocols

The Ultimate Guide to gRPC Pentesting: Breaking Binary Protocols

Modern application security has largely grown up around a familiar set of assumptions: HTTP/1.1 requests, JSON bodies, predictable endpoints, and tooling that can intercept and rewrite traffic without much friction. gRPC breaks many of those assumptions, by design.

gRPC is now a default choice for internal microservice communication and increasingly for public-facing APIs as well. It’s fast, strongly typed, and built on HTTP/2. But that same “high performance, strongly typed, binary protocol” combination creates a blind spot in many pentests and bug bounty workflows. When defenders rely on JSON-aware WAFs and traditional proxy-centric testing, attackers get a quieter lane to probe.

This article provides an end-to-end, practical guide to pentesting gRPC systems, with a focus on the real issues that show up repeatedly in the wild: server reflection exposure, metadata-based bypasses, privilege escalation via deprecated fields (protobuf “mass assignment”), gRPC-Web CORS/CSRF pitfalls, and the uncomfortable truth that many WAFs struggle to inspect what they can’t easily parse.

gRPC traffic looks “weird” if you’re used to REST:

  • It’s HTTP/2 only.
  • Payloads are typically Protocol Buffers (protobuf), not JSON.
  • The contract is defined in .proto files, not OpenAPI/Swagger.
  • Many security tools treat the request body as opaque bytes rather than structured input.

The outcome is predictable: teams test what they can see and manipulate easily, and skip what feels expensive to decode. In real engagements, that means gRPC endpoints can remain lightly tested even when they handle authentication, user management, payments, or admin functionality.

A useful mental model is this:

  • A REST API with a publicly accessible Swagger UI is usually treated as “high visibility” and therefore gets attention.
  • A gRPC service with reflection enabled can provide a similar level of insight, sometimes even more, but is often overlooked.

If you find a gRPC service with server reflection enabled, you may be able to enumerate service names, RPC methods, and message types in seconds. That’s not automatically a vulnerability, but it is a major accelerant for an attacker.

The Security Shift: How gRPC Differs from REST

Before testing, it helps to understand the security “shift” gRPC introduces:

Transport: The Impact of HTTP/2 Semantics

Because gRPC runs over HTTP/2, the networking layer (proxies, load balancers, gateways, WAFs) must properly support HTTP/2 semantics to handle, route, and inspect calls. Misconfigurations here can lead to:

  • Incorrect routing decisions (especially if metadata headers are trusted too much)
  • Security controls that only partially apply (e.g., policy enforcement built for HTTP/1.1 assumptions)

Serialization: The Binary Protobuf Hurdle

JSON payloads are easy for WAFs and logging tools to parse. Protobuf payloads are compact and binary. That has two major security implications:

  1. Security monitoring often becomes “header-focused” because the body is harder to interpret.
  2. Signature-based inspection can become ineffective if the body isn’t decoded.

Schema: Using .proto as Your Attack Blueprint

A .proto file is not just documentation. It’s the contract that defines:

  • Services and methods (your endpoint map)
  • Input/output message structures (your parameter map)
  • Field numbers and types (what you can inject, and where)

A realistic gRPC service might include methods like GetUser, UpdateUser, and an admin-only action such as AdminBulkDelete. If you can obtain the schema, via reflection or other means, you can test systematically instead of blindly.

// Example of a vulnerable .proto schema
syntax = "proto3";
package user.v1;

service UserService {
  rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse);
}

message UpdateUserRequest {
  string user_id   = 1;
  string username  = 2;
  bool is_admin    = 3 [deprecated = true];  // ← DANGEROUS: still processed by backend! [cite: 25]
}

The Pentester’s Arsenal: Essential gRPC Tooling

If you approach gRPC with the same tooling you use for REST, you’ll be fighting your tools.

A practical baseline includes:

  • grpcurl: effectively “curl for gRPC”, great for enumeration and calling methods.
  • grpcui: a web UI that can make exploration faster once you have a schema.
  • buf: useful for protobuf workflows (linting/building schemas in real projects).
  • protoscope: helpful when you need to inspect raw protobuf frames at a low level.

Burp Suite: workable, but not “out of the box”

Burp can proxy HTTP/2, but it won’t magically decode protobuf. For gRPC-Web, an extension such as gRPC-Web Coder can make traffic human-readable and editable.

For native gRPC (not gRPC-Web), you typically end up using grpcurl/grpcui for direct method calls, and Burp primarily for observing/altering headers, testing gateways, and analyzing gRPC-Web behavior.

Phase 1: Reconnaissance & Server Reflection Abuse

gRPC services frequently live on ports that aren’t “classic web” ports. Common ports include 50051, 50052, 9090, 8080, and sometimes 443. Basic reconnaissance can include HTTP/2 detection and service fingerprinting to identify candidates.

gRPC Server Reflection allows clients to query the server for available services and method descriptions at runtime. This is incredibly helpful in development, and frequently too helpful in production.

With reflection enabled, you can often:

  • List exposed services
  • Describe methods and message shapes
  • Dump the full schema for offline analysis
# 1. Check if reflection is enabled
grpcurl -plaintext target.com:50051 list

# 2. Enumerate methods for a specific service
grpcurl -plaintext target.com:50051 describe user.v1.UserService

# 3. Dump the full schema for offline analysis
grpcurl -plaintext target.com:50051 describe > full_schema.txt 2>&1

From a security perspective, reflection is not always a direct vulnerability. But it dramatically reduces the effort required to find:

  • hidden admin methods,
  • sensitive fields,
  • and dangerous legacy behaviors.

If reflection is disabled, schema discovery becomes harder, but not impossible. Schemas can leak through gRPC-Web JavaScript bundles, compiled binaries (via strings extraction), error responses, or simply via iterative fuzzing.

Discovering hidden administrative endpoints. By querying the exposed ServerReflection service, we instantly extract the .proto schema and identify the highly sensitive AdminListAllServices method, all without authentication

Phase 2: Metadata Injection & Auth Bypasses

gRPC metadata is conceptually similar to HTTP headers: key-value pairs attached to calls. In many real systems, metadata carries authentication tokens, routing info, user context, and internal flags.

This creates an immediate and familiar attack surface: header trust issues.

Common tests include injecting headers that some internal component might wrongly trust, such as:

  • x-forwarded-for: 127.0.0.1 (IP allowlist bypass attempts)
  • “internal request” markers like x-internal: true
  • custom headers used by gateways for identity propagation

A recurring problem is when upstream proxies or gateways set these headers, and backend services assume they are always truthful. If an attacker can hit the service directly (or the gateway doesn’t strip/overwrite untrusted metadata), those assumptions break.

If JWTs are passed via metadata, the usual JWT failure modes can still apply (weak validation, algorithm confusion, misuse of claims, improper audience checks, and so on). gRPC doesn’t make JWT safer; it just moves where the token is carried.

Phase 3: Privilege Escalation via Deprecated Fields

One of the most practical and severe gRPC vulnerabilities comes from a misunderstanding:

In protobuf, marking a field as [deprecated = true] is a signal to developers and code generators. It is not a security control.

If a backend handler still reads and acts on deprecated fields, you can often reintroduce parameters that the UI stopped sending months ago. That’s the gRPC equivalent of a classic mass assignment bug.

A typical example:

  • The UI no longer sends is_admin or role_level because the frontend removed those options.
  • The server still deserializes those fields and may apply them if present.
  • An attacker who knows the schema can send those fields anyway.

This is especially dangerous in “Update” style methods (UpdateUser, UpdateProfile, UpdateAccount) where developers may have historically allowed privileged fields and later “hid” them.

What to test:

  • Any update request with sensitive flags, roles, limits, account tiers, permissions, or ownership fields.
  • Fields marked deprecated, renamed, or “legacy” in schema comments.
  • Any server-side logic that merges request objects into database models without strict allowlists.

Mitigation is straightforward conceptually: server-side authorization and field-level allowlisting. But the vulnerability persists because teams mistakenly treat “deprecated” as “ignored.”

Phase 4: Bypassing WAFs with Binary Protobuf Encoding

Many WAF deployments are optimized for JSON/URL-encoded bodies. When the request body becomes a protobuf binary stream, inspection can degrade sharply:

  • Signature-based detection becomes unreliable if the WAF cannot decode the message.
  • Logging and security analytics may lose visibility into user-controlled parameters.
  • Defensive teams may over-rely on “we have a WAF” without confirming it meaningfully inspects gRPC payloads.

This doesn’t mean SQL injection or command injection magically becomes possible. It means the same injection strings may reach the backend with fewer layers of scrutiny.

A practical testing approach is to inject classic payloads into string fields via grpcurl and observe:

  • error messages,
  • timing anomalies (e.g., sleep-based payloads),
  • differences between REST gateway vs direct gRPC access.

A related real-world pattern is “allowlisting” specific gRPC-Web user agents or headers. If a WAF trusts a header such as a gRPC-Web SDK identifier, spoofing it can change the security posture of the request, sometimes drastically.

Phase 5: Exposing the gRPC-Web CSRF Myth

gRPC-Web exists to let browsers call gRPC-like endpoints. It typically uses HTTP requests that carry a framed payload and special headers like X-Grpc-Web.

The risky assumption some teams make is: “It’s binary, so CSRF won’t work.”

In reality, CSRF is about browser behavior, not human readability.

An attacker can craft a request using fetch() and send bytes (for example, as a Uint8Array). Under certain conditions, the request can be made to look like a “simple request” (e.g., using text/plain as a content type), which can avoid a CORS preflight. If the server’s CORS configuration is permissive, especially if it reflects Origin and allows credentials, then authenticated cross-site calls become feasible.

<script>
async function grpcCsrfAttack() {
  // 5-byte header + protobuf payload serialized as Uint8Array
  // Bypasses CORS preflight by using text/plain 
  const frame = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x07, 0x0A, 0x05, 0x31, 0x32, 0x33, 0x34, 0x35]);
  
  await fetch('https://target.com/user.v1.UserService/GetUser', {
    method: 'POST',
    credentials: 'include', // Sends victim's session cookies 
    headers: {
      'Content-Type': 'text/plain', 
      'X-Grpc-Web': '1',
    },
    body: frame
  });
}
grpcCsrfAttack();
</script>

What to test in gRPC-Web contexts:

  • Does the server reflect arbitrary Origin values?
  • Is Access-Control-Allow-Credentials: true set?
  • Are “simple request” paths possible without preflight?
  • Are cookies used for session auth, making CSRF materially impactful?

The combination of “credentials included” + permissive CORS is where gRPC-Web can become as CSRF-prone as any other browser-consumable API.

Phase 6: Streaming Endpoint Abuse

Streaming Endpoint Abuse: IDOR and DoS

gRPC supports server-streaming, client-streaming, and bidirectional streaming. Server-streaming endpoints are frequently vulnerable to Insecure Direct Object Reference (IDOR) because developers apply authorization only on the initial request, not on each streamed response.

Streaming IDOR: If an endpoint like ListUsersStream iterates through records, test if you can request another user's stream by manipulating the user_id parameter.

Stream Exhaustion (DoS): Streaming endpoints are highly vulnerable to resource exhaustion if the server lacks backpressure and rate limiting. Opening dozens of concurrent, persistent HTTP/2 streams can easily exhaust server memory and threads without triggering traditional volumetric rate limits.

A Practical Workflow for Real-World Engagements

When approaching a target with gRPC, a disciplined workflow helps you avoid getting lost in tooling:

  1. Identify gRPC endpoints (ports, gateways, service meshes, ingress configs).
  2. Check for reflection:
    • If enabled, enumerate services/methods and dump schema.
    • If disabled, hunt for schema leaks (web bundles, binaries, errors).
  3. Build a method-by-method test plan:
    • Auth boundaries (unauth vs auth, user vs admin)
    • Input validation (especially string fields)
    • Object-level authorization (IDOR patterns)
  4. Focus on high-yield gRPC-specific issues:
    • Metadata trust and bypasses
    • Deprecated/legacy fields that alter privilege or ownership
    • gRPC-Web CORS/CSRF misconfigurations
    • WAF visibility gaps for binary payloads
  5. Validate exploitability with controlled proofs:
    • Demonstrate unauthorized enumeration, unauthorized action, or privilege elevation.
    • Include evidence from server responses, timing, or state changes.

Remediation

From a defender’s perspective, the common fixes are not exotic, they’re often the same principles as REST, but applied correctly in a gRPC ecosystem:

  • Disable reflection in production unless there’s a strong reason to keep it on, and restrict access when enabled.
  • Treat metadata as untrusted input unless it is set by a controlled, authenticated gateway that strips attacker-supplied values.
  • Implement strict server-side authorization and field allowlists, especially for update methods.
  • Confirm WAF and logging visibility: if you cannot decode protobuf bodies, you may not be inspecting or alerting on what matters.
  • For gRPC-Web, review CORS rigorously:
    • Avoid reflecting Origin.
    • Avoid allowing credentials unless necessary.
    • Ensure preflight behavior is correct and enforced.
  • Build security testing muscle for gRPC so it doesn’t remain the “binary thing we skip.”

Conclusion

gRPC isn’t insecure. But it changes the defaults that many security programs quietly rely on: easy inspection, mature proxy tooling, and “WAF coverage” that assumes JSON. Attackers don’t need gRPC to be inherently vulnerable, they just need it to be less observed and less tested.

If you’re a pentester, the opportunity is clear: treat gRPC services as first-class citizens in your methodology. If you’re a defender, the message is equally clear: make sure your security controls, authorization, validation, monitoring, and CORS policies, apply just as strongly to binary protocols as they do to REST.

When you bring gRPC into your threat model with the same seriousness as everything else, it stops being a blind spot, and starts being just another system you can secure.

References & Further Reading

Documentation & Basics

Research & Pentesting Articles

Read more