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/