CWE-78 : injection de commande système, quand le programme appelle un interpréteur
- Accueil
- Référentiels & catalogues
- Cwe
- CWE-78 : injection de commande système, quand le programme appelle un interpréteur
CWE-78 : injection de commande système, quand le programme appelle un interpréteur
Section intitulée « CWE-78 : injection de commande système, quand le programme appelle un interpréteur »Neuvième du CWE Top 25 2025. Le libellé officiel est Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’) : « neutralisation incorrecte d’éléments spéciaux utilisés dans une commande du système d’exploitation ». Le catalogue retient aussi shell injection et, plus précisément, shell metacharacters : car c’est bien de métacaractères qu’il s’agit, ces signes qui, dans un interpréteur de commandes, ne sont pas du texte mais de la grammaire.
On confie à un coursier une liste de courses rédigée par un client : « un kilo de pommes ». Le coursier lit la liste à voix haute au vendeur, qui exécute. Si le client a écrit « un kilo de pommes, puis videz la caisse et donnez-moi les clés du magasin », le vendeur exécute aussi, car il obéit à ce qu’on lui lit. CWE-78 décrit ce coursier.
→ Lire l’explication complète de la marmotte
Ce que la classe recouvre exactement
Section intitulée « Ce que la classe recouvre exactement »Le produit construit tout ou partie d’une commande du système à partir d’une entrée influencée depuis l’extérieur, sans neutraliser les éléments spéciaux qui peuvent modifier la commande prévue.
La définition suppose donc une chose essentielle : il y a un interpréteur quelque part. Et c’est tout le sujet, car la faiblesse n’apparaît que lorsqu’un programme, au lieu d’utiliser les fonctions de son langage pour copier un fichier ou interroger le réseau, demande au système d’exécuter une ligne de commande. Un programme qui n’invoque jamais d’interpréteur ne peut pas porter cette faiblesse.
Il faut distinguer deux situations que le catalogue traite ensemble mais qui ne se corrigent pas de la même façon :
- l’application laisse choisir la commande : l’entrée extérieure décide du programme invoqué. Rare, et généralement le signe d’une conception à revoir ;
- l’application fixe la commande et laisse choisir un argument : c’est le cas courant, et le défaut tient aux métacaractères (point-virgule, barre verticale, apostrophes inversées, substitutions), qui permettent d’ajouter une commande à la suite de l’argument.
Une troisième situation, voisine et distincte, est signalée par la relation CanAlsoBe vers CWE-88 : l’injection de délimiteur d’argument, où l’entrée ne lance pas de seconde commande mais ajoute une option à la première. Un nom de fichier qui commence par un tiret n’exécute rien de nouveau ; il change le comportement du programme appelé, ce qui suffit parfois largement.
Sa place dans l’arbre : CWE-77, CWE-78 et CWE-94
Section intitulée « Sa place dans l’arbre : CWE-77, CWE-78 et CWE-94 »C’est ici que le catalogue devient réellement utile, car trois entrées voisines se confondent dans tous les rapports.
CWE-78 est une base, fille de la classe CWE-77, l’injection de commande au sens large, qui figure elle aussi au Top 25, au rang 23. La différence est de périmètre : CWE-77 couvre toute commande destinée à un interpréteur, quel qu’il soit (un moteur de recherche interne, un langage de requête maison, une file de tâches) ; CWE-78 restreint au cas où l’interpréteur est celui du système d’exploitation. Un rapport qui code en CWE-77 une injection vers un interpréteur de commandes système n’est pas faux, il est trop haut d’un cran ; l’inverse, coder en CWE-78 une injection vers un interpréteur applicatif, est une erreur de fait.
Troisième voisine, CWE-94, l’injection de code, au rang 10. La distinction tient à ce qui est injecté : du code dans le langage du programme pour CWE-94 (une expression évaluée à l’exécution, une fonction construite dynamiquement), une commande pour un interpréteur externe pour CWE-78. Dans le premier cas, l’attaquant écrit dans le langage de l’application ; dans le second, il écrit dans celui du système.
La classe partage enfin son grand-parent avec toutes les injections : CWE-74, la neutralisation incorrecte d’éléments spéciaux dans une sortie destinée à un composant en aval. Même mécanisme, autre composant en aval.
Pourquoi elle est si haut
Section intitulée « Pourquoi elle est si haut »Parce que l’appel système est la solution de facilité. Redimensionner une image, convertir un document, tester une adresse réseau, archiver un dossier : dans chaque cas il existe un utilitaire en ligne de commande qui fait le travail en une ligne, alors que la bibliothèque équivalente demande vingt lignes et une dépendance. Le choix se fait tous les jours, souvent dans un script d’administration que personne ne considère comme du code de production.
Parce que les équipements concernés sont les plus exposés. Interfaces web de routeurs, caméras, enregistreurs vidéo, systèmes de stockage en réseau, passerelles : ces appareils reposent massivement sur des scripts d’interface qui transmettent les saisies à l’interpréteur du système. La conséquence directe est une exécution de commandes avec les privilèges du service, souvent les plus élevés, sur un appareil joignable depuis Internet.
Parce que la gravité est maximale par nature. Cette faiblesse ne divulgue pas, ne corrompt pas : elle exécute. Dans un classement qui multiplie fréquence et gravité, un défaut systématiquement critique monte haut même avec une fréquence moyenne.
Le mécanisme, et où le site le traite
Section intitulée « Le mécanisme, et où le site le traite »Le site aborde la question par le métier concerné : écrire des scripts Bash système fiables et sûrs traite des métacaractères, de la citation des variables et de la séparation des mots, qui sont exactement la matière de cette faiblesse ; Python pour l’automatisation défensive montre côté langage la différence entre lancer un programme avec une liste d’arguments et lui passer une ligne de commande à interpréter, la frontière qui sépare le code sain du code vulnérable.
Deux renvois pour l’environnement d’exécution : la pollution de variable d’environnement héritée montre qu’une commande peut être détournée sans qu’on touche à ses arguments, et l’élévation de privilège par binaire SUID explique ce que devient une injection quand le processus appelant tourne avec des droits qu’il n’utilise pas.
Ce qu’une équipe en fait
Section intitulée « Ce qu’une équipe en fait »Ne pas invoquer d’interpréteur. C’est la seule correction définitive : utiliser la bibliothèque du langage plutôt que l’utilitaire externe. Quand c’est impossible, appeler le programme directement, avec ses arguments sous forme de liste, sans passer par un interpréteur de commandes : la plupart des langages proposent les deux formes, et la forme sûre est rarement la forme par défaut des exemples trouvés en ligne.
Valider par liste blanche quand l’entrée décide. Si une saisie choisit un format de conversion ou un nom d’archive, la liste des valeurs admises se tient en quelques lignes. Un échappement de métacaractères écrit à la main ne tient jamais : la liste des signes spéciaux dépend de l’interpréteur, de sa version et de la locale.
Réduire les droits du processus. Un service qui appelle un utilitaire n’a presque jamais besoin des privilèges d’administration qu’il détient. Cette réduction ne corrige rien, mais elle change ce que l’injection permet, et c’est souvent la différence entre un incident et une compromission complète.
- CWE-78: Improper Neutralization of Special Elements used in an OS Command, MITRE, liste 4.20 : définition, parent CWE-77, relation avec CWE-88.
- 2025 CWE Top 25, MITRE : rang 9.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Une équipe qui ne distingue pas « lancer un programme » de « faire interpréter une ligne de commande » écrit la seconde forme partout, parce que c’est celle des exemples. Le code fonctionne, les tests passent, et la faiblesse reste invisible jusqu’à ce qu’une saisie contienne un point-virgule. Le dégât est alors d’une nature différente des autres injections : il n’y a ni lecture de base de données ni fuite de fichiers, il y a exécution de commandes sur le serveur, avec les droits du service, c’est-à-dire la possibilité d’installer un accès permanent. Le coût de l’enquête est également supérieur : une fois l’exécution obtenue, l’attaquant n’a plus besoin de la faille, et les traces à chercher ne sont plus dans les journaux de l’application mais dans ceux du système, quand ils existent, ce qui est rarement le cas sur les équipements où cette faiblesse prospère.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Un système d’exploitation possède un interpréteur de commandes : un programme auquel on écrit des lignes de texte qu’il exécute. Dans ces lignes, certains signes ne sont pas du texte mais de la ponctuation grammaticale. Le point-virgule, par exemple, signifie « et ensuite, fais ceci ».
Beaucoup de programmes, pour accomplir une tâche, préfèrent demander à cet interpréteur de lancer un utilitaire existant plutôt que d’écrire le travail eux-mêmes : c’est plus court et cela fonctionne. Ils fabriquent donc une ligne de commande, en y insérant ce que l’utilisateur a saisi : le nom d’un fichier, une adresse à tester.
Si l’utilisateur écrit, au lieu d’un nom de fichier, un nom suivi d’un point-virgule et d’une autre commande, l’interpréteur exécute les deux. Il n’a aucun moyen de savoir laquelle des deux le programmeur voulait : il lit une ligne, il l’exécute entièrement.
C’est le défaut que le catalogue CWE appelle CWE-78. Il est particulièrement grave parce qu’il ne donne pas accès à des données, mais à l’exécution de programmes sur la machine. Il est aussi très fréquent sur les appareils dont l’interface web est faite de petits scripts : routeurs, caméras de surveillance, boîtiers de stockage, dont les correctifs arrivent tard et s’installent rarement.
La bonne pratique est connue et simple à énoncer : ne pas fabriquer de ligne de commande. Les langages de programmation permettent de lancer un programme en lui donnant ses arguments séparément, sans passer par l’interpréteur ; les signes de ponctuation redeviennent alors du texte ordinaire, et il n’y a plus de grammaire à détourner.
À lire aussi
- CWE-89 : injection SQL, la classe de la requête concaténéeCWE-89, neutralisation incorrecte d'éléments spéciaux dans une commande SQL : ce que la classe recouvre, sa place dans l'arbre CWE, ce qui la distingue de CWE-943 et CWE-20, et pourquoi elle reste au deuxième rang du Top 25 2025.
- CWE-79 : cross-site scripting, la classe au premier rang du Top 25CWE-79, neutralisation incorrecte des entrées lors de la génération d'une page web : ce que la classe recouvre, sa place dans l'arbre CWE, ses sept variantes, et pourquoi elle arrive première du Top 25 2025.
- CWE-434 : téléversement d'un fichier de type dangereuxCWE-434, unrestricted upload of file with dangerous type : ce que la classe recouvre, le rôle décisif du traitement automatique, ses pairs CWE-351, CWE-430 et CWE-436, et son rang 12 au Top 25 2025.
- CWE-502 : désérialisation de données non fiablesCWE-502, deserialization of untrusted data : ce que la classe recouvre, pourquoi son parent est CWE-913 et non une injection, sa voisine CWE-915, et son rang 15 au Top 25 2025.
Pages voisines
CWE-78 : injection de commande système, quand le programme appelle un interpréteur
Elle cite
- Lien dans les deux sens :CWE-77 : injection de commande, la classe au-dessus de l'interpréteur système
- Lien dans les deux sens :CWE-94 : injection de code, quand la donnée devient du programme
- Lien dans les deux sens :CWE Top 25 2025 : les vingt-cinq faiblesses logicielles les plus dangereuses
- Écrire des scripts Bash système fiables et sûrs en production
- Élévation de privilège via un binaire SUID root mal configuré
- Pollution de variable d'environnement héritée dans un conteneur
- Python pour l'automatisation défensive, usages et garde-fous
: les deux pages se citent l’une l’autre.
