Skip to content

GraphQL

GraphQL

Automate Listing queries and mutations

Usual Endpoints:
- /graphql
- /v1/graphql
- /v2/graphql
- /graphql/console
- /graphiql
- /graphiql.php
- /explorer
- /altair
- /playground

Possible Debug Flag:
- &debug=1

Enumeration of Data
Enumerate GraphQL endpoints
Burp Plugin

Query

  • Read only retrieve data
  • Can be used in GET or POST

Example Query Request:

POST /graphql HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 840
Host: example.com
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/4.9.0

{"query": "mutation function($email:String!) { changePassword(email:$email) }", "variables": {"email": ""}}

Mutation

  • Can be used in POST only

Make a change to the data. You can also make a query request to have it return new data.

Note

Try SQL, NOSQL and Other Injection Techniques on Parameters

Example Mutation Request:

POST /graphql HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 840
Host: example.com
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/4.9.0

{"query": "query function($latitude:Float!, $longitude:Float!) { distanceToCoast(latitude:$latitude, longitude:$longitude) }", "variables": {"latitude": 1.1, "longitude": 1.1}}

Introspection

This is enabled by default

POST Request:

POST /graphql HTTP/1.1
Accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 840
Host: example.com
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/4.9.0

{"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 } } } } } } } } "}

GET Request:

GET /graphql?query={__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}}}}}}}} HTTP/1.1
Accept: application/json
Host: example.com
Connection: close
Accept-Encoding: gzip, deflate
User-Agent: okhttp/4.9.0

Viewing the Schema

Use Graphql Voyager to have a look at the Schema and their relationship.

Authorization

No Built in Authorization. Look for IDs to change

Batching Attacks

https://lab.wallarm.com/graphql-batching-attack/
https://www.whiteoaksecurity.com/blog/graphql-batching-attacks-turbo-intruder/

Schema Recursion