GraphQL
What You Will Learn
- How GraphQL differs from REST APIs
- How queries, mutations, and subscriptions work
- How introspection can be used to discover the API schema
- Common GraphQL security vulnerabilities
What Is It?
GraphQL is a query language for APIs. Unlike REST where each endpoint returns a fixed structure, GraphQL lets the client request exactly the data it needs. The client controls the shape of the response.
GraphQL has a single endpoint (usually /graphql) and all operations are sent as POST requests.
Why It Matters
GraphQL is increasingly used in modern web applications. Its flexibility introduces security issues:
- Introspection can expose the entire schema to attackers
- Overly permissive resolvers can leak sensitive data
- Batching attacks can bypass rate limiting
- Injection vulnerabilities still apply
Key Concepts
Three Operation Types
GraphQL schemas can be manipulated using three types of operations:
| Operation | Description |
|---|---|
| Query | Read data — similar to GET in REST |
| Mutation | Add, change, or remove data — similar to POST/PUT/DELETE |
| Subscription | Set up a persistent connection — server pushes data to client in real time |
Queries
# Fetch all products
query {
products {
id
name
published
}
}
# Fetch product with id 5
query {
product(id: 5) {
id
name
published
}
}
Mutations
mutation {
createProduct(name: "Flamin' Cocktail Glasses", published: true) {
id
name
listed
}
}
Introspection
Introspection helps you understand how to interact with a GraphQL API. It returns the full schema — all types, queries, mutations, and fields.
# Introspection probe — check if introspection is enabled
{
"query": "{__schema{queryType{name}}}"
}
# Full introspection query
query IntrospectionQuery {
__schema {
queryType { name }
mutationType { name }
subscriptionType { name }
types {
kind
name
fields(includeDeprecated: true) {
name
type {
kind
name
ofType { kind name }
}
}
}
}
}
Using Introspection for Recon
If introspection is enabled, an attacker can map the entire API:
# Use graphql-voyager or InQL Burp plugin to visualize the schema
# Or use clairvoyance to guess the schema even without introspection
Common GraphQL Vulnerabilities
1. Introspection Enabled in Production
If introspection is not disabled, attackers can discover all fields — including hidden admin fields.
2. Injection
GraphQL resolvers that pass user input to databases can be vulnerable to SQL injection or NoSQL injection:
# Malicious query if resolver passes name directly to SQL
query {
user(name: "' OR '1'='1") {
id
email
password
}
}
3. Batching Attacks
GraphQL allows sending multiple queries in one request. This bypasses rate limiting:
[
{"query": "mutation { login(user: \"admin\", pass: \"pass1\") }"},
{"query": "mutation { login(user: \"admin\", pass: \"pass2\") }"},
{"query": "mutation { login(user: \"admin\", pass: \"pass3\") }"}
]
4. Excessive Data Exposure
Resolvers that return entire objects when only part of the data is needed can expose sensitive fields.
Security Testing Checklist
# Check if introspection is enabled
curl -s -X POST https://target.com/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{__schema{queryType{name}}}"}' | jq .
# Try accessing admin fields
# Try deeply nested queries (DoS via query depth)
# Try batched queries (rate limit bypass)
# Try SQL/NoSQL injection in string arguments