Breachwire.riscent

Breach report

GraphQL batching and introspection: when flexibility becomes attack surface

Web Application BreachesHigh (rate-limit bypass, schema disclosure)2024-01
The bottom lineGraphQL's introspection and aliasing features, left unrestricted, leak the full schema and let a single request pack many operations — defeating rate limits and enabling brute-force of authentication codes and other secrets.
Category
Web Application Breaches
Type
Vulnerability class · API design abuse
Date
2024-01
Severity
High (rate-limit bypass, schema disclosure)
OWASP
Web A01 Broken Access Control
CWE / CVE
CWE-799 / CWE-307

What happened

This is a vulnerability class rooted in how GraphQL APIs are commonly configured, not a single company's breach. PortSwigger's Web Security Academy documents two recurring failure patterns. First, introspection — a built-in feature that lets a client query the server for its entire schema — when left enabled in production, exposes the full API structure, including sensitive or hidden fields. Second, aliasing and batching: because aliases let a client pack many operations into one HTTP request, rate limiters that count *requests* rather than *operations* can be defeated, letting an attacker "brute-force authentication codes or discount codes at scale." GraphQL endpoints that accept GET or form-encoded POST requests are additionally exposed to CSRF.

The through-line is that convenience features designed for developers double as reconnaissance and throughput tools for attackers.

Root cause

Two weaknesses combine. Improper control of interaction frequency (CWE-799) lets aliased/batched operations bypass request-counting rate limits, enabling improper restriction of excessive authentication attempts (CWE-307) — brute force. Unrestricted introspection is an information-exposure problem that hands attackers the schema map. Both fall under OWASP's Broken Access Control and related API-security concerns: the server enforces limits and disclosure controls at the wrong granularity.

How it would have been caught

An API security test that sends a single batched request with many aliased login attempts and asserts the rate limiter still blocks it would fail against a naive per-request limiter. An introspection query (__schema) fired at production and expected to be refused reveals whether the schema is exposed. A reproduction packs N authentication guesses into one request and confirms all N are processed.

How to prevent it

  • Disable introspection on production/private APIs.
  • Rate-limit by operation and cost, not by HTTP request; add query-depth, complexity, and batch-size limits.
  • Enforce per-account attempt limits on sensitive operations so batching cannot amplify brute force; require JSON POST and CSRF protection.

The Breachwire test (red → green)

Send one request containing many aliased authentication attempts and confirm the rate limiter processes all of them; fire an introspection query and confirm the schema is returned — the RED controls. Add operation-level rate limiting with depth/batch caps and disable introspection, then confirm the batched attempts are throttled and introspection is refused while legitimate queries still work.