Pourquoi il vaut la peine de tester des applications pour les conditions de course

Si votre application ou service fonctionne avec une devise interne, vous devez le tester pour des vulnérabilités de condition de concurrence («condition de concurrence» ou, plus précisément, «incertitude de concurrence»). La condition de course est un "bug flottant" qui peut être exploité par des attaquants. L'essentiel est que, grâce à l'exécution de code parallèle, vous pouvez accéder à la devise interne de l'application, la manipuler et, si vous le souhaitez, causer des dommages financiers tangibles au propriétaire du service. Nous avons récemment découvert ce problème avec l'un de nos clients et avons aidé à le résoudre.







Qu'est-ce qu'une condition de course



Étant donné que les développeurs oublient souvent que le code peut être exécuté par plusieurs threads en même temps, ils ne testent pas le produit pour une condition de concurrence, bien que cette erreur soit assez courante.



Du point de vue du backend, cela ressemble à ceci: plusieurs threads accèdent simultanément à la même ressource partagée: des variables ou des fichiers pour lesquels il n'y a pas de blocage ou de synchronisation. Cela conduit à une sortie de données incohérente.



Voici un exemple concret d'une telle vulnérabilité. Disons que nous avons une application qui vous permet de transférer des bonus entre des portefeuilles de paiement. L'attaquant a deux portefeuilles - A et B, et chacun d'eux a 1000 bonus. Le diagramme montre comment en manipulant l'heure d'envoi d'une demande de transaction, un attaquant peut augmenter le montant du transfert sur son compte et faire 10 bonus sur 20.







Il existe des outils automatiques pour rechercher de telles vulnérabilités. Par exemple, RacePWN, qui en un minimum de temps envoie de nombreuses requêtes HTTP au serveur et accepte la configuration json en entrée, facilitant ainsi le processus d'attaque des cybercriminels. Cela se fait manuellement en envoyant des requêtes POST.



Condition de race mortelle



Aux États-Unis, de juin 1985 à janvier 1987, une erreur de condition de course dans un appareil de radiothérapie Therac-25 créé par l'organisme d'État canadien Énergie atomique du Canada limitée (EACL) a causé six surdoses de radiation . Les victimes ont reçu des doses de dizaines de milliers de joyeux. Le niveau de 1000 est considéré comme mortel. Après les brûlures qui en ont résulté, les victimes sont décédées en quelques semaines. Un seul patient a réussi à survivre.



Les modèles Therac précédents avaient des mécanismes de protection matérielle: des circuits de blocage indépendants qui contrôlent le faisceau d'électrons; bloqueurs mécaniques; disjoncteurs matériels; débrancher les fusibles. La protection matérielle a été supprimée dans Therac-25. Le logiciel était responsable de la sécurité. L'appareil avait plusieurs modes de fonctionnement et, en raison d'une erreur de condition de course, le médecin ne comprenait parfois pas dans quel mode l'appareil fonctionne réellement. Au cours de la procédure judiciaire, il s'est avéré que le logiciel Therac-25 avait été développé par un programmeur, mais EACL n'avait pas d'informations sur qui exactement.



À la suite de ce processus, le gouvernement américain a sérieusement resserré les exigences relatives à la conception et à l'exploitation de systèmes dont la sécurité est essentielle pour les personnes.



Comment se protéger



Le moyen le plus simple et le moins cher de résoudre le problème des conditions de concurrence consiste à concevoir correctement l'architecture de l'application. Voici ce qu'il faut prévoir pour cela.



  • Verrouillage des enregistrements critiques dans la base de données. Il existe différentes manières de vous assurer de travailler avec l'enregistrement d'un flux à un moment donné. L'essentiel est de ne rien bloquer d'inutile.
  • Isolement des transactions dans la base de données , ce qui garantit que les transactions sont validées de manière séquentielle. Le plus important ici est de trouver un équilibre entre sécurité et vitesse.
  • . . , , , . , , , .




Notre client est un magasin de livraison d'épicerie en ligne qui prend en charge la fonction de fournir des remises à l'aide de coupons. Lors des tests, nous avons découvert une vulnérabilité - lors de l'envoi d'une requête POST avec une valeur de coupon. En envoyant une demande avec des délais différents, il était possible d'obtenir une réduction deux fois. Apparemment, les développeurs ont commis une erreur grossière liée à l'accès partagé à l'objet identifié lors de l'achat.



Il y avait très probablement un tel pseudo-code sans mécanismes de synchronisation:



1 Si promo_flag n'est pas défini:

2 Price = get_price ()

3 Price - = price * promo_percent;

4 set_price (prix)

5 set_promo_flag ()

...

Ici, appliquer un code promo et définir le drapeau approprié n'est pas une opération atomique. Très probablement, lorsque la deuxième application du code promotionnel a commencé, la première s'est arrêtée sur la 5ème ligne (c'est-à-dire qu'elle n'a pas encore été exécutée). À ce moment, la fonction get_price () de la deuxième ligne a renvoyé une nouvelle valeur de prix, déjà avec une remise.



Décision



Le problème est résolu simplement:



1 acqure_mutex ()

2 Si promo_flag n'est pas défini:

3 Price = get_price ()

4 Price - = price * promo_percent;

5 set_price (price)

6 set_promo_flag ()

7 release_mutex ()

...

Maintenant, l'application du code promo sera effectuée complètement et complètement une fois. Même lorsqu'une situation survient dans laquelle le deuxième thread essaie d'appliquer le code promotionnel alors que le premier processus est déjà occupé avec le traitement, il ne pourra pas le faire. Le mutex bloquera l'accès à la "section critique", et le second processus devra attendre que le premier soit terminé.



La condition de race ne doit pas être sous-estimée. Mieux vaut consacrer du temps et des ressources à la recherche de vulnérabilités afin d'éviter des conséquences imprévues, y compris sur le budget de l'entreprise.






Blog ITGLOBAL.COM - Managed IT, clouds privés, IaaS, services de sécurité de l'information pour les entreprises:






All Articles