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

This commit is contained in:
Translator 2024-06-17 17:39:58 +00:00
parent bdbbdab881
commit 4e594e66bd

View file

@ -6,11 +6,11 @@
Autres façons de soutenir 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) ! * 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) * 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) * 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)**.** * **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. * **Partagez vos astuces de piratage en soumettant des PRs aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts GitHub.
</details> </details>
@ -20,11 +20,11 @@ GraphQL est **souligné** comme une **alternative efficace** aux API REST, offra
## GraphQL et Sécurité ## GraphQL et Sécurité
Avec l'avènement de nouvelles technologies, y compris GraphQL, de nouvelles vulnérabilités de sécurité émergent également. Un point clé à noter est que **GraphQL ne comprend pas de mécanismes d'authentification par défaut**. Il incombe aux développeurs de mettre en œuvre 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. Avec l'avènement de nouvelles technologies, y compris GraphQL, de nouvelles vulnérabilités de sécurité émergent également. Un point clé à noter est que **GraphQL ne comprend pas de mécanismes d'authentification par défaut**. Il incombe aux développeurs de mettre en œuvre de telles mesures de sécurité. Sans une authentification appropriée, les points de terminaison GraphQL peuvent exposer des informations sensibles à des utilisateurs non authentifiés, posant un risque de sécurité significatif.
### Attaques de Force Brute de Répertoire et GraphQL ### Attaques de Force Brute sur les Répertoires et GraphQL
Pour identifier les instances GraphQL exposées, l'inclusion de chemins spécifiques dans des attaques de force brute de répertoire est recommandée. Ces chemins sont : Pour identifier les instances GraphQL exposées, l'inclusion de chemins spécifiques dans des attaques de force brute sur les répertoires est recommandée. Ces chemins sont :
* `/graphql` * `/graphql`
* `/graphiql` * `/graphiql`
@ -35,11 +35,11 @@ Pour identifier les instances GraphQL exposées, l'inclusion de chemins spécifi
* `/graphql/api` * `/graphql/api`
* `/graphql/graphql` * `/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 qu'un schéma prend en charge. 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/) 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 ### 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é. 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 de sécurité.
#### Requêtes universelles <a href="#universal-queries" id="universal-queries"></a> #### Requêtes universelles <a href="#universal-queries" id="universal-queries"></a>
@ -177,17 +177,17 @@ 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}+} /?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 d'objets, paramètres, types...) La dernière ligne de code est une requête graphql qui va extraire toutes les métainformations du graphql (noms d'objets, paramètres, types...)
![](<../../.gitbook/assets/image (363).png>) ![](<../../.gitbook/assets/image (363).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. 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 ### Requête
Maintenant que nous savons quel type d'informations est stocké dans la base de données, essayons d'**extraire certaines valeurs**. Maintenant que nous savons quel type d'informations est enregistré 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. 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 flag.
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-17-48.png>) ![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-17-48.png>)
@ -195,7 +195,7 @@ Notez que le type de la requête "_flags_" est "_Flags_", et que cet objet est d
![](<../../.gitbook/assets/Screenshot from 2021-03-13 18-22-57 (1).png>) ![](<../../.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 : Vous pouvez voir que les objets "_Flags_" sont composés par **name** et **value**. Ensuite, vous pouvez obtenir tous les noms et valeurs des flags avec la requête :
```javascript ```javascript
query={flags{name, value}} query={flags{name, value}}
``` ```
@ -203,11 +203,11 @@ Notez que dans le cas où l'**objet à interroger** est un **type primitif** com
![](<../../.gitbook/assets/image (958).png>) ![](<../../.gitbook/assets/image (958).png>)
Vous pouvez simplement interroger avec: Vous pouvez simplement interroger avec :
```javascript ```javascript
query={hiddenFlags} query={hiddenFlags}
``` ```
Dans un autre exemple où il y avait 2 objets à l'intérieur de l'objet de type "_Query_": "_user_" et "_users_".\ 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 pouvez **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 : Si ces objets n'ont pas besoin d'arguments pour être recherchés, vous pouvez **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 (880).png>) ![](<../../.gitbook/assets/image (880).png>)
@ -217,11 +217,11 @@ Cependant, dans cet exemple, si vous essayez de le faire, vous obtenez cette **e
![](<../../.gitbook/assets/image (1042).png>) ![](<../../.gitbook/assets/image (1042).png>)
On dirait qu'il va rechercher en utilisant l'argument "_**uid**_" de type _**Int**_.\ 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 avait é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}}}}}}}` Quoi qu'il en soit, nous savions déjà que, dans la section [Énumération de base](graphql.md#basic-enumeration), une requête avait é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'**argument** "_**uid**_" de type _Int_. Si vous lisez l'image fournie lorsque j'ai exécuté cette requête, vous verrez que "_**user**_" avait l'**argument** "_**uid**_" de type _Int_.
Ainsi, en effectuant une légère attaque par force brute sur l'_**uid**_, j'ai découvert qu'avec _**uid**=**1**_, un nom d'utilisateur et un mot de passe ont été récupérés :\ 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}}` `query={user(uid:1){user,password}}`
![](<../../.gitbook/assets/image (90).png>) ![](<../../.gitbook/assets/image (90).png>)
@ -240,7 +240,7 @@ Si vous pouvez rechercher par un type chaîne de caractères, comme : `query={th
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. 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 : Vous pouvez **rechercher** des personnes **par** le **nom** et obtenir leurs e-mails :
```javascript ```javascript
{ {
searchPerson(name: "John Doe") { searchPerson(name: "John Doe") {
@ -273,7 +273,7 @@ name
} }
}r }r
``` ```
Ou même **relations entre plusieurs objets différents en utilisant des alias** : Ou même **relations de plusieurs objets différents en utilisant des alias** :
```javascript ```javascript
{ {
johnsMovieList: searchPerson(name: "John Doe") { johnsMovieList: searchPerson(name: "John Doe") {
@ -319,7 +319,7 @@ rating
``` ```
**Notez comment les valeurs et le type de données sont indiqués dans la requête.** **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. 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 ```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"}]) {
@ -354,9 +354,9 @@ Comme expliqué dans [**l'une des vulnérabilités décrites dans ce rapport**](
### Force brute par lots en 1 requête API ### Force brute par lots en 1 requête API
Ces informations ont été prises sur [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\ Ces informations ont été prises sur [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
L'authentification via l'API GraphQL en **envoyant 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 login/mot de passe par requête HTTP en raison de la fonctionnalité de lotissement de 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. L'authentification via l'API GraphQL en **envoyant 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 login/mot de passe par requête HTTP en raison de la fonctionnalité de lotissement de 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**. De toute évidence, il est possible d'en envoyer des milliers en une seule requête de la même manière : Ci-dessous, vous trouverez la démonstration la plus simple d'une demande d'authentification d'application, avec **3 paires d'email/mot de passe différents à la fois**. De toute évidence, il est possible d'en envoyer des milliers en une seule requête de la même manière :
![](<../../.gitbook/assets/image (1081).png>) ![](<../../.gitbook/assets/image (1081).png>)
@ -368,15 +368,13 @@ Comme nous pouvons le voir sur la capture d'écran de la réponse, les première
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 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). 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** à 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?). Une **liste de mots** utile pour découvrir les [**entités GraphQL peut être trouvée ici**](https://github.com/Escape-Technologies/graphql-wordlist?).
### Contourner les défenses d'introspection GraphQL <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a> ### Contourner les défenses d'introspection GraphQL <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
### **Contourner les 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 :
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 négligences 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 ```bash
# Example with newline to bypass # Example with newline to bypass
{ {
@ -408,7 +406,7 @@ Notez que les requêtes GraphQL sont généralement envoyées via des requêtes
```javascript ```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"} {"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** au format **`form-urlencoded` :** Cependant, la plupart des points d'extrémité GraphQL prennent également en charge les requêtes POST **`form-urlencoded` :**
```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
``` ```
@ -418,7 +416,7 @@ Cependant, notez que la nouvelle valeur par défaut du cookie pour le drapeau `s
Notez qu'il est généralement possible d'envoyer la **requête** **query** également en tant que requête **GET et que le jeton CSRF pourrait ne pas être validé dans une requête GET.** Notez qu'il est généralement possible d'envoyer la **requête** **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. 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). Pour plus d'informations, consultez le [**message original ici**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
@ -428,7 +426,7 @@ De nombreuses fonctions GraphQL définies sur l'endpoint pourraient uniquement v
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). 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'un autre compte. Une mutation pourrait même entraîner une prise de contrôle de compte en essayant de modifier d'autres données de compte.
```javascript ```javascript
{ {
"operationName":"updateProfile", "operationName":"updateProfile",
@ -440,19 +438,19 @@ Une mutation pourrait même entraîner une prise de contrôle de compte en essay
[Chainer des requêtes](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) peut contourner un système d'authentification faible. [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. 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'enregistre en tant que nouvel utilisateur.
<figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure> <figure><img src="../../.gitbook/assets/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
## Contournement des limites de taux en utilisant des alias en GraphQL ## Contournement des limites de taux en utilisant des alias en GraphQL
En 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 portant le même nom. En GraphQL, les alias sont une fonctionnalité puissante qui permet de **nommer explicitement des propriétés** lors de la réalisation 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 portant 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). 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 le but 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 l'inclusion de plusieurs requêtes dans une seule requête HTTP, ils peuvent contourner de telles mesures de limitation de taux. 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 limitant 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 l'inclusion de 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 la limitation de taux car elle regroupe plusieurs requêtes en une seule requête HTTP, permettant potentiellement de vérifier simultanément de nombreux codes de réduction. 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 la limitation 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 ```bash
# Example of a request utilizing aliased queries to check for valid discount codes # Example of a request utilizing aliased queries to check for valid discount codes
query isValidDiscount($code: Int) { query isValidDiscount($code: Int) {
@ -471,11 +469,13 @@ valid
### Scanners de vulnérabilités ### 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://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop) : Testez les mauvaises configurations courantes des points de terminaison graphql
* [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/dolevf/graphw00f](https://github.com/dolevf/graphw00f) : Identifiez l'utilisation de graphql
* [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap) : Peut être utilisé en tant que client CLI pour automatiser les attaques. * [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler) : Ensemble d'outils pouvant être utilisé pour extraire 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é seul ou en tant qu'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://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 de 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. * [https://github.com/doyensec/inql](https://github.com/doyensec/inql) : Extension Burp pour des tests GraphQL avancés. Le composant _**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 des limites de taux mal implémentées.
### Clients ### Clients