IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Une faille de sécurité critique, baptisée "BatBadBut", a été découverte dans la bibliothèque standard Rust
Mais elle affecte également Erlang, Go, Haskell, Java, Node.js, PHP, Python et Ruby

Le , par Anthony

130PARTAGES

10  0 
Une faille de sécurité critique, baptisée "BatBadBut", a été découverte entre autres dans la bibliothèque standard Rust, affectant toutes les versions antérieures à 1.77.2 sous Windows. La vulnérabilité, identifiée comme CVE-2024-24576, a un score CVSS de 10.0 et permet à un attaquant d'exécuter des commandes shell arbitraires en contournant le mécanisme d'échappement lors de l'invocation de fichiers batch avec l'API Command.

La vulnérabilité "BatBadBut" a été découverte par le chercheur en sécurité RyotaK et divulguée de manière responsable à l'équipe de sécurité de Rust, qui a donc expliqué comment l'équipe Rust a géré l'alerte, et patché la faille, ce qui n'est pas encore le cas sur tous les autres langages affectés.


Selon le billet de blog de RyotaK, le problème provient des règles complexes d'analyse de cmd.exe, l'invite de commande de Windows, qui est implicitement lancée lors de l'exécution de fichiers batch. La bibliothèque standard Rust ne parvient pas à échapper correctement les arguments de commande pour cmd.exe, ce qui permet l'injection potentielle de commandes.

Alors que les API Command::arg et Command::args de Rust garantissent que les arguments seront transmis tels quels au processus créé et ne seront pas évalués par un shell, la mise en œuvre sous Windows est plus complexe.

L'API Windows ne fournit qu'une seule chaîne de caractères contenant tous les arguments, laissant au processus créé la responsabilité de les diviser. La plupart des programmes utilisent la chaîne d'exécution standard argv en C, ce qui permet d'obtenir un comportement cohérent en matière de division des arguments. Cependant, cmd.exe possède sa propre logique de découpage des arguments, qui nécessite un échappement personnalisé par la bibliothèque standard Rust.

"Pour éviter l'exécution inattendue de fichiers batch, vous devriez envisager de déplacer les fichiers batch dans un répertoire qui n'est pas inclus dans la variable d'environnement PATH.", a noté RyotaK dans son billet de blog. "Dans ce cas, les fichiers batch ne seront pas exécutés à moins que le chemin d'accès complet ne soit spécifié, ce qui permet d'éviter l'exécution inattendue de fichiers batch."

L'équipe de sécurité de Rust a reconnu que la logique d'échappement existante dans la bibliothèque standard était insuffisante, ce qui permettait à des arguments malveillants de contourner l'échappement et d'entraîner une exécution arbitraire de l'interpréteur de commandes. La gravité de la vulnérabilité "BatBadBut" est considérée comme critique si des arguments non fiables sont transmis lors de l'invocation de fichiers batch sous Windows.

BatBadBut ne se limite pas à un seul identifiant CVE

Alors que l'attention s'est d'abord portée sur le langage de programmation Rust, il est apparu que la vulnérabilité "BatBadBut" ne se limite pas à un seul identifiant CVE. La vulnérabilité affecte plusieurs langages de programmation et outils, chacun se voyant attribuer un identifiant CVE différent en fonction de la mise en œuvre et de l'impact spécifiques.


Outre CVE-2024-24576, qui concerne la bibliothèque standard Rust, "BatBadBut" englobe également CVE-2024-1874, CVE-2024-22423 (qui affecte yt-dlp avec un score de risque élevé de 8,3) et CVE-2024-3566 (qui affecte Haskell, Node.js, Rust, PHP et yt-dlp). Cela met en évidence la nature étendue de la vulnérabilité et la nécessité pour les développeurs d'évaluer leurs applications et dépendances à travers différents langages de programmation et outils.

Atténuation

Pour remédier à la vulnérabilité "BatBadBut", l'équipe Rust a publié la version 1.77.2, qui inclut un correctif pour le problème. Ce correctif améliore la robustesse du code d'échappement et modifie l'API Command pour qu'elle renvoie une erreur InvalidInput lorsqu'elle ne peut pas échapper un argument en toute sécurité. Cette erreur sera émise lors du lancement du processus.

Pour les développeurs qui implémentent leur propre échappement ou qui ne gèrent que des entrées fiables sous Windows, la méthode CommandExt::raw_arg peut être utilisée pour contourner la logique d'échappement de la bibliothèque standard.

Il est important de noter que la vulnérabilité n'affecte que le code Rust fonctionnant sous Windows qui exécute des fichiers batch avec des arguments non fiables. Les autres plateformes ou utilisations de Windows ne sont pas concernées.

La communauté Rust a exprimé sa gratitude à RyotaK pour avoir divulgué la vulnérabilité de manière responsable, à Simon Sawicki (Grub4K) pour avoir identifié certaines des règles d'échappement adoptées, et aux membres du projet Rust qui ont aidé à développer le correctif, à le réviser et à coordonner le processus de divulgation.

Il est fortement conseillé aux développeurs utilisant Rust sur Windows de mettre à jour vers la version 1.77.2 dès que possible afin de réduire le risque d'attaques potentielles par injection de commandes. Il est essentiel de s'assurer que les entrées non fiables sont correctement validées et assainies avant d'être transmises en tant qu'arguments à des fichiers batch.

État des lieux sur les autres langages de programmation affectés


Sources : Équipe Rust, "BatBadBut: You can't securely execute commands on Windows" (RyotaK, chercheur en sécurité)

Et vous ?

Quelle lecture faites-vous de cette situation ?

Voir aussi :

Comment Rust améliore la sécurité de son écosystème : la Rust Foundation publie un rapport sur ce que leur initiative de sécurité a accompli au cours des six derniers mois de 2023

« Choisir Rust est opter pour une meilleure sécurisation des logiciels qu'avec le C, mais une efficacité énergétique et une performance d'exécution que seul le C offre », d'après l'équipe AWS

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de Fagus
Membre expert https://www.developpez.com
Le 12/04/2024 à 16:01
En fait c'est plus un défaut de conception dans cmd.exe qui oblige les langages à contourner le défaut de manière alambiquée.

Citation Envoyé par RyotaK
However, when you execute the following command on the command prompt, calc.exe will be executed:

echo ""&calc.exe"

So, the following command spawns calc.exe when executed on PowerShell:

cmd.exe /c 'echo "%CMDCMDLINE:~-1%&calc.exe"
5  0 
Avatar de Uther
Expert éminent sénior https://www.developpez.com
Le 13/04/2024 à 6:39
En effet, ou pour être plus précis, le défaut vient de la fonction CreateProcess de l'API de Windows qui fait insidieusement appel à cmd.exe quand le fichier exécuté est un fichier de commande (de type bat ou cmd). Cela à pour conséquence que les arguments ne sont plus traités comme tels, mais comme une ligne d'un fichier batch à exécuter.

Le principal problème vient du fait que ce comportement est mal documenté par Microsoft. La documentation MSDN actuelle n'indique pas du tout le comportement spécifique dans le cas des fichiers de commande. Au contraire elle indique que pour exécuter un fichier de commande, il faut invoquer cmd.exe manuellement.
4  0 
Avatar de Uther
Expert éminent sénior https://www.developpez.com
Le 18/04/2024 à 8:39
Citation Envoyé par OuftiBoy Voir le message
Je n'ai pas tout compris (j'ai pas eu le temps de gratter), mais dire que c'est la faute de cmd.exe, parce qu'il fait les choses différemment, me semble un rien douteux... Le fond du problème, c'est que les développeurs ont utilisé quelque chose qu'ils ne maîtrisaient pas. Un rien de bon sens, si on ne sait pas comment se comporte quelque, on teste ou on utilise pas.
C'est assez ironique d'avouer ne pas très bien comprendre le problème dont on parle, et en même temps de conclure que le problème vient des développeurs qui ne comprennent pas bien l’outil qu'ils utilisent.

Plus sérieusement, bien sur que les développeurs se doivent de maitriser les API qu'ils utilisent. Mais pour cela, encore faudrait-il qu'il puissent se renseigner sur leur comportement. Le fait que la fonction CreateProcess de l'API Win32 fasse appel à cmd.exe et surtout que les paramètres sont interprétés comme une ligne de commande, n'est pas documenté officielement.
Difficile de reprocher aux développeur de ne pas connaitre un comportement non documenté.

Citation Envoyé par OuftiBoy Voir le message
Pour en revenir à la faille, si c'était à cause de l'API de microsoft, c'est lui qui devrait réagir, non ? Ici, pleins de langages (mais pas tous) sont concernés et vont "faire autrement" pour éviter le problème. Comment ont fait les développeurs des langages non concernés ? Soit ils ont eu du bol, soit ils ont (bien) fait les choses.
Microsoft peut difficilement corriger ça sans risquer de casser la compatibilité.
Mais à défaut de corriger la fonction CreateProcess, ils devraient au moins correctement la documenter pour indiquer qu'elle fait appel à cmd.exe pour les fichiers de commande et que ça implique des règles d’échappement différentes et bien plus complexes.
3  0 
Avatar de Uther
Expert éminent sénior https://www.developpez.com
Le 15/04/2024 à 7:43
Le problème c'est justement que ça ne concerne pas que les fichiers externes. Si tu fais appel à un fichier de commande, même interne, avec des paramètres variables, tu peux tout à fait être concerné.
2  0 
Avatar de chrtophe
Responsable Systèmes https://www.developpez.com
Le 18/04/2024 à 18:07
Je vais prendre une métaphore. Tu te ballades dans la foret (dans ce cas, on pourrait dire la jungle), tu as faim, et tu vois un champignon. Tu n'as pas avec toi le "petit manuel des champignons dangereux" (et que même si tu l'as, tu ne trouve rien sur ce champignon), que fais-tu ? Perso, je ne mange pas le champignon... Remplace foret par développement, champignon par API, et le manuel par la documentation
L'analogie valable serait plutôt que le "petit manuel des champignons dangereux" te dise que tu peux manger ce champignon sans te préciser qu'il faut le faire bouillir avant. C'est ce qu'on appelle la documentation. si celle-ci est imprécise, l'API peut être mal utilisée.

Je n'avais pas compris le prob au départ, car pour moi je ne m'attendais pas à ce que createprocess appelle cmd (après je suis pas développeur), donc si je devais développer un programme appelant createprocess pourquoi je devrais formater les arguments comme si je passais par cmd ? Et après on va dire que c'est mon code qui est pas bon, alors que comme il n'est pas précisé dans la doc que je dois échapper les arguments comme si j'appelais cmd, je ne l'ai pas fait.
2  0 
Avatar de chrtophe
Responsable Systèmes https://www.developpez.com
Le 18/04/2024 à 20:55
Que je sois développeur ou non, j'ai accès à la même documentation technique. Le prob. n'est pas là.

Pour reprendre tes exemples :
Un garagiste tout compétent qu'il soit ne pourra pas correctement réparer ta voiture si il n'a pas accès à une documentation technique fiable, sauf si il a lui-même fabriqué le moteur.

Un médecin te prescris un médicament qui a pignon sur rue. Plusieurs années plus tard, on découvre que ce médicament provoque de graves problèmes, le médecin est responsable ?

Un développeur utilise un OS incluant des fonctions, si celle-ci ne sont pas correctement documentées, ou ne réagit pas comme documenté, on ne peut pas incriminer le développeur en question.
2  0 
Avatar de Uther
Expert éminent sénior https://www.developpez.com
Le 19/04/2024 à 23:14
Citation Envoyé par OuftiBoy Voir le message
Je conçois très bien que tout le monde ne travail pas sur des logiciel critiques, et que oui, il faut faire un minimum confiance.
Le cas du logiciel embarqué critique est particulier : on se limite à des OS assez simples avec une API minimale, voire pas d'OS du tout. On a forcément plus de contrôle des détails. Et encore, si tu te retrouves à travailler avec des OS comme VxWorks, ou similaire, je serais surpris que tu analyses systématiquement son comportement dans absolument tous les cas possibles pour t'assurer que la doc est correcte et exhaustive.

Pour le sujet en question, à savoir l'API Win32, c'est hors sujet. Si tu fais de l'embarqué en Rust, tu vas travailler en mode "no_std", où tu n’auras pas non plus de problème avec l'API Win32, vu que la bibliothèque standard est amputée de ses dépendances à l'OS.

Citation Envoyé par OuftiBoy Voir le message
Les "devs" responsables du compilateur, eux, j'ai du mal à leur trouver une excuse, même si ça peut arriver, personne n'est a l'abris de faire une bêtise. Mais quand même, ils livrent un outil "critique", puisque l'on va utiliser leur compilateur de part le monde.
Auditer la fiabilité de l'OS ne rentre pas dans le domaine de compétence d'un langage de programmation. Les dev de la bibliothèque standard de Rust ont utilisé l'API standard de Microsoft qu'ils n'avaient aucune raison particulière d'imaginer problématique, comme beaucoup d'autres l'ont fait depuis bien plus longtemps qu'eux sans que personne n'ait vu le problème.

Rust a beau prendre la sécurité au sérieux, ça reste un langage de programmation, il ne prétend pas être un outil magique qui résoudra tous les problèmes de sécurité possible à tous les niveaux.

Citation Envoyé par OuftiBoy Voir le message
Les "devs" responsables du compilateur, eux, j'ai du mal à leur trouver une excuse, même si ça peut arriver, personne n'est a l'abris de faire une bêtise. Mais quand même, ils livrent un outil "critique", puisque l'on va utiliser leur compilateur de part le monde. Certains langages et leur compilateur n'ont apparemment pas le soucis, c'est donc qu'ils ont chercher/trouver/compris la doc et/ou surement fait un test.
Tous les gens qui font appels à des fichiers de commande avec des paramètres manipulables par un tiers sont touchés par ce problème sous Windows, que le langage soit directement impliqué ou non :

Les langages qui ont eu des bulletins d’alertes sont ceux qui avaient mis en place une abstraction autour de CreateProcess censé fournir un échappement sécurisé des paramètres. Cet échappement ne fonctionnait pas dans le cas particulier des scripts de commande, ce qu'ils ont du corriger ou documenter.

Pour les langages qui n'ont pas eu de CVE, comme le C et le C++, ça n'est pas parce qu'ils ont anticipé quoi que ce soit, mais au contraire parce qu'ils ne font rien et laissent l'utilisateur appeler CreateProcess directement, ou quasi directement, sans fournir la moindre garantie. Il n'y a en effet rien à corriger au niveau du langage vu que c'est l'utilisateur qui doit faire l'échappement lui même. Cependant, comme le problème n’était pas vraiment connu, pas officiellement documenté, et pas facile à résoudre correctement, il est à peu près certain que aucun des utilisateurs actuels de CreateProcess, dans les cas qui posaient problème en Rust, ne l'utilise de manière sécurisée. Et vu que rien n'a changé pour les langages qui n'encapsulent pas les appel a CreateProcess, il est probable que la situation dure pour leurs utilisateurs, là où Rust protège maintenant contre ce type de problèmes.

Citation Envoyé par OuftiBoy Voir le message
Si je prends ton exemple avec l'image, le dev qui utilise un logiciel fait pour manipuler les images, il lui fait confiance. Il ne va pas tout vérifier, je l'accepte sans soucis.
J'ai juste pris ça comme exemple de comportement inattendu d'une API (peut importe qu'il soit malicieux ou non), difficile à anticiper, et qui ne constitue qu'un cas parmi une infinité de possibilité. On ne peut pas attendre de l'utilisateur d'une l'API, quelque soit sont niveau de technique, qu'il anticipe tous les cas non documentés possibles, c'est infini. S'il ne peut pas faire confiance au comportement décrit dans la documentation, la seule solution serait d'auditer le code, mais ça n'est clairement pas le boulot du créateur d'un langage, ce n'est même pas possible officiellement dans le cas de l'API Win32.

Citation Envoyé par OuftiBoy Voir le message
Mais comme ça a été découvert sur Rust, qui a comme argument une meilleur sécurité, ça me fais un peur rire :-)
Justement, alors que le problème existe depuis possiblement 30 ans, il a été découvert en premier sur du Rust, où il a rapidement été rendu inexploitable depuis sa bibliothèque standard. D'un autre coté, Java a décidé de ne rien faire et Microsoft n'a, semble-il à l'heure actuelle, même pas mis à jour sa documentation officielle.
On voit quand même une sacré différence dans la gestion des risques. Pour rappel, Rust n'a jamais prétendu empêcher 100% des failles de sécurité, mais clairement, il prend le problème au sérieux.

Citation Envoyé par OuftiBoy Voir le message
Tu sais depuis quand elle existe cette faille ? A mon avis, depuis un certains temps je pense, et peut-être moins sur des langages plus anciens dont les équipes connaissaient le comportement de cmd.exe ? Je n'affirme rien, je demande ton avis et/ou si tu as des infos à ce sujet ?
CreateProcess est il me semble une fonction historique de l'API Win32, je ne sais pas exactement si elle est présente depuis le tout début de l'API et si elle a toujours permis d’exécuter les fichiers de commande, mais si c'est le cas, ce qui ne me parais pas impossible, ça remonterait au milieu des années 90.
2  0 
Avatar de chrtophe
Responsable Systèmes https://www.developpez.com
Le 15/04/2024 à 6:45
Appeler un fichier externe avec cmd est une mauvaise idée.
1  0 
Avatar de chrtophe
Responsable Systèmes https://www.developpez.com
Le 15/04/2024 à 21:15
J’avais compris que c'était lié à cmd.exe, Donc utilisé pour appeler une commande externe au logiciel.

Pas clair pour moi.
1  0 
Avatar de Uther
Expert éminent sénior https://www.developpez.com
Le 19/04/2024 à 8:55
Citation Envoyé par OuftiBoy
Je préfère en effet qu'un garagiste n'ayant pas toutes les informations nécessaire ne touche pas à ma voiture, tout comme un dev qui n'a pas toutes les informations nécessaire n'utilise pas qlq chose de non documenté ou mal documenté. C'est exactement ce que je dis, rien de plus. On parle ici de gens (d'une équipe) qui devraient être à la pointe. Pas d'un dev qui fait un petit projet dans son garage...
La problème c'est qu'il n'est pas évident de savoir qu'il nous manque une information. Rétrospectivement, et sur un cas connu, c'est toujours facile d'imaginer pourquoi l'API peut réagir particulièrement. Mais un développeur ne peut pas systématiquement anticiper tous les comportements internes potentiellement tordus d'une API : on peut toujours en imaginer plus. Si on ne fait rien sans être sur, on ne fait rien du tout, jamais. A un moment, il faut accorder un minimum de confiance au service fourni et on le fait sur la base d'une spécification ou à défaut d'une doc de référence.

Supposons qu'un développeur utilise la fonction système de copie de fichiers dans son application et que l'on découvre plus tard que cette fonction modifie certains types de fichiers images à la volée pour ajouter un watermark invisible sans le préciser. Est-ce qu'on devrait rendre le développeur responsable du fait que son application leake des informations, parce qu'il aurait du l'anticiper en vérifiant le comportement de la fonction pour tous les types de fichiers possibles ?
Et des exemple du genre, on peut en imaginer des dizaines sur quasiment toutes les fonctions possibles d'une API. Si on doit anticiper tous les cas imaginables de mauvais fonctionnement, on ne peut plus rien utiliser.
1  0