GraphQL hunting
The schema is the app. Introspection off just means you reconstruct it. node(id), aliases, batch, and hidden mutations skip the UI.
Skill: GraphQL APIs
Ask: Does the operation name or the persisted query id skip the authorization check the HTTP route was supposed to enforce?
Stop: One allowed operation and one denied operation are saved, and suggestions or introspection are labeled as inventory.
Practice the class in the browser: PortSwigger Web Security Academy. The lab is theirs. This page is the stop condition and the disclosures.
Checklists
- GraphQL - The schema is the app. Introspection off just means you reconstruct it.
Disclosures
- A GraphQL tag mutation acted on another user's asset - Insecure direct object reference
Playbooks
- GraphQL Abuse - Enumerate and attack GraphQL: schema recovery, authorization gaps, and resource abuse.
- GraphQL persisted queries - Automatic persisted queries and allow lists only help if an unknown operation is rejected. Authorization still has to run per field and per object after the hash is accepted.
Tools
- Burp Suite - The industry-standard intercepting proxy for manual web testing. Community edition is free; Pro adds the active scanner and automation.
- graphw00f - Detects whether a URL is serving GraphQL and fingerprints the engine. Run it from a local clone, in detect and fingerprint mode only, and only on an in-scope host.
Payloads
- GraphQL - Start with introspection to dump the schema; if it's off, use field-suggestion errors (clairvoyance) to rebuild it. Then hunt BOLA/BFLA on objects and mutations.
Bypasses
- GraphQL authorization and batching - UI hide is not schema hide. Aliases, batch, and node(id) skip the screen the designer drew.
Questions
Introspection is disabled. Now what?
Field suggestions, clairvoyance, persisted-query hashes, mobile APKs, and JS operation names rebuild the schema.
Is batching a finding?
Batching or aliases that skip rate limits or authorization are. A working introspection on a public playground is usually P4/P5.
This page is the linked pack hunt_brief("graphql") returns on the MCP connector. Authorized testing only.