Mit der query query{__typename} kann geprüft werden, ob ein graphql Endpunkt erreichbar ist und funktioniert. Dies ist möglich, da jede graphql das reservierte Wort __typename hat, welches den Typ der Anfrage zurückgibt also in diesem Fall query. Graphql nutzt dabei zumeist einen der folgenden Suffixe:
- graphql
- /api
- /api/graphql
- /graphql/api
- /graphql/graphql
Falls dies nicht erfolgreich ist kann noch etwas wie /v1 angehängt werden.
Zum senden der Anfragen sollte dabei der Content-Type application/json benutzt werden, da dieser vor CSRF schützt, während dies beim Content-Type x-form-urlencoded nicht zutrifft.
Es kann mit der folgenden Anfrage überprüft werden, ob Introspektion erlaubt ist:
{ "query": ".
{__schema{queryType{name}}}"
}
query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description args { ...InputValue } onOperation #Often needs to be deleted to run query onFragment #Often needs to be deleted to run query onField #Often needs to be deleted to run query } } } 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 } } } }
onOperation, onFragment und onFieldzu entfernen. Da manche diese nicht akzeptieren in einer Introspektion.
Umgehen der Introspektion Verteidigung
Um die Introspektion zu unterdrücken nutzen manche Entwickler Regex. Ist dieses Regex aber nicht richtig erstellt, kann es sein, dass durch kleine Anpassungen diese umgangen werden können. Dazu können zu dem Schlüsselwort __schema Zeichen wie Kommas, Leerzeichen oder newlines angehängt werden.
Auch kann es mit einem GET Request klappen oder einem POST mit dem Content-TYPE x-www-form-urlencoded.
Auch können andere Felder wie der __type abgefragt werden.
Wurde ein Objekt gefunden kann durch "stuffing", also das ausprobieren von Feldnamen diese erraten werden.
Suggestions
Falls die Introspektion nicht klappt oder deaktiviert ist gibt es noch die Vorschläge. Beispielsweise benutzt Apollo graphql dies, wenn ein kleiner Fehler gemacht wurde liefert es Vorschläge:
There is no entry for 'productInfo'. Did you mean 'productInformation' instead?
Debug ausnutzen
Es kann sein, dass die Debug Funktionalität aktiviert ist. Allerdings kann es sein, dass diese versteckt ist, beispielsweise kann diese durch setzen von HTTP Headern oder das setzen des Parameters debug ausgenutzt werden:
http://example.com/graphql?debug=1
systemDebug abzurufen:
query {
systemDebug
}
Graphql Authentication
| Error message | Authentifizierungsimplementation |
|---|---|
| Authentication credentials are missing, Authorization header is required and must contain a value | OAuth 2.0 Bearer with JSON Web Token |
| Not Authorised! | GraphQL Shield |
| Not logged in Auth required API key is required |
GraphQL Modules |
| Invalid token! Invalid role! |
graphql-directive-auth |
Circular query mit Fragmenten
query CircularFragment {
__schema
...A
}
}
fragment A on __Schema {
directives {
name
}
...B
}
fragment B on __Schema {
...A
}
Resourcen
https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/graphql https://github.com/cyprosecurity/API-SecurityEmpire https://www.yeswehack.com/learn-bug-bounty/how-exploit-graphql-endpoint-bug-bounty https://0xn3va.gitbook.io/cheat-sheets/web-application/graphql-vulnerabilities https://www.youtube.com/watch?v=jyjGneKJynk https://www.youtube.com/watch?v=Wb0BO8J7024 https://github.com/nicholaseks/graphql-threat-matrix
Tools
commix(command injection Framework) Graphqlmap Addon Apollo Client Devtools