Utilisez [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) pour créer facilement et **automatiser des flux de travail** alimentés par les outils communautaires les plus avancés au monde.\
* Vous travaillez dans une **entreprise de cybersécurité** ? Vous souhaitez voir votre **entreprise annoncée dans HackTricks** ? ou souhaitez-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) !
* **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).
Le principal problème de l'exploitation des conditions de course est que vous avez besoin que les requêtes soient traitées en parallèle avec une très courte différence de temps (généralement >1ms). Dans la section suivante, différentes solutions sont proposées pour rendre cela possible.
L'utilisation d'un seul paquet TCP élimine complètement l'effet du jitter du réseau, il y a donc clairement un potentiel pour les attaques par condition de course. Cependant, **deux requêtes ne suffisent pas pour une attaque de course fiable** grâce au **jitter côté serveur** - variations du temps de traitement des requêtes de l'application causées par des variables incontrôlables telles que la contention du processeur.
Mais, en utilisant la technique de '**synchronisation du dernier octet**' d'HTTP/1.1, il est possible d'envoyer préalablement la majeure partie des données en retenant un petit fragment de chaque requête, puis de 'compléter' **20 à 30 requêtes avec un seul paquet TCP**.
- Si la requête n'a pas de corps, envoyez tous les en-têtes, mais ne définissez pas le drapeau END\_STREAM. Retenez un cadre de données vide avec le drapeau END\_STREAM défini.
- Si la requête a un corps, envoyez les en-têtes et toutes les données du corps sauf le dernier octet. Retenez un cadre de données contenant le dernier octet.
- Attendez 100 ms pour vous assurer que les trames initiales ont été envoyées.
- Assurez-vous que TCP\_NODELAY est désactivé - il est crucial que l'algorithme de Nagle regroupe les trames finales.
- Envoyez un paquet ping pour réchauffer la connexion locale. Si vous ne le faites pas, la pile réseau du système d'exploitation placera la première trame finale dans un paquet séparé.
Notez que cela **ne fonctionne pas pour les fichiers statiques** sur certains serveurs, mais les fichiers statiques ne sont pas pertinents pour les attaques par condition de course. Mais les fichiers statiques sont sans importance pour les attaques RC.
En utilisant cette technique, vous pouvez faire en sorte que 20 à 30 requêtes arrivent simultanément sur le serveur - indépendamment du jitter du réseau :
Il est important de noter que de nombreuses applications se trouvent derrière un serveur frontal, et celui-ci peut décider de transférer certaines requêtes sur des connexions existantes vers l'arrière-plan, et de créer de nouvelles connexions pour d'autres.
Par conséquent, il est important de ne pas attribuer des délais de requête incohérents au comportement de l'application, tel que des mécanismes de verrouillage qui n'autorisent qu'un seul thread à accéder à une ressource à la fois. De plus, le routage des requêtes côté frontal est souvent effectué sur une base de connexion, vous pouvez donc lisser le délai des requêtes en effectuant un préchauffage de la connexion côté serveur - **envoyer quelques requêtes insignifiantes sur votre connexion avant de lancer l'attaque** (il s'agit simplement d'envoyer plusieurs requêtes avant de commencer l'attaque proprement dite).
#### Mécanismes de verrouillage basés sur la session <a href="#session-based-locking-mechanisms" id="session-based-locking-mechanisms"></a>
Certains frameworks tentent de prévenir la corruption accidentelle des données en utilisant une forme de **verrouillage de requête**. Par exemple, le module de gestionnaire de session natif de **PHP ne traite qu'une seule requête par session à la fois**.
Il est extrêmement important de repérer ce type de comportement, car il peut masquer des vulnérabilités facilement exploitables. Si vous remarquez que toutes vos requêtes sont traitées séquentiellement, essayez de les envoyer chacune avec un jeton de session différent.
#### **Abus des limites de taux ou de ressources**
Si le réchauffement de la connexion ne fait aucune différence, il existe différentes solutions à ce problème.
En utilisant Turbo Intruder, vous pouvez introduire un léger délai côté client. Cependant, comme cela implique de diviser vos requêtes d'attaque réelles en plusieurs paquets TCP, vous ne pourrez pas utiliser la technique d'attaque en un seul paquet. Par conséquent, sur des cibles à forte gigue, l'attaque est peu susceptible de fonctionner de manière fiable, quel que soit le délai que vous définissez.
Les serveurs Web retardent souvent le traitement des requêtes s'il en est envoyé trop rapidement. En envoyant un grand nombre de requêtes factices pour déclencher intentionnellement la limite de taux ou de ressources, vous pouvez provoquer un délai approprié côté serveur. Cela rend l'attaque en un seul paquet viable même lorsque l'exécution retardée est nécessaire.
Pour plus d'informations sur cette technique, consultez le rapport original sur [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
* **Tubo Intruder - Attaque en un seul paquet HTTP2 (1 point d'extrémité)**: Vous pouvez envoyer la requête à **Turbo intruder** (`Extensions` -> `Turbo Intruder` -> `Send to Turbo Intruder`), vous pouvez modifier dans la requête la valeur que vous souhaitez forcer pour **`%s`** comme dans `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` puis sélectionnez **`examples/race-single-packer-attack.py`** dans la liste déroulante :
Si le site web ne prend pas en charge HTTP2 (seulement HTTP1.1), utilisez `Engine.THREADED` ou `Engine.BURP` à la place de `Engine.BURP2`.
{% endhint %}
* **Tubo Intruder - Attaque à un seul paquet HTTP2 (Plusieurs points d'extrémité)**: Si vous avez besoin d'envoyer une requête à un point d'extrémité, puis plusieurs à d'autres points d'extrémité pour déclencher l'exécution de code à distance (RCE), vous pouvez modifier le script `race-single-packet-attack.py` comme suit:
* Il est également disponible dans **Repeater** via la nouvelle option '**Envoyer le groupe en parallèle**' dans Burp Suite.
* Pour **dépasser la limite**, vous pouvez simplement ajouter la **même requête 50 fois** dans le groupe.
* Pour **chauffer la connexion**, 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 deux étapes de sous-états, vous pouvez **ajouter des requêtes supplémentaires entre** les deux requêtes.
* Pour un RC à **multi-point d'extrémité**, vous pouvez commencer par envoyer la **requête** qui **va vers l'état caché** puis **50 requêtes** juste après qui **exploitent l'état caché**.
Avant les recherches précédentes, voici quelques charges utiles utilisées qui tentaient simplement d'envoyer les paquets aussi rapidement que possible pour provoquer un RC.
* **Intruder**: Envoyez la **requête** à **Intruder**, définissez le **nombre de threads** sur **30** dans le menu **Options**, sélectionnez comme charge utile **Null payloads** et générez **30**.
La bibliothèque `asyncio` de Python est utilisée pour écrire du code asynchrone de manière concurrente. Elle permet d'exécuter des tâches en parallèle, ce qui est particulièrement utile pour les opérations d'entrée/sortie (I/O) intensives, telles que les requêtes réseau.
L'asynchronisme est un concept clé dans la programmation concurrente, car il permet d'exécuter plusieurs tâches en même temps sans bloquer l'exécution du programme. Cela signifie que les tâches peuvent être exécutées de manière indépendante et que le programme peut passer à autre chose pendant que les tâches sont en cours d'exécution.
La bibliothèque `asyncio` utilise des coroutines pour gérer les tâches asynchrones. Une coroutine est une fonction spéciale qui peut être suspendue et reprise ultérieurement. Cela permet d'exécuter plusieurs coroutines en parallèle, ce qui facilite la gestion des tâches asynchrones.
L'un des avantages de `asyncio` est qu'il permet de gérer facilement les problèmes de concurrence, tels que les conditions de course. Une condition de course se produit lorsqu'il y a un conflit entre plusieurs tâches qui tentent d'accéder ou de modifier une ressource partagée en même temps. Cela peut entraîner des résultats imprévisibles ou indésirables.
Pour éviter les conditions de course, `asyncio` fournit des mécanismes tels que les verrous (locks) et les sémaphores. Ces mécanismes permettent de synchroniser l'accès aux ressources partagées, en garantissant qu'une seule tâche peut y accéder à la fois.
En résumé, la bibliothèque `asyncio` de Python est un outil puissant pour écrire du code asynchrone et gérer les problèmes de concurrence tels que les conditions de course. Elle facilite l'exécution de tâches en parallèle et permet d'améliorer les performances des applications qui effectuent des opérations d'entrée/sortie intensives.
Il s'agit du type le plus basique de condition de concurrence où des **vulnérabilités** apparaissent dans des endroits qui **limitent le nombre de fois où vous pouvez effectuer une action**. Par exemple, utiliser plusieurs fois le même code de réduction dans une boutique en ligne. 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 bogue**](https://hackerone.com/reports/759247)**.**
Les RC les plus complexes exploiteront des **sous-états dans l'état de la machine** qui pourraient permettre à un attaquant d'**abuser** d'états auxquels il n'était **jamais censé avoir accès**, mais il existe une **petite fenêtre** pour que l'attaquant y accède.
La première étape consiste à identifier tous les points d'extrémité qui écrivent ou lisent des données à partir de ceux-ci, puis utilisent ces données pour quelque chose d'important. Par exemple, les utilisateurs peuvent être stockés dans une table de base de données qui est modifiée lors de l'inscription, de la modification du profil, de l'initiation de la réinitialisation du mot de passe et de la finalisation de la réinitialisation du mot de passe.
Nous pouvons utiliser trois questions clés pour exclure les points d'extrémité qui sont peu susceptibles de provoquer des collisions. Pour chaque objet et les points d'extrémité associés, demandez-vous :
Les données stockées dans une structure de données côté serveur persistante sont idéales pour l'exploitation. Certains points d'extrémité stockent leur état entièrement côté client, comme les réinitialisations de mot de passe qui fonctionnent en envoyant un JWT par e-mail - ceux-ci peuvent être ignorés en toute sécurité.
Les applications stockent souvent certains états dans la session utilisateur. Ceux-ci sont souvent quelque peu protégés contre les sous-états - nous en parlerons plus tard.
Les opérations qui modifient des données existantes (comme le changement de l'adresse e-mail principale d'un compte) ont un potentiel de collision important, tandis que les actions qui se contentent d'ajouter des données existantes (comme l'ajout d'une adresse e-mail supplémentaire) sont peu susceptibles d'être vulnérables à autre chose qu'à des attaques de dépassement de limite.
La plupart des points d'extrémité fonctionnent sur un enregistrement spécifique, qui est recherché à l'aide d'une « clé », telle qu'un nom d'utilisateur, un jeton de réinitialisation de mot de passe ou un nom de fichier. Pour une attaque réussie, nous avons besoin de deux opérations qui utilisent la même clé. Par exemple, imaginons deux implémentations plausibles de réinitialisation de mot de passe :
À ce stade, il est temps de **lancer des attaques RC** sur les points d'extrémité potentiellement intéressants pour essayer de trouver des résultats inattendus par rapport aux résultats habituels. **Toute déviation de la réponse attendue**, telle qu'un changement dans une ou plusieurs réponses, ou un effet de second ordre tel que des contenus d'e-mail différents ou un changement visible dans votre session, pourrait être un indice indiquant un problème.
Lorsque vous envoyez un lot de requêtes, vous pouvez constater qu'une paire de requêtes initiale déclenche un état final vulnérable, mais que les requêtes ultérieures l'écrasent/invalident et que l'état final n'est pas exploitable. Dans ce scénario, vous voudrez éliminer toutes les requêtes inutiles - deux devraient suffire pour exploiter la plupart des vulnérabilités. Cependant, passer à deux requêtes rendra l'attaque plus sensible au timing, vous devrez donc peut-être réessayer l'attaque plusieurs fois ou l'automatiser.
Parfois, vous ne trouverez peut-être pas de conditions de concurrence, mais les **techniques de livraison de requêtes avec une synchronisation précise** peuvent toujours révéler la présence d'autres vulnérabilités.
Un exemple est lorsque des **horodatages haute résolution sont utilisés au lieu de chaînes aléatoires cryptographiquement** sécurisées pour générer des jetons de sécurité.
Considérons un **jeton de réinitialisation de mot de passe qui n'est aléatoire qu'à l'aide d'un horodatage**. Dans ce cas, il pourrait être possible de **déclencher deux réinitialisations de mot de passe pour deux utilisateurs différents**, qui utilisent tous deux le **même jeton**. Il vous suffit de synchroniser les requêtes de manière à ce qu'elles génèrent le même horodatage.
{% hint style="warning" %}
Pour confirmer par exemple la situation précédente, vous pourriez simplement demander **2 jetons de réinitialisation de mot de passe en même temps** (en utilisant une attaque à paquet unique) et vérifier s'ils sont **identiques**.
Consultez [**l'exemple dans ce laboratoire**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities).
[**Consultez ce laboratoire**](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** pour lequel vous n'aurez pas besoin de payer.
L'idée est de **vérifier une adresse e-mail et de la changer en une autre en même temps** pour savoir si la plateforme vérifie la nouvelle adresse modifiée.
### Changer l'e-mail en 2 adresses e-mail basées sur les cookies
Selon [**cet article**](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'un e-mail à l'autre**.
Vous pouvez également consulter [**ce laboratoire**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) pour en savoir plus à ce sujet.
### É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 existe une petite période de temps où **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**, puis 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**.
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 confirmer un compte dont vous ne contrôlez pas l'e-mail.
Consultez [**ce laboratoire**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) pour voir un exemple.
### Contourner l'authentification à deux facteurs (2FA)
Comme vous pouvez le voir, il s'agit en fait d'une **séquence en plusieurs étapes dans le cadre d'une seule requête**. Plus important encore, elle passe par un sous-état dans lequel l'utilisateur dispose temporairement d'une session valide connectée, **mais où la MFA n'est pas encore appliquée**. Un attaquant pourrait potentiellement exploiter cela en envoyant une demande de connexion accompagnée d'une demande à un point de terminaison sensible et authentifié.
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 enregistrés auprès du fournisseur. Pour ce faire, le **client** devra **autoriser votre application** à accéder à certaines de leurs données à l'intérieur du **fournisseur OAuth**.\
Jusqu'ici, il s'agit simplement d'une connexion classique avec Google/LinkedIn/GitHub... où vous êtes invité avec une page indiquant : "_L'application \<InsertCoolName> souhaite accéder à vos informations, voulez-vous l'autoriser ?_"
Le **problème** survient lorsque vous **l'acceptez** et envoyez automatiquement un **`authorization_code`** à l'application malveillante. Ensuite, cette **application exploite une course condition dans le fournisseur de services OAuth pour générer plus d'un AT/RT** (_Authentication Token/Refresh Token_) à partir du **`authorization_code`** pour votre compte. Fondamentalement, elle exploitera le fait que vous avez accepté l'application pour accéder à vos données afin de **créer plusieurs comptes**. Ensuite, si vous **arrêtez d'autoriser l'application à accéder à vos données, une paire AT/RT sera supprimée, mais les autres resteront valides**.
Une fois que vous avez **obtenu un RT valide**, vous pouvez essayer de **l'exploiter 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**.
* Vous travaillez dans une **entreprise de cybersécurité** ? Vous souhaitez voir votre **entreprise annoncée dans HackTricks** ? ou souhaitez-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) !
* **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).
Utilisez [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) pour créer et **automatiser facilement des workflows** alimentés par les outils communautaires les plus avancés au monde.\