Directrices

Inyección de comandos

Veamos la Inyección de Comandos por sí misma por ahora. Vamos a centrarnos principalmente en algunos ejemplos diferentes para que sea más fácil ver cómo se ve en acción. Así que, como repaso rápido, las vulnerabilidades de inyección de comandos se producen cuando la entrada del usuario utiliza parte de un comando del sistema operativo, como la siguiente función:

let ip = request.params.ipAddress;

system("ping " + ip);

Si un usuario proporciona la dirección IP, usaremos `8.8.8.8` como ejemplo, el comando que se ejecutará será `ping 8.8.8.8`, que hace exactamente lo que uno esperaría. Sin embargo, si el usuario proporciona `8.8.8.8 && ls /etc/` este comando no sólo hará ping a la IP 8.8.8.8, sino que también ejecutará `ls` en la carpeta `/etc/. 

Mitigación

Dada la gravedad de un ataque de inyección de comandos, hay algunas preguntas importantes que debe plantearse en primer lugar cuando trabaje con comandos del sistema:

  • ¿Es realmente necesario invocar ese comando? La mejor defensa es no invocar nunca comandos del sistema
  • ¿Existen bibliotecas/vinculaciones que permitan conseguir el mismo efecto sin utilizar un comando del sistema?
  • ¿Puede pasar datos al proceso a través de Standard In, en lugar del propio comando? 

Si estas cosas no son posibles, la parametrización es importante.

Ejemplos

He aquí algunos ejemplos en varios idiomas para mostrar cómo se ve esto en la práctica. 

Sin el uso de la parametrización, esto es vulnerable a la inyección de comandos.

string folder = "/tmp/ && ifconfig";
string cmd = "\"ls " + folder +"\"";

// INSECURE: Ejecuta tanto el comando `ls` como `ifconfig`
System.Diagnostics.Process.Start("bash", "-c " + cmd);

C# - seguro

Al proporcionar el comando como una lista de parámetros, el comando está parametrizado y protegido contra la inyección de comandos.

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 - Inseguro

Sin el uso de la parametrización, esto es vulnerable a la inyección de comandos.

String folder = "/tmp/ && ifconfig";

// INSECURE: Ejecuta tanto el comando `ls` como `ifconfig`
ProcessBuilder b = new ProcessBuilder("bash -c ls " + carpeta);

Process p = pb.start();

Java - Seguro

Al proporcionar el comando como una lista de parámetros, el comando está parametrizado y protegido contra la inyección de comandos.

String folder = "/tmp/ && ifconfig";

// SEGURO: No ejecuta el comando ifconfig
ProcessBuilder b = new ProcessBuilder("bash", "-c", "ls", folder);

Process p = pb.start();

Javascript - Inseguro

Sin el uso de la parametrización, esto es vulnerable a la inyección de comandos.

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 - Seguro

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 - Inseguro

Sin el uso de la parametrización, esto es vulnerable a la inyección de comandos.‍

import subprocess

folder = "/tmp/ && ifconfig"

# INSECURE: Ejecuta tanto el comando `ls` como `ifconfig`
subprocess.run("bash -c ls " + folder, shell=True)

Python - Seguro

Al proporcionar el comando como una lista de parámetros, el comando está parametrizado y protegido contra la inyección de comandos.

import subprocess

folder = "/tmp/ && ifconfig"

# SEGURO: No ejecuta el comando ifconfig
subprocess.run(["bash", "-c", "ls", folder])