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 des variations de réseau, il y a donc clairement un potentiel pour des attaques par condition de course. Cependant, **deux requêtes ne suffisent pas pour une attaque par condition de course fiable** grâce à la **variation côté serveur** - des variations dans le 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 cadres initiaux ont été envoyés.
- Assurez-vous que TCP\_NODELAY est désactivé - il est crucial que l'algorithme de Nagle regroupe les cadres finaux.
- Envoyez un paquet de ping pour réchauffer la connexion locale. Si vous ne le faites pas, la pile réseau du système d'exploitation placera le premier cadre final 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 des variations 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 court 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** à **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 appels réseau.
L'asynchronisme est basé sur le concept de coroutines, qui sont des fonctions spéciales pouvant être suspendues et reprises ultérieurement. Cela permet d'éviter les blocages et d'optimiser l'utilisation des ressources.
`asyncio` fournit également des primitives pour gérer les événements, les boucles d'événements et les tâches. Les événements sont des objets qui se produisent lorsqu'une opération asynchrone est terminée, tandis que les boucles d'événements sont responsables de l'exécution des coroutines et de la gestion des événements.
Pour utiliser `asyncio`, vous devez définir des coroutines en utilisant le mot-clé `async` et les exécuter dans une boucle d'événements à l'aide de la fonction `run_until_complete`. Vous pouvez également utiliser des mots-clés tels que `await` pour suspendre l'exécution d'une coroutine jusqu'à ce qu'une opération asynchrone soit terminée.
Voici un exemple simple d'utilisation de `asyncio` pour effectuer une requête HTTP asynchrone :
```python
import asyncio
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
url = "https://example.com"
response = await fetch(url)
print(response)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
```
Dans cet exemple, la fonction `fetch` est une coroutine qui utilise la bibliothèque `aiohttp` pour effectuer une requête HTTP asynchrone. La fonction `main` est également une coroutine qui appelle `fetch` et attend la réponse. Enfin, la boucle d'événements exécute la coroutine `main` jusqu'à ce qu'elle soit terminée.
`asyncio` est un outil puissant pour écrire du code asynchrone en Python, ce qui peut améliorer les performances et l'efficacité de vos applications.
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 que 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 réguliers. **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 disant : "_L'application \<InsertCoolName> souhaite accéder à vos informations, voulez-vous l'autoriser ?_"
Le **problème** survient lorsque vous **l'acceptez** et envoie automatiquement un **`authorization_code`** à l'application malveillante. Ensuite, cette **application exploite une condition de concurrence 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.\