# attaque par injection de commandes
## Description
Le but de l'attaque par **injection de commandes** est d'injecter et exécuter des commandes spécifiées par l'attaquant dans l'application vulnérable. Dans ce genre de situation, l'application, qui exécute des commandes de système non désirées, est comme un ** 'pseudo-Shell Système' **, et l'attaquant peut l'utiliser comme n'importe quel utilisateur autorisé du système. Toutefois, les commandes sont exécutées avec les mêmes privilèges dont dispose l'environnement de l'application. Les attaques par injection de commandes sont possibles dans la plupart des cas en raison du manque de validation des données d'entrée, qui peut être manipulé par l'attaquant (formulaires, cookies, HTTP headers, etc.)
C'est une variante à l'attaque ** ' injection de code ' **. La différence avec l'injection de code est que l'attaquant ajoute son propre code au code existant. De cette manière, l'attaquant étend la fonctionnalité par défaut de l'application sans la nécessité d'exécuter des commandes système. Code injecté est exécuté avec les mêmes privilèges ont dispose l'environnement de l'application.
Une attaque par **injection de commandes OS** se produit quand un attaquant essaie d'exécuter des commandes au niveau du système par le biais d'une application vulnérable. Les demandes sont considérées comme vulnérables à l'attaque par injection de commandes OS s'ils utilisent l'entrée de l'utilisateur dans une commande au niveau du système.
## Exemples
### Exemple 1
Le code suivant est un enrobage de la commande UNIX //cat// qui imprime le contenu d'un fichier sur la sortie standard. Il est également injectable:
#include
#include
int main(int argc, char **argv) {
char cat[] = "cat ";
char *command;
size_t commandLength;
commandLength = strlen(cat) + strlen(argv[1]) + 1;
command = (char *) malloc(commandLength);
strncpy(command, cat, commandLength);
strncat(command, argv[1], (commandLength - strlen(cat)) );
system(command);
return (0);
}
Utilisé normalement, la sortie est tout simplement le contenu du fichier demandé:
$. /CatWrapper Story.txt
La dernière fois que nous avons laissé nos héros ...
Cependant, si l'on ajoute un point-virgule et une autre commande à la fin de cette ligne, la commande est exécutée par 'catWrapper' sans contrainte:
$. /CatWrapper "Story.txt; ls"
La dernière fois que nous avons laissé nos héros ...
Story.txt doubFree.c nullpointer.c
unstosig.c www * a.out *
format.c strlen.c useFree *
catWrapper * misnull.c strlength.c useFree.c
commandinjection.c nodefault.c trunc.c writeWhatWhere.c
Si //catWrapper// avait été fixé à un niveau de privilège plus élevé que l'utilisateur standard, des commandes arbitraires pourraient être exécutés avec ce privilège plus élevé.
### Exemple 2
Le simple programme suivant accepte un nom de fichier comme argument de ligne de commande et affiche le contenu du fichier de l'arrière à l'utilisateur. Le programme est installé 'setuid root', car il est destiné à être utilisé comme outil d'apprentissage pour permettre aux administrateurs système en cours de formation pour inspecter les fichiers système privilégiés sans leur donner la possibilité de les modifier ou d'endommager le système.
int main(char * argc, char ** argv) {
char cmd[CMD_MAX] = "/usr/bin/cat";
strcat(cmd, argv [1]);
système(cmd);
}
Parce que le programme s'exécute avec les privilèges //root//, l'appel à //system ()// exécute également avec les privilèges //root//. Si un utilisateur spécifie un nom de fichier standard, l'appel fonctionne comme prévu. Toutefois, si un attaquant transmet une chaîne de la forme ";rm-rf /", alors l'appel à //system ()// ne parvient pas à exécuter //cat// à cause d'un manque d'arguments et efface récursivement le contenu de la partition racine.
### Exemple 3
Le code suivant à partir d'un programme privilégié utilise la variable d'environnement //$ APPHOME// pour déterminer le répertoire d'installation de l'application, puis exécute un script d'initialisation dans ce répertoire.
...
char* home=getenv("APPHOME");
char* cmd=(char*)malloc(strlen(home)+strlen(INITCMD));
if (cmd) {
strcpy(cmd, home);
strcat(cmd, INITCMD);
execl(cmd, NULL);
}
...
Comme dans l'exemple 2, le code de cet exemple permet à un attaquant d'exécuter des commandes arbitraires avec les privilèges élevés de l'application. Dans cet exemple, l'attaquant peut modifier la variable d'environnement //$APPHOME// ,de spécifier un chemin différent contenant une version malicieuse de //INITCMD//. Parce que le programme ne valide pas la valeur lue sur l'environnement, en contrôlant la variable d'environnement, l'attaquant peut tromper l'application en cours d'exécution du code malveillant.
L'attaquant utilise la variable d'environnement pour contrôler la commande que le programme invoque, donc l'effet de l'environnement est explicite dans cet exemple. Nous allons maintenant tourner notre attention vers ce qui peut arriver lorsque l'attaquant modifie la façon dont la commande est interprétée.
### Exemple 4
Le code ci-dessous provient d'un utilitaire //Web CGI// qui permet aux utilisateurs de changer leurs mots de passe. Le processus de mise à jour passe sous NIS inclut l'exécution 'make' dans le répertoire '/var/yp'. A noter que depuis les dossiers du programme des mises à jour de mot de passe, il a été installé //setuid root//.
Le programme invoque faire comme suit:
system("cd /var/yp && make &> /dev/null");
Contrairement aux exemples précédents, la commande de cet exemple est codée en dur, de sorte qu'un attaquant ne peut pas contrôler l'argument passé à //system ()//. Cependant, puisque le programme ne spécifie pas un chemin absolu pour //make//, et ne nettoie pas les variables d'environnement avant d'appeler la commande, l'attaquant peut modifier leur variable $PATH pour pointer vers un binaire malveillant nommé //make// et d'exécuter le script à partir d'un l'invite du shell. Et comme le programme a été installé setuid root, la version de l'attaquant de //make// fonctionne désormais avec les privilèges root.
L'environnement joue un rôle important dans l'exécution de commandes système au sein des programmes. Des fonctions comme //system()// et //exec()// utilisent l'environnement du programme qui les appelle, et donc les attaquants ont une opportunité potentielle pour influencer le comportement de ces appels.
Il existe de nombreux sites qui vous diront que //Runtime.exec// de Java est exactement la même que la fonction système du C. Ce n'est pas vrai. Les deux vous permettent d'invoquer un nouveau programme / processus. Cependant, la fonction du système C de passe ses arguments au //shell (/bin/sh)// pour être analysée, alors //Runtime.exec de Java// tente de diviser la chaîne en un tableau de mots, puis exécute le premier mot dans la matrice avec le reste des mots en tant que paramètres. //Runtime.exec// n'essaye pas d'invoquer le shell à tout moment. La principale différence est que la plupart des fonctionnalités fournies par le shell qui pourrait être utilisé pour méfait (chaîner les commandes en utilisant "&", "&&", "|", "| |", etc, redirigeant les entrées et sorties) serait tout simplement utiliser en tant que paramètre qui est passé à la première commande, et qui probablement causerait une erreur de syntaxe, ou serait rejeté comme paramètre invalide.
### Exemple 5
Les extraits de codes triviaux suivants sont vulnérable à l'injection de commande OS sur la plate-forme Unix / Linux:
* C:
##include
#include
#include
int main(int argc, char **argv)
{
char command[256];
if(argc != 2) {
printf("Error: Please enter a program to time!\n");
return -1;
}
memset(&command, 0, sizeof(command));
strcat(command, "time ./");
strcat(command, argv[1]);
system(command);
return 0;
}
* S'il s'agissait d'un //binaire suid//, considérons le cas quand un attaquant entre le texte suivant: //«ls; cat /etc/shadow //'. Dans un environnement Unix, les commandes shell sont séparés par un point-virgule. Nous pouvons maintenant exécuter des commandes système à volonté!
* Java:
Il existe de nombreux sites qui vous diront que **//Runtime.exec//** de Java est exactement la même que la fonction **//système du C//**. Ce n'est pas vrai. Les deux vous permettent d'invoquer un nouveau programme / processus. Cependant, la fonction du système C passe ses arguments au* **//shell (/bin/sh)//** pour être analysée, alors **//Runtime.exec//** tente de diviser la chaîne en un tableau de mots, puis exécute le premier mot dans la matrice avec le reste des mots en tant que paramètres. **//Runtime.exec//** n'essaye pas d'invoquer le shell à tout moment. La principale différence est que la plupart des fonctionnalités fournies par le shell qui pourrait être utilisé pour méfait (chaîner les commandes en utilisant "&", "&&", "|", "| |", etc, redirigeant les entrées et sorties) serait tout simplement utiliser en tant que paramètre qui est passé à la première commande, et qui a probablement causerait une erreur de syntaxe, ou serait rejetés comme un paramètre invalide.
## Références
CWE-77: Injection de Commande
CWE-78: Injection de commandes OS
http://blog.php-security.org/archives/76-Holes-in-most-preg_match-filters.html