Translated ['network-services-pentesting/pentesting-web/graphql.md'] to

This commit is contained in:
Translator 2024-06-17 17:40:01 +00:00
parent 49d815db6f
commit eed4d60a1b

View file

@ -6,8 +6,8 @@
Andere Möglichkeiten, HackTricks zu unterstützen: Andere Möglichkeiten, HackTricks zu unterstützen:
* Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen möchten** oder **HackTricks als PDF herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)! * Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen möchten** oder **HackTricks im PDF-Format herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* Holen Sie sich das [**offizielle PEASS & HackTricks-Merchandise**](https://peass.creator-spring.com) * Holen Sie sich das [**offizielle PEASS & HackTricks-Merch**](https://peass.creator-spring.com)
* Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family) * Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen. * **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen.
@ -16,7 +16,7 @@ Andere Möglichkeiten, HackTricks zu unterstützen:
## Einführung ## Einführung
GraphQL wird als **effiziente Alternative** zu REST-APIs hervorgehoben und bietet einen vereinfachten Ansatz zum Abfragen von Daten vom Backend. Im Gegensatz zu REST, bei dem oft zahlreiche Anfragen an verschiedene Endpunkte gestellt werden müssen, ermöglicht GraphQL das Abrufen aller erforderlichen Informationen durch eine **einzige Anfrage**. Diese Vereinfachung **nutzt Entwicklern** erheblich, indem sie die Komplexität ihrer Datenabrufprozesse verringert. GraphQL wird als **effiziente Alternative** zu REST-APIs hervorgehoben und bietet einen vereinfachten Ansatz zum Abfragen von Daten vom Backend. Im Gegensatz zu REST, bei dem oft zahlreiche Anfragen an verschiedene Endpunkte gestellt werden müssen, um Daten zu sammeln, ermöglicht GraphQL das Abrufen aller erforderlichen Informationen durch eine **einzige Anfrage**. Diese Vereinfachung **nutzt Entwicklern** erheblich, indem sie die Komplexität ihrer Datenabrufprozesse verringert.
## GraphQL und Sicherheit ## GraphQL und Sicherheit
@ -24,7 +24,7 @@ Mit dem Aufkommen neuer Technologien, einschließlich GraphQL, entstehen auch ne
### Verzeichnis-Brute-Force-Angriffe und GraphQL ### Verzeichnis-Brute-Force-Angriffe und GraphQL
Zur Identifizierung von freigelegten GraphQL-Instanzen wird die Einbeziehung spezifischer Pfade in Verzeichnis-Brute-Force-Angriffen empfohlen. Diese Pfade sind: Um freiliegende GraphQL-Instanzen zu identifizieren, wird die Einbeziehung spezifischer Pfade in Verzeichnis-Brute-Force-Angriffen empfohlen. Diese Pfade sind:
* `/graphql` * `/graphql`
* `/graphiql` * `/graphiql`
@ -39,11 +39,11 @@ Die Identifizierung offener GraphQL-Instanzen ermöglicht die Untersuchung unter
### Fingerabdruck ### Fingerabdruck
Das Tool [**graphw00f**](https://github.com/dolevf/graphw00f) ist in der Lage zu erkennen, welcher GraphQL-Engine auf einem Server verwendet wird, und liefert dann einige hilfreiche Informationen für den Sicherheitsauditor. Das Tool [**graphw00f**](https://github.com/dolevf/graphw00f) ist in der Lage zu erkennen, welcher GraphQL-Engine auf einem Server verwendet wird, und liefert dann einige hilfreiche Informationen für den Sicherheitsprüfer.
#### Universelle Abfragen <a href="#universal-queries" id="universal-queries"></a> #### Universelle Abfragen <a href="#universal-queries" id="universal-queries"></a>
Um zu überprüfen, ob eine URL einen GraphQL-Dienst bereitstellt, 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 Feld `__typename` von GraphQL, das den Typ des abgefragten Objekts offenbart. 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 Feld `__typename` von GraphQL, das den Typ des abgefragten Objekts offenbart.
```javascript ```javascript
query{__typename} query{__typename}
``` ```
@ -53,7 +53,7 @@ Graphql unterstützt in der Regel **GET**, **POST** (x-www-form-urlencoded) und
#### Introspektion #### Introspektion
Um die Schema-Informationen mit Hilfe der Introspektion zu entdecken, frage das `__schema`-Feld ab. Dieses Feld ist auf dem Wurzeltyp aller Abfragen verfügbar. Um die Schema-Informationen mithilfe der Introspektion zu entdecken, abfragen Sie das `__schema`-Feld. Dieses Feld ist auf dem Wurzeltyp aller Abfragen verfügbar.
```bash ```bash
query={__schema{types{name,fields{name}}}} query={__schema{types{name,fields{name}}}}
``` ```
@ -173,7 +173,7 @@ name
} }
} }
``` ```
Inline Inspektionsabfrage: Inline Introspektionsabfrage:
``` ```
/?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}+} /?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}+}
``` ```
@ -195,31 +195,27 @@ Beachten Sie, dass der Typ der Abfrage "_flags_" "_Flags_" ist, und dieses Objek
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>) ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>)
Sie sehen, dass die "_Flags_"-Objekte aus **Name** und **Wert** bestehen. Dann können Sie alle Namen und Werte der Flags mit der Abfrage erhalten: Sie können sehen, dass die "_Flags_"-Objekte aus **Name** und **Wert** bestehen. Dann können Sie alle Namen und Werte der Flags mit der Abfrage erhalten:
```javascript ```javascript
query={flags{name, value}} query={flags{name, value}}
``` ```
Beachten Sie, dass im Falle des **abzufragenden Objekts** ein **primitiver Typ** wie **String** ist, wie im folgenden Beispiel Beachten Sie, dass im Falle des **zu abfragenden Objekts** ein **primitiver Typ** wie **String** wie im folgenden Beispiel ist, können Sie es einfach abfragen mit:
![](<../../.gitbook/assets/image (958).png>)
Sie können es einfach abfragen mit:
```javascript ```javascript
query={hiddenFlags} query={hiddenFlags}
``` ```
In einem anderen Beispiel, in dem es 2 Objekte innerhalb des "_Query_"-Typobjekts gab: "_user_" und "_users_".\ In einem anderen Beispiel, in dem sich 2 Objekte innerhalb des "_Query_"-Typobjekts befanden: "_user_" und "_users_".\
Wenn diese Objekte keine Argumente zum Suchen benötigen, könnten Sie **alle Informationen von ihnen abrufen**, indem Sie einfach nach den Daten fragen, die Sie möchten. In diesem Beispiel aus dem Internet könnten Sie Benutzernamen und Passwörter extrahieren: Wenn diese Objekte keine Argumente zum Suchen benötigen, könnten Sie **alle Informationen von ihnen abrufen**, indem Sie einfach nach den Daten fragen, die Sie möchten. In diesem Beispiel aus dem Internet könnten Sie Benutzernamen und Passwörter extrahieren:
![](<../../.gitbook/assets/image (880).png>) ![](<../../.gitbook/assets/image (880).png>)
Jedoch erhalten Sie in diesem Beispiel bei dem Versuch, dies zu tun, diesen **Fehler**: Jedoch erhalten Sie in diesem Beispiel, wenn Sie dies versuchen, diesen **Fehler**:
![](<../../.gitbook/assets/image (1042).png>) ![](<../../.gitbook/assets/image (1042).png>)
Es scheint, dass auf irgendeine Weise nach dem "_**uid**_"-Argument vom Typ _**Int**_ gesucht wird.\ Es scheint, dass auf irgendeine Weise nach dem "_**uid**_"-Argument vom Typ _**Int**_ gesucht wird.\
Wie auch immer, wir wussten bereits, dass in der [Grundlegenden Aufzählung](graphql.md#basic-enumeration) ein 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}}}}}}}` Wie auch immer, wir wussten bereits, dass in der [Grundlegenden Aufzählung](graphql.md#basic-enumeration) ein 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 Sie das bereitgestellte Bild lesen, sehen Sie, dass "_**user**_" das **Arg** "_**uid**_" vom Typ _Int_ hatte, als ich diese Abfrage ausführte. Wenn Sie das bereitgestellte Bild lesen, sehen Sie, dass "_**user**_" das **Arg** "_**uid**_" vom Typ _Int_ hatte.
Also, nachdem ich ein leichtes _**uid**_ Bruteforce durchgeführt hatte, fand ich heraus, dass bei _**uid**=**1**_ ein Benutzername und ein Passwort abgerufen wurden:\ Also, nachdem ich ein leichtes _**uid**_ Bruteforce durchgeführt hatte, fand ich heraus, dass bei _**uid**=**1**_ ein Benutzername und ein Passwort abgerufen wurden:\
`query={user(uid:1){user,password}}` `query={user(uid:1){user,password}}`
@ -230,11 +226,11 @@ Beachten Sie, dass ich **herausgefunden** habe, dass ich nach den **Parametern**
![](<../../.gitbook/assets/image (707).png>) ![](<../../.gitbook/assets/image (707).png>)
Und während der **Aufzählungsphase** fand ich heraus, dass das "_**dbuser**_"-Objekt die Felder "_**user**_" und "_**password**_ hatte. Und während der **Aufzählungsphase** entdeckte ich, dass das "_**dbuser**_"-Objekt die Felder "_**user**_" und "_**password**_ hatte.
**Abfragezeichenfolge Dump-Trick (Dank an @BinaryShadow\_)** **Abfragezeichenfolge Dump-Trick (Dank an @BinaryShadow\_)**
Wenn Sie nach einem String-Typ suchen können, wie z. B.: `query={theusers(description: ""){username,password}}` und Sie nach einem leeren String suchen, werden alle Daten abgerufen. (_Beachten Sie, dass dieses Beispiel nicht mit dem Beispiel der Tutorials zusammenhängt. Nehmen Sie für dieses Beispiel an, dass Sie mit "**theusers**" nach einem String-Feld namens "**description**" suchen können"_). Wenn Sie nach einem String-Typ suchen können, wie: `query={theusers(description: ""){username,password}}` und Sie nach einem leeren String suchen, werden alle Daten **ausgegeben**. (_Beachten Sie, dass dieses Beispiel nicht mit dem Beispiel der Tutorials zusammenhängt. Für dieses Beispiel nehmen Sie an, dass Sie mit "**theusers**" nach einem String-Feld namens "**description**" suchen können"_).
### Suche ### Suche
@ -248,7 +244,7 @@ email
} }
} }
``` ```
Du kannst Personen **nach** dem **Namen** suchen und ihre **abonnierten** **Filme** erhalten: Sie können Personen **nach** dem **Namen** suchen und ihre **abonnierten** **Filme** erhalten:
```javascript ```javascript
{ {
searchPerson(name: "John Doe") { searchPerson(name: "John Doe") {
@ -306,7 +302,7 @@ In der **Introspektion** können Sie die **deklarierten** **Mutationen** finden.
In diesem Setup enthält eine **Datenbank** **Personen** und **Filme**. **Personen** werden anhand ihrer **E-Mail** und ihres **Namens** identifiziert; **Filme** anhand ihres **Namens** und ihrer **Bewertung**. **Personen** können miteinander befreundet sein und auch Filme haben, was Beziehungen innerhalb der Datenbank anzeigt. In diesem Setup enthält eine **Datenbank** **Personen** und **Filme**. **Personen** werden anhand ihrer **E-Mail** und ihres **Namens** identifiziert; **Filme** anhand ihres **Namens** und ihrer **Bewertung**. **Personen** können miteinander befreundet sein und auch Filme haben, was Beziehungen innerhalb der Datenbank anzeigt.
Eine Mutation zum **Erstellen neuer** Filme in der Datenbank könnte wie folgt aussehen (in diesem Beispiel wird die Mutation `addMovie` genannt): Eine Mutation zum **Erstellen neuer** Filme in der Datenbank kann wie folgt aussehen (in diesem Beispiel wird die Mutation `addMovie` genannt):
```javascript ```javascript
mutation { mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) { addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
@ -319,7 +315,7 @@ rating
``` ```
**Beachten Sie, wie sowohl die Werte als auch der Datentyp in der Abfrage angegeben sind.** **Beachten Sie, wie sowohl die Werte als auch der Datentyp in der Abfrage angegeben sind.**
Zusätzlich unterstützt die Datenbank eine **Mutation**-Operation namens `addPerson`, die die Erstellung von **Personen** zusammen mit ihren Verknüpfungen zu vorhandenen **Freunden** und **Filmen** ermöglicht. Es ist entscheidend zu beachten, dass die Freunde und Filme vor dem Verknüpfen mit der neu erstellten Person bereits in der Datenbank vorhanden sein müssen. Zusätzlich unterstützt die Datenbank eine **Mutation**-Operation namens `addPerson`, die die Erstellung von **Personen** zusammen mit ihren Verknüpfungen zu vorhandenen **Freunden** und **Filmen** ermöglicht. Es ist wichtig zu beachten, dass die Freunde und Filme vor dem Verknüpfen mit der neu erstellten Person bereits in der Datenbank vorhanden sein müssen.
```javascript ```javascript
mutation { mutation {
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"}]) { 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"}]) {
@ -351,12 +347,12 @@ releaseYear
Wie in [**einer der Schwachstellen, die in diesem Bericht beschrieben sind**](https://www.landh.tech/blog/20240304-google-hack-50000/) erläutert, bedeutet eine Direktivenüberlastung, eine Direktive sogar Millionen Mal aufzurufen, um den Server dazu zu bringen, Operationen zu verschwenden, bis es möglich ist, einen DoS-Angriff durchzuführen. Wie in [**einer der Schwachstellen, die in diesem Bericht beschrieben sind**](https://www.landh.tech/blog/20240304-google-hack-50000/) erläutert, bedeutet eine Direktivenüberlastung, eine Direktive sogar Millionen Mal aufzurufen, um den Server dazu zu bringen, Operationen zu verschwenden, bis es möglich ist, einen DoS-Angriff durchzuführen.
### Batching-Brute-Force in 1 API-Anfrage ### Batch-Brute-Force in 1 API-Anfrage
Diese Information stammt von [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\ Diese Information stammt von [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
Authentifizierung über GraphQL-API durch **gleichzeitiges Senden vieler Abfragen mit verschiedenen Anmeldeinformationen** zur Überprüfung. 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, aufgrund der GraphQL-Batching-Funktion. Dieser Ansatz würde externe Rate-Monitoring-Anwendungen dazu bringen zu glauben, dass alles in Ordnung ist und es keinen Brute-Force-Bot gibt, der versucht, Passwörter zu erraten. Authentifizierung über GraphQL-API durch **gleichzeitiges Senden vieler Abfragen mit unterschiedlichen Anmeldeinformationen** zur Überprüfung. 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, aufgrund der GraphQL-Batch-Funktion. Dieser Ansatz würde externe Rate-Monitoring-Anwendungen dazu bringen zu glauben, dass alles in Ordnung ist und es keinen Brute-Force-Bot gibt, der versucht, Passwörter zu erraten.
Im Folgenden finden Sie die einfachste Demonstration einer Anwendungsauthentifizierungsanfrage, mit **3 verschiedenen E-Mail/Passwort-Paaren gleichzeitig**. Offensichtlich ist es möglich, auf die gleiche Weise Tausende in einer einzigen Anfrage zu senden: Im Folgenden finden Sie die einfachste Demonstration einer Authentifizierungsanfrage der Anwendung, mit **3 verschiedenen E-Mail/Passwort-Paaren gleichzeitig**. Offensichtlich ist es möglich, auf die gleiche Weise Tausende in einer einzigen Anfrage zu senden:
![](<../../.gitbook/assets/image (1081).png>) ![](<../../.gitbook/assets/image (1081).png>)
@ -364,19 +360,17 @@ Wie aus dem Antwort-Screenshot ersichtlich ist, haben die ersten und dritten Anf
![](<../../.gitbook/assets/image (119) (1).png>) ![](<../../.gitbook/assets/image (119) (1).png>)
## GraphQL Ohne Introspektion ## GraphQL ohne Introspektion
Immer mehr **GraphQL-Endpunkte deaktivieren die Introspektion**. Die Fehler, die GraphQL wirft, wenn eine unerwartete Anfrage empfangen wird, reichen jedoch aus, damit Tools wie [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) den Großteil des Schemas rekonstruieren können. Immer mehr **GraphQL-Endpunkte deaktivieren die Introspektion**. Die Fehler, die GraphQL wirft, wenn eine unerwartete Anfrage empfangen wird, reichen jedoch aus, damit Tools wie [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) den Großteil des Schemas rekonstruieren können.
Darüber hinaus beobachtet die Burp Suite-Erweiterung [**GraphQuail**](https://github.com/forcesunseen/graphquail) **GraphQL-API-Anfragen, die durch Burp gehen** und **erstellt** ein internes GraphQL-**Schema** mit jeder neuen Abfrage, die es sieht. Es kann auch das Schema für GraphiQL und Voyager freigeben. Die Erweiterung gibt eine gefälschte Antwort zurück, wenn sie eine Introspektionsabfrage erhält. Als Ergebnis zeigt GraphQuail alle Abfragen, Argumente und Felder, die innerhalb der API verfügbar sind. Für weitere Informationen [**überprüfen Sie dies**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema). Darüber hinaus beobachtet die Burp Suite-Erweiterung [**GraphQuail**](https://github.com/forcesunseen/graphquail) **GraphQL-API-Anfragen, die durch Burp gehen** und **erstellt** ein internes GraphQL-**Schema** mit jeder neuen Abfrage, die es sieht. Es kann auch das Schema für GraphiQL und Voyager freigeben. Die Erweiterung gibt eine gefälschte Antwort zurück, wenn sie eine Introspektionsabfrage erhält. Als Ergebnis zeigt GraphQuail alle Abfragen, Argumente und Felder, die innerhalb der API verwendet werden können. Für weitere Informationen [**überprüfen Sie dies**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
Eine schöne **Wortliste** zur Entdeckung von [**GraphQL-Entitäten finden Sie hier**](https://github.com/Escape-Technologies/graphql-wordlist?). Eine schöne **Wortliste** zur Entdeckung von [**GraphQL-Entitäten finden Sie hier**](https://github.com/Escape-Technologies/graphql-wordlist?).
### Umgehung von GraphQL-Introspektionsabwehrmaßnahmen <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a> ### Umgehen von GraphQL-Introspektionsabwehrmechanismen <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
### **Umgehung von GraphQL-Introspektionsabwehrmaßnahmen** Um Beschränkungen bei Introspektionsabfragen in APIs zu umgehen, erweist sich das Einfügen eines **Sonderzeichens nach dem `__schema`-Schlüsselwort** als wirksam. Diese Methode nutzt häufige Entwicklerfehler in Regex-Mustern aus, die darauf abzielen, die Introspektion durch Fokussierung auf das `__schema`-Schlüsselwort zu blockieren. Durch das Hinzufügen von Zeichen wie **Leerzeichen, Zeilenumbrüche und Kommas**, die von GraphQL ignoriert werden, aber möglicherweise nicht in Regex berücksichtigt werden, können Beschränkungen umgangen werden. Beispielsweise kann eine Introspektionsabfrage mit einem Zeilenumbruch nach `__schema` solche Abwehrmechanismen umgehen:
Um Beschränkungen bei Introspektionsabfragen in APIs zu umgehen, erweist sich das Einfügen eines **Sonderzeichens nach dem `__schema`-Schlüsselwort** als wirksam. Diese Methode nutzt häufige Entwicklerfehler in Regex-Mustern aus, die darauf abzielen, die Introspektion durch Fokussierung auf das `__schema`-Schlüsselwort zu blockieren. Durch das Hinzufügen von Zeichen wie **Leerzeichen, Zeilenumbrüche und Kommas**, die von GraphQL ignoriert werden, aber möglicherweise nicht in Regex berücksichtigt werden, können Beschränkungen umgangen werden. Beispielsweise kann eine Introspektionsabfrage mit einem Zeilenumbruch nach `__schema` solche Abwehrmaßnahmen umgehen:
```bash ```bash
# Example with newline to bypass # Example with newline to bypass
{ {
@ -384,11 +378,11 @@ Um Beschränkungen bei Introspektionsabfragen in APIs zu umgehen, erweist sich d
{queryType{name}}}" {queryType{name}}}"
} }
``` ```
Wenn dies nicht erfolgreich ist, sollten alternative Anfragemethoden in Betracht gezogen werden, wie z.B. **GET-Anfragen** oder **POST mit `x-www-form-urlencoded`**, da Einschränkungen möglicherweise nur für POST-Anfragen gelten. Wenn dies nicht erfolgreich ist, sollten alternative Anfragemethoden in Betracht gezogen werden, wie z. B. **GET-Anfragen** oder **POST mit `x-www-form-urlencoded`**, da Einschränkungen möglicherweise nur für POST-Anfragen gelten.
### **Aufdecken von freigelegten GraphQL-Strukturen** ### **Aufdecken von freigelegten GraphQL-Strukturen**
Wenn die Introspektion deaktiviert ist, ist die Untersuchung des Quellcodes der Website nach vorab geladenen Abfragen in JavaScript-Bibliotheken eine nützliche Strategie. Diese Abfragen können mithilfe des `Quellen`-Tabs in den Entwicklertools gefunden werden und Einblicke in das API-Schema bieten sowie potenziell **sensible freigelegte Abfragen** aufdecken. Die Befehle zum Suchen in den Entwicklertools lauten: Wenn die Introspektion deaktiviert ist, ist die Untersuchung des Quellcodes der Website nach vorab geladenen Abfragen in JavaScript-Bibliotheken eine nützliche Strategie. Diese Abfragen können mithilfe des `Quellen`-Tabs in den Entwicklertools gefunden werden und Einblicke in das Schema der API bieten sowie potenziell **freigelegte sensible Abfragen** aufdecken. Die Befehle zum Suchen in den Entwicklertools lauten:
```javascript ```javascript
Inspect/Sources/"Search all files" Inspect/Sources/"Search all files"
file:* mutation file:* mutation
@ -412,13 +406,13 @@ Jedoch unterstützen die meisten GraphQL-Endpunkte auch **`form-urlencoded` POST
```javascript ```javascript
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
``` ```
Daher, da CSRF-Anfragen wie die vorherigen **ohne Vorab-Anfragen** gesendet werden, ist es möglich, **Änderungen** im GraphQL vorzunehmen, indem CSRF missbraucht wird. Daher ist es möglich, CSRF-Anfragen wie die vorherigen **ohne Vorab-Anfragen** zu senden, um **Änderungen** im GraphQL vorzunehmen und CSRF auszunutzen.
Beachten Sie jedoch, dass der neue Standard-Cookie-Wert des `samesite`-Flags von Chrome `Lax` ist. Dies bedeutet, dass das Cookie nur von einer Drittanbieter-Website in GET-Anfragen gesendet wird. Beachten Sie jedoch, dass der neue Standard-Cookie-Wert des `samesite`-Flags von Chrome `Lax` ist. Dies bedeutet, dass das Cookie nur von einer Drittanbieter-Website in GET-Anfragen gesendet wird.
Es ist in der Regel möglich, die **Abfrageanfrage** auch als **GET**-Anfrage zu senden, und das CSRF-Token wird möglicherweise nicht bei einer GET-Anfrage validiert. Es ist in der Regel möglich, die **Abfrageanfrage** auch als **GET**-Anfrage zu senden, und das CSRF-Token wird möglicherweise nicht in einer GET-Anfrage validiert.
Durch den Missbrauch eines [**XS-Search**](../../pentesting-web/xs-search/) **Angriffs** könnte es möglich sein, Inhalte aus dem GraphQL-Endpunkt unter Ausnutzung der Anmeldeinformationen des Benutzers zu exfiltrieren. Durch Ausnutzen eines [**XS-Search**](../../pentesting-web/xs-search/)-**Angriffs** könnte es möglich sein, Inhalte aus dem GraphQL-Endpunkt unter Ausnutzung der Anmeldeinformationen des Benutzers zu exfiltrieren.
Für weitere Informationen **überprüfen Sie den** [**Originalbeitrag hier**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html). Für weitere Informationen **überprüfen Sie den** [**Originalbeitrag hier**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
@ -426,9 +420,9 @@ Für weitere Informationen **überprüfen Sie den** [**Originalbeitrag hier**](h
Viele in dem Endpunkt definierte GraphQL-Funktionen überprüfen möglicherweise nur die Authentifizierung des Anfragenden, jedoch nicht die Autorisierung. Viele in dem Endpunkt definierte GraphQL-Funktionen überprüfen möglicherweise nur die Authentifizierung des Anfragenden, jedoch nicht die Autorisierung.
Die Änderung von Abfrageeingabevariablen könnte zu sensiblen Kontodetails führen, die [geleakt](https://hackerone.com/reports/792927) werden. Das Ändern von Abfrageeingabevariablen könnte zu sensiblen Kontodetails führen, die [offengelegt](https://hackerone.com/reports/792927) werden.
Mutationen könnten sogar zu Account-Übernahmen führen, wenn versucht wird, andere Kontodaten zu ändern. Mutationen könnten sogar zu Account-Übernahmen führen, wenn versucht wird, Daten anderer Konten zu ändern.
```javascript ```javascript
{ {
"operationName":"updateProfile", "operationName":"updateProfile",
@ -440,13 +434,13 @@ Mutationen könnten sogar zu Account-Übernahmen führen, wenn versucht wird, an
Das Verketten von Abfragen kann ein schwaches Authentifizierungssystem umgehen. Das Verketten von Abfragen kann ein schwaches Authentifizierungssystem umgehen.
Im folgenden Beispiel sehen Sie, dass die Operation "forgotPassword" ist und dass nur die damit verbundene forgotPassword-Abfrage ausgeführt werden sollte. Dies kann umgangen werden, indem am Ende eine weitere Abfrage hinzugefügt wird. In diesem Fall fügen wir "register" hinzu und eine Benutzervariable, damit das System sich als neuer Benutzer registriert. Im folgenden Beispiel sehen Sie, dass die Operation "forgotPassword" ist und dass nur die damit verbundene forgotPassword-Abfrage ausgeführt werden sollte. Dies kann umgangen werden, indem am Ende eine weitere Abfrage hinzugefügt wird. In diesem Fall fügen wir "register" und eine Benutzervariable hinzu, damit sich das System als neuer Benutzer registriert.
<figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure> <figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## Umgehung von Rate Limits unter Verwendung von Aliassen in GraphQL ## Umgehung von Rate Limits unter Verwendung von Aliassen in GraphQL
In GraphQL sind Aliasse ein leistungsstarkes Feature, das es ermöglicht, **Eigenschaften explizit zu benennen**, wenn eine API-Anfrage gestellt wird. Diese Funktion ist besonders nützlich, um **mehrere Instanzen desselben Objekttyps** innerhalb einer einzigen Anfrage abzurufen. Aliasse können eingesetzt werden, um die Einschränkung zu überwinden, die verhindert, dass GraphQL-Objekte mehrere Eigenschaften mit demselben Namen haben. In GraphQL sind Aliasse ein leistungsstarkes Feature, das es ermöglicht, **Eigenschaften explizit zu benennen**, wenn eine API-Anfrage gestellt wird. Diese Funktion ist besonders nützlich, um **mehrere Instanzen desselben Objekttyps** innerhalb einer einzelnen Anfrage abzurufen. Aliasse können eingesetzt 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). 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).
@ -471,11 +465,13 @@ valid
### Schwachstellen-Scanner ### Schwachstellen-Scanner
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Toolkit, das verwendet werden kann, um Schemas abzurufen und nach sensiblen Daten zu suchen, Autorisierung zu testen, Schemas per Bruteforce anzugreifen und Pfade zu einem bestimmten Typ zu finden. * [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): Testet häufige Fehlkonfigurationen von GraphQL-Endpunkten
* [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): Erstellt ein Fingerprint des verwendeten GraphQL
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Toolkit, das verwendet werden kann, um Schemas abzurufen und nach sensiblen Daten zu suchen, Autorisierung zu testen, Schemas per Brute Force anzugreifen 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 eigenständig oder als [Burp-Erweiterung](https://github.com/doyensec/inql) verwendet werden. * [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Kann eigenständig oder als [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://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://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/inql](https://github.com/doyensec/inql): Burp-Erweiterung für fortgeschrittenes GraphQL-Testing. Der _**Scanner**_ ist der Kern von InQL v5.0, mit dem Sie einen GraphQL-Endpunkt oder eine lokale Introspektions-Schema-Datei analysieren können. Es generiert automatisch alle möglichen Abfragen und Mutationen und organisiert sie in einer strukturierten Ansicht für Ihre Analyse. Die _**Attacker**_-Komponente ermöglicht das Ausführen von Stapelangriffen auf GraphQL, was nützlich sein kann, um schlecht implementierte Rate-Limits zu umgehen. * [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Burp-Erweiterung für fortgeschrittene GraphQL-Tests. Der _**Scanner**_ ist der Kern von InQL v5.0, mit dem Sie einen GraphQL-Endpunkt oder eine lokale Introspektions-Schema-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 Komponente _**Attacker**_ ermöglicht das Ausführen von Stapelangriffen auf GraphQL, was nützlich sein kann, um schlecht implementierte Rate-Limits zu umgehen.
### Clients ### Clients
@ -500,14 +496,14 @@ valid
<details> <details>
<summary><strong>Erlernen Sie AWS-Hacking von Null auf Held mit</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary> <summary><strong>Erlernen Sie AWS-Hacking von Grund auf mit</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Andere Möglichkeiten, HackTricks zu unterstützen: Andere Möglichkeiten, HackTricks zu unterstützen:
* Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen möchten** oder **HackTricks als PDF herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)! * Wenn Sie möchten, dass Ihr **Unternehmen in HackTricks beworben wird** oder **HackTricks als PDF herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* Holen Sie sich das [**offizielle PEASS & HackTricks-Merch**](https://peass.creator-spring.com) * Holen Sie sich das [**offizielle PEASS & HackTricks-Merch**](https://peass.creator-spring.com)
* Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family) * Entdecken Sie [**The PEASS Family**](https://opensea.io/collection/the-peass-family), unsere Sammlung exklusiver [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.** * **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen. * **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories senden.
</details> </details>