Admirer Write-Up

Fecha de lanzamiento02 May 2020
EstadoRetirada
DificultadEasy
PlataformaLinux
IP10.10.10.187

Información de la máquina



RECONOCIMIENTO

Durante la fase de reconocimiento de nmap, se han identificado 3 puertos abierto por el protocolo TCP: FTP(21), SSH(22) y HTTP(80).

nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn -oN nmap_scan 10.10.10.187
nmap -sCV -p21,22,80 -oN nmap_services 10.10.10.187

Si filtramos en LaunchPad por la version de OpenSSH y de Apache, a priori parece que nos estamos enfrentando a un Debian 9 Stretch, pero lo tendremos que confirmar más adelante una vez que tengamos acceso a la máquina víctima.

Viendo que no tenemos credenciales para SSH y/o FTP, y además no tenemos acceso como usuario anónimo al servidor FTP, vamos a centrar la intrusión por el puerto 80, teniendo en cuenta que uno de los scripts de enumeración de nmap ha reportado la existencia de 1 disallowed entry en robots.txt: admin-dir.

HTTP 80 – Servidor Web

Si revisamos la página web, vemos que se trata de una web artística con poca funcionalidad, donde únicamente podemos observar diferentes imágenes almacenadas en el servidor y tenemos en el footer un formulario de contacto.

Hemos tratado de probar posibles inyecciones XSS y SQL en los campos del formulario pero no hemos obtenido nada interesante.

Chequeando la ruta almacenada en el archivo robots.txt, vemos que la respuesta es un 403 Forbidden.

Vamos a realizar fuzzing de posibles directorios mediante la herramienta GoBuster, y además agregaremos la extensión php sabiendo que está corriendo en el servidor web.

gobuster dir -u http://10.10.10.187 -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -x php -t 20

Como podemos ver en la siguiente imagen, no obtenemos ningún resultado destacable:

De forma paralela, haremos fuzzing también en la ruta http://10.10.10.187/admin-dir/ añadiendo posibles extensiones:

gobuster dir -u http://10.10.10.187/admin-dir/ -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -x php,html,txt -t 20

Identificamos dos archivos con extensión txt que tienen información acerca de usuarios y además contraseñas para diferentes servicios:

Teniendo ya credenciales FTP, vamos a conectarnos y a descargarnos todo para examinarlo de forma local. Tenemos dos archivos, uno con extensión .sql y el otro es un comprimido que contiene diferentes directorios y archivos.

El archivo dump.sql contiene información acerca de las imágenes e información que se muestran en la web, y no existen datos relevantes a priori en él.

Sin embargo, si descomprimimos el otro archivo mediante el comando tar -xf html.tar.gz, vemos que tenemos varios archivos y directorios de lo que parece ser un servidor web con bastantes similitudes a la estructura web que hemos observado anteriormente. Vamos a ver paso por paso que contiene cada archivo y que información relevante podemos sacar de ellos:

  • El archivo index.php nos ofrece información de una conexión SQL, mostrándonos un usuario, contraseña y BBDD que nos vamos a guardar por si nos es útil más tarde:
  • El directorio w4ld0s_s3cr3t_d1r parece una versión anterior al directorio /admin-dir/ que actualmente está en producción y contiene dos archivos idénticos (credentials.txt y contacts.txt) al entorno de producción, pero la data en ellos es ligeramente diferente por lo que también guardaremos estas nuevas credenciales:
  • El directorio utility-scripts no nos lo había reportado la herramienta GoBuster y si comprobamos la web en producción vemos que esta nos devuelve un código 403 Forbidden. Si comprobamos los archivos alcanzables en producción, comparando con aquellos archivos que nos hemos descargado del servidor FTP, vemos que el archivo admin_tasks.php existe, el archivo info.php también y el archivo phptest.php de nuevo también. Sin embargo si buscamos el recurso db_admin.php parece no existir en el entorno de producción.

Teniendo en cuenta que info.php y phptest.php no nos aportan mucha información y que el archivo admin_tasks.php es un script que corre comandos y que hemos tratado de explotar de diversas maneras sin éxito, vamos a observar el contenido del archivo db_admin.php.

Observamos credenciales e información de una conexión que guardaremos, pero lo más remarcable aquí sería el comentario del final. Si seguimos suponiendo que estos archivos son de un entorno anterior y que el entorno en producción es una ligera modificación de los archivos que nos hemos descargado del servidor FTP, podemos intuir que actualmente como este archivo no existe, se ha implementado una alternativa.

Por probar, vamos a correr de nuevo GoBuster para ver si hay alguna ruta nueva en producción bajo el directorio utility_scripts donde pueda estar alojada una posible nueva implementación de db_admin.php:

gobuster dir -u http://10.10.10.187/utility-scripts/ -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt -x php,html,txt -t 20

En la ruta http://10.10.10.187/utility-scripts/adminer.php tenemos el panel login de Adminer, una herramienta para la gestión de contenidos de BBDD.

Una vez en el panel login, hemos probado con todas las credenciales encontradas anteriormente pero no hemos tenido éxito en la conexión. Buscando exploits para la versión en producción hemos encontrado el siguiente post donde se explica una explotación de Adminer para obtener información local de la máquina víctima. El post es el siguiente -> LINK

Básicamente a modo resumen, existe una vulnerabilidad en la versión en uso que proporciona a un atacante permisos arbitrarios de lectura en el servidor conectando una base de datos MySQL externa a Adminer. Para ello es necesario la creación en local de una base de datos en nuestro host, que explicaremos a continuación.

Vamos a correr el servicio mysql y a abrirnos la interfaz de MariaDB. A continuación crearemos una nueva base de datos que será la que conectemos a Adminer y crearemos una tabla dentro de ella que será donde se deposite la información que vamos a leer de la máquina víctima:

sudo service mysql start #Iniciar Servicio
mysql -uroot #Abrir interfaz
create database Pwned; #Crear base de datos
use Pwned; #Seleccionarla
create table output (output VARCHAR(256)); #Crear tabla llamada output con una columna llamada output

Para poder identificarnos en Adminer vamos a crear un usuario con una contraseña que definiremos y vamos a asignar a ese usuario permisos ALL para todas las tablas y columnas de la base de datos Pwned que recientemente hemos creado:

create user 'srmeirins'@'10.10.10.187' identified by 'srmeirins123';
GRANT ALL on Pwned.* to 'srmeirins'@'10.10.10.187';

Debo decir que aquí me encontré dos tipos de errores a la hora de autenticarse. El primero fue el mencionado anteriormente que era cuestión de permisos asignados para el usuario dentro de la base de datos. El segundo fue algo mas quebradero de cabeza, ya que daba un error de Connection Refused. En este caso tuve que modificar el archivo /etc/mysql/mariadb.conf.d/50-server.cnf y cambiar Bind-Address por nuestra IP asignada en la interfaz de la VPN.

Una vez dentro, si tratamos de ejecutar la consulta SQL para leer el archivo /etc/passwd local de la máquina víctima vemos que no tenemos acceso, y lo mismo para el archivo .ssh del usuario local Waldo.

Sin embargo si que somos capaces de obtener los datos del archivo index.php y guardarlo en nuestra base de datos.

Observando vemos unas credenciales en el código del archivo. Estas credenciales son diferentes al archivo index.php que hemos descargado del servidor FTP y son las que actualmente se están usando en producción. Además estas credenciales nos permiten también autenticarnos como el usuario Waldo via SSH.

Privilege Escalation to Root

Haciendo un sudo -l , observamos que el usuario Waldo puede correr como cualquier usuario un script en bash situado en el directorio /opt/scripts. Es decir vamos a poder correr como el usuario ROOT este script.

Pero lo interesante aquí también es que tenemos la etiqueta SETENV:definida. Esto significa que tenemos la capacidad de definir variables de entorno para el usuario ROOT, de lo cual nos vamos a aprovechar para escalar privilegios.

Si observamos el script, vemos que está bastante bien sanitizado y por lo menos para mi no ha sido posible inyectar nada. Además todas las llamadas a comandos se realizan mediante su ruta absoluta.

Sin embargo si vemos una de las funciones, backup_web(), se está llamando a un custom script en Python3:

Se está importando make_archive de la librería shutil. Aquí es donde vemos una vía potencial de escalada de privilegios. Vamos a aprovecharnos de la capacidad que tenemos de definir variables de entorno como el usuario ROOT para secuestrar la librería Shutil.py y ejecutar código como el usuario ROOT.

Lo primero, vamos a crear un archivo malicioso que simule ser la librería dentro de una ruta del sistema donde tengamos capacidad de escritura, en este caso en /tmp:

Ahora cuando ejecutamos el script como el usuario ROOT, definiendo en la misma linea de comando que queremos añadir la ruta /opt/ al PATH de Python, vemos que nos da un error. Esto es buena señal, significa que hemos podido secuestrar la librería y que evidentemente como no tenemos definido make_archive en nuestro archivo malicioso no ha podido importarlo.

Pero sin embargo, si vemos los permisos que tiene /bin/bash vemos que ya tiene el bit SUID asignado:

El remate final es sencillo, bash -p y ya hemos escalado privilegios en la máquina.

Jorge Escrito por: