
Forschung zu GraphQL aus AppSec-Sicht.
Es wurde eine Laborumgebung erstellt, um die verschiedenen Probleme zu untersuchen. Diese bezieht sich auf den Kontext einer Tierarztpraxis, die die Gesundheitsversorgung von Hunden verwaltet.
Die Laborumgebung wurde mit IntelliJ IDEA Community Edition entwickelt.
Verwendete Domänen sind die folgenden:```text
127.0.0.1 localhost 127.0.0.1 domain1.local 127.0.0.1 domain2.local
Es gibt die Laborbedingungen und -annahmen:
* Ein Tierarzt kann 0 oder N Hunden zugeordnet sein.
* Ein Hund kann 0 oder 1 Tierarzt zugeordnet sein.
* Ein Tierarzt besitzt eine Eigenschaft namens **Popularität**, die im Speichersystem (Datenbank) vorhanden ist, aber von GraphQL-Clients nicht abgerufen werden darf, da es sich um vertrauliche Informationen handelt.
* Der Datenverbrauchspunkt von GraphQL ist der Tierarzt. Die Hundedaten sind öffentlich.
* Das Labor ist explizit eine verwundbare Anwendung, in der mehrere Schwachstellen implementiert und mit dem Marker `[VULN]` in Kommentaren gekennzeichnet sind.
* Bezüglich der Authentifizierung wurde ein gefälschter Drittanbieterdienst (über ein Servlet) implementiert, der ein JWT-Token zurückgibt, das den Namen des Tierarztes im Token enthält.
Sobald die Anwendung über die im Projekt vorhandene Startkonfiguration oder den Befehlszeilenbefehl `mvn spring-boot:run` gestartet wurde, ist das Labor unter diesen Endpunkten verfügbar:
* [GraphiQL](http://localhost:8080/graphiql)
* [GraphQL](http://localhost:8080/graphql)
Um die Anwendung als tragbare Jar-Datei zu paketieren, verwenden Sie den Befehl `mvn package` (eine vorgefertigte Jar-Datei ist [hier](https://github.com/righettod/poc-graphql/releases) verfügbar):
* Die Jar-Datei wird im Ordner *target* erstellt und heißt *graphql-poc.jar*.
* Verwenden Sie den Befehl `java -jar graphql-poc.jar`, um die Anwendung auszuführen.
## Bereitstellung auf Docker
> Das Image wird täglich auf [DockerHub](https://hub.docker.com/r/righettod/poc-graphql) veröffentlicht
Um die Anwendung in einem Docker-Container bereitzustellen, führen Sie die folgenden Schritte aus:
1. Stellen Sie sicher, dass `docker` installiert ist.
2. Klonen Sie das Repository mit `git clone`.
3. Wechseln Sie in das geklonte Verzeichnis.
4. Erstellen Sie das Docker-Image mit `docker build -t poc-graphql .`
5. Ein Image namens **poc-graphql:latest** wurde nun auf Ihrem Rechner erstellt.
6. Führen Sie den Container mit `docker run -p 8080:8080 poc-graphql:latest` aus.
7. Greifen Sie über die folgenden Endpunkte auf das Labor zu:
* [GraphiQL](http://localhost:8080/graphiql)
* [GraphQL](http://localhost:8080/graphql)
## Sicherheitsschwachstellen
### Autorisierung
*fehlerhafte Zugriffskontrolle*
[CWE-285](https://cwe.mitre.org/data/definitions/285.html)
#### Problem
Da GraphQL auf einem einzigen Endpunkt basiert, an den jede Anfrage gesendet wird, und die Autorisierung außerhalb des Geltungsbereichs der Spezifikation liegt (keine integrierten Funktionen).
Es liegt an der Anwendung, eine Autorisierungslogik zu implementieren.
In meinem Labor gibt es eine Schwachstelle in diesem Punkt, da die Überprüfung des Zugriffstokens nicht verifiziert, dass das Token dem in **veterinaryId** übergebenen Tierarzt gehört.
**Beispiel:**
Ich fordere ein Zugriffstoken für **Dr. Julien** an, der die Kennung **3** im Speicher hat, indem ich diese GraphQL-Anfrage sende:```javascript
query getAccessToken {
auth(veterinaryName: "Julien")
}
Ich erhalte das Zugriffstoken in der folgenden GraphQL-Antwort:```javascript { "data": { "auth": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJwb2MiLCJzdWIiOiJKdWxpZW4iLCJpc3MiOiJBdXRoU3lzdGVtIiwiZXhwIjoxNTQ2NDQyOTAyfQ.H9A-vXRsiivFGShtdhiR3N2lSDDx-sNqbbJxMRNnExI" } }
Ich sende eine GraphQL-Anfrage an die Abfrage `myInfo(...)` unter Verwendung des erhaltenen Zugriffstokens, ABER ich gebe die Kennung **2** an, die die von **Dr Benoit** ist:```javascript
query brokenAccessControl {
myInfo(accessToken:"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJwb2MiLCJzdWIiOiJKdWxpZW4iLCJpc3MiOiJBdXRoU3lzdGVtIiwiZXhwIjoxNTQ2NDQyOTAyfQ.H9A-vXRsiivFGShtdhiR3N2lSDDx-sNqbbJxMRNnExI", veterinaryId: 2){
id, name, dogs {
name
}
}
}
Ich erhalte in der GraphQL-Antwort die Liste der Dogs, die mit Dr Benoit verknüpft sind:```javascript { "data": { "myInfo": { "id": 2, "name": "Benoit", "dogs": [ { "name": "Babou" }, { "name": "Baboune" }, { "name": "Babylon" }, ...
#### Reco
Mit GraphQL sind wir von einer Autorisierungsmatrix mit `Role x Feature` zur Datensicherheit auf Datenebene mit `Role x Data` übergegangen, da es auch einen einzelnen Endpunkt gibt. Die Benutzeridentität und -rollen müssen an die oberste Schicht übergeben werden, die für das Abrufen der Daten zuständig ist (auf diese einwirkt), um vor dem Abrufen der Daten eine Überprüfung anhand der Benutzeridentität durchzuführen.
### Injection
[CWE-20](https://cwe.mitre.org/data/definitions/20.html) / [CWE-116](https://cwe.mitre.org/data/definitions/116.html)
#### Issue
Je nachdem, wie die Informationen aus der GraphQL-Anfrage (Query/Mutation/Subscription) vom GraphQL-Server verwendet werden, um auf Datenspeicher zuzugreifen, besteht die Möglichkeit einer Injection.
In meinen Laboren habe ich eine Schwachstelle in diesem Punkt bezüglich SQLi in der Query `dogs(namePrefix: String, limit: Int = 500): [Dog!]`, da der Parameter **namePrefix** in einer Stringverkettung verwendet wird, um eine SQL-Abfrage zu erstellen.
**Example:**