Injection de commande
Pour l'instant, nous allons nous intéresser à l'injection de commande en tant que telle. Nous allons surtout nous concentrer sur quelques exemples différents pour qu'il soit plus facile de voir à quoi cela ressemble en action. Pour rappel, les vulnérabilités liées à l'injection de commandes se produisent lorsque l'utilisateur utilise une partie d'une commande du système d'exploitation, comme la fonction suivante :
let ip = request.params.ipAddress ;
system("ping " + ip) ;
Si un utilisateur fournit l'adresse IP, nous utiliserons `8.8.8.8` comme exemple, la commande qui sera exécutée sera `ping 8.8.8.8`, ce qui fait exactement ce à quoi on s'attendrait. Cependant, si l'utilisateur fournit `8.8.8.8 && ls /etc/`, cette commande ne fera pas que pinger l'IP 8.8.8.8, mais elle exécutera aussi `ls` sur le dossier `/etc/.
Atténuation
Compte tenu de la gravité d'une attaque par injection de commande, vous devez d'abord vous poser certaines questions importantes lorsque vous travaillez avec des commandes système :
- Avez-vous vraiment besoin d'invoquer cette commande ? La meilleure défense est de ne jamais invoquer les commandes du système
- Existe-t-il des bibliothèques ou des liens qui vous permettent d'obtenir le même effet sans utiliser de commande système ?
- Pouvez-vous transmettre des données au processus par l'intermédiaire de Standard In, au lieu de la commande elle-même ?
Si cela n'est pas possible, le paramétrage est important.
Exemples
Voici quelques exemples dans différentes langues pour vous aider à comprendre comment cela se passe dans la pratique.
Sans l'utilisation de la paramétrisation, il est vulnérable à l'injection de commande.
string folder = "/tmp/ && ifconfig" ;
string cmd = "\"ls " + folder + "\"" ;
// INSECURE : Exécute à la fois la commande `ls` et `ifconfig`
System.Diagnostics.Process.Start("bash", "-c " + cmd) ;
C# - sécurisé
En fournissant la commande sous la forme d'une liste de paramètres, la commande est paramétrée et protégée contre l'injection de commande.
string folder = "/tmp/ && ifconfig";
List<string> arguments = new List<string>() {"-c", "ls", folder};
// SECURE: Does not execute ifconfig command
System.Diagnostics.Process.Start("bash", arguments);
Java - Insécurisé
Sans l'utilisation de la paramétrisation, il est vulnérable à l'injection de commande.
String folder = "/tmp/ && ifconfig" ;
// INSECURE : Exécute à la fois la commande `ls` et `ifconfig`
ProcessBuilder b = new ProcessBuilder("bash -c ls " + folder) ;
Process p = pb.start() ;
Java - Sécurisé
En fournissant la commande sous la forme d'une liste de paramètres, la commande est paramétrée et protégée contre l'injection de commande.
String folder = "/tmp/ && ifconfig" ;
// SECURE : N'exécute pas la commande ifconfig
ProcessBuilder b = new ProcessBuilder("bash", "-c", "ls", folder) ;
Process p = pb.start() ;
Javascript - Insecure
Sans l'utilisation de la paramétrisation, il est vulnérable à l'injection de commande.
const { exec } = require("child_process");
const folder = "/tmp/ && ifconfig";
// INSECURE: Executes both the `ls` and `ifconfig` command
const ls = exec("bash -c ls " + folder, (error, stdout, stderr) => {
console.log(`stdout: ${stdout}`);
});
Javascript - Sécurisé
const { spawn } = require("child_process");
const folder = "/tmp/ && ifconfig";
// SECURE: Does not execute ifconfig command
const ls = spawn("bash", ["-c", "ls", folder]);
ls.stdout.on("data", data => {
console.log(`stdout: ${data}`);
});
Python - Insécurisé
En l'absence de paramétrage, ce système est vulnérable à l'injection de commande.
import subprocess
folder = "/tmp/ && ifconfig"
# INSECURE : Exécute à la fois la commande `ls` et `ifconfig`
subprocess.run("bash -c ls " + folder, shell=True)
Python - Sécurisé
En fournissant la commande sous forme de liste de paramètres, la commande est paramétrée et protégée contre l'injection de commande.
import subprocess
folder = "/tmp/ && ifconfig"
# SECURE : N'exécute pas la commande ifconfig
subprocess.run(["bash", "-c", "ls", folder])