How to Test GraphQL APIs: Security Risks Every Bug Bounty Hunter Should Know
GraphQL is becoming the standard for modern APIs. GitHub, Shopify, Twitter — all use GraphQL. But security tools built for REST APIs don't work on GraphQL. Most security professionals don't even know how to test GraphQL properly.
I discovered this the hard way. My first bug bounty target had a GraphQL API. I ran my usual REST API testing tools. Nothing. Then I learned GraphQL works completely differently. Once I understood that, I found vulnerabilities in 3 different GraphQL endpoints.
This post explains GraphQL security from a bug bounty perspective. Not a theoretical walkthrough. Real vulnerabilities I found. Real techniques that worked. Real explanations of why REST API tools fail on GraphQL.
Why GraphQL is Different: The Security Problem
REST APIs have predictable endpoints: `/api/users/123`, `/api/posts/456`. Each endpoint does one thing. A scanner can enumerate endpoints and test them systematically.
GraphQL has a single endpoint: `/graphql`. Everything goes through it. A single POST request with a query language that looks like JSON. Traditional API scanners don't know what to do with it.
This means:
- Endpoint enumeration fails: There's only 1 endpoint. Everything is query-based.
- Parameter discovery fails: You don't know what fields exist until you query for them.
- Authentication bypass patterns are different: REST uses URL manipulation. GraphQL uses query manipulation.
- Information disclosure risk is higher: GraphQL introspection exposes the entire schema automatically.
Vulnerability 1: GraphQL Introspection Information Disclosure
Running this returned the entire API schema: 50+ types, 200+ fields. Including "adminPanel", "userCreditCard", "internalNotes" — fields that should never be exposed.
Why REST tools miss this: REST API scanners look for HTTP methods (GET, POST, PUT). GraphQL introspection is a legitimate query, not an unusual HTTP pattern. Scanners don't know to test for it.
Vulnerability 2: IDOR (Insecure Direct Object Reference) Via GraphQL Query Manipulation
The REST API correctly rejected my attempt to access another user. The GraphQL API... didn't. I could query any user ID and retrieve full profiles including credit card data.
Why REST tools miss this: REST scanners fuzz the URL path and query parameters. GraphQL queries have a completely different format. Burp Suite and OWASP ZAP don't natively understand GraphQL query syntax. They can't fuzz a GraphQL query intelligently because they'd need to understand the schema first.
Vulnerability 3: Batch Query Denial of Service (DoS)
Sent 1000 user queries in one HTTP request. The server tried to execute all 1000 simultaneously. Database CPU spiked to 100%, and the service went down for 5 minutes.
Why REST tools miss this: REST tools see 1 HTTP request = 1 query. GraphQL allows multiplexing. A single HTTP POST can contain hundreds of queries. Standard rate limiting by HTTP request won't catch this.
My Methodology for Testing GraphQL APIs
Step-by-Step Process (What Actually Works)
- Step 1: Find the GraphQL endpoint — Usually `/graphql` or `/graphql/`. Sometimes `/api/graphql`. Look for it in JS source code or check for `graphql` in request history.
- Step 2: Query introspection — Run introspection query to dump schema. Use tools like `graphql-introspect` or manually run queries.
- Step 3: Analyze exposed schema — Look for fields that shouldn't be public (admin panels, internal notes, user data). Look for unusual operations.
- Step 4: Test authentication bypass — Try unauthenticated queries. Try accessing other users' data by changing ID parameters.
- Step 5: Test query complexity — Send deeply nested queries to see if server has limits. Send batch queries to check rate limiting.
- Step 6: Test field manipulation — For mutations, try changing other users' data. GraphQL mutations can be more dangerous than REST because you can modify multiple fields in one request.
Tools That Actually Work on GraphQL
- Burp Suite (basic support, not great for GraphQL-specific testing)
- OWASP ZAP (tries to fuzz GraphQL like REST, doesn't work well)
- Nmap NSE scripts (irrelevant for GraphQL)
- Graphql-core / graphql-php: Python/PHP libraries to build GraphQL clients and fuzz queries
- graphql-introspect: Dump entire schema from introspection endpoint
- Altair GraphQL Client: GUI tool like Postman, but for GraphQL. Lets you explore schema and craft custom queries
- clairvoyance: Tool for escaping obfuscated GraphQL endpoints and gathering schema info
- graphql-core-tests: Fuzz test GraphQL implementations
Real Example: Complete Exploitation Workflow
Target: SaaS platform with e-commerce features
Step 1: Discovered endpoint — Found `/api/graphql` in JavaScript source
Step 2: Dumped schema — Ran introspection query, got 100+ types including "UserAccount", "PaymentMethod", "AdminSettings"
Step 3: Tested IDOR — Queried `user(id: "2")` while authenticated as user 1. Got back another user's email, name, address. No authorization check.
Step 4: Enumerated data — Wrote Python script to loop through user IDs 1-10000. Downloaded 9,500 user profiles.
Step 5: Extracted sensitive data — Analyzed profiles, found 200 credit card records (partial), 500 email addresses, 1000 phone numbers.
Result: HackerOne report accepted, $2,500 bounty paid. Company issued CVE for the IDOR vulnerability.
0 Comments