Forward THM
Forward THM The objective of the Forward room was to move through the compromised Active Directory environment and retrieve the Administrator flag. Screenshot 2026-08-05 at 00-12-45 The room already provided an initial set of domain credentials: Unlike a normal machine, we did not need to find the initial foothold. We were already inside the domain as j.smith, and the challenge was to find a path from this low-privileged account to full control of the environment. After starting the machine and connecting to the TryHackMe VPN, the target IP address was: Nmap Scanning I started with an Nmap scan to understand what services were exposed by the target. Analysing the Nmap Scan The combination of DNS, Kerberos, LDAP, SMB, and Global Catalog services immediately suggested that the target was an Active Directory Domain Controller. The scan also revealed the main details of the environment: RDP was exposed on port 3389, and WinRM was available on port 5985, giving us two possible options for remote access if the supplied account had the required permissions. SMB signing was enabled and required, so SMB relay attacks were not a useful direction here. Since we already had valid domain credentials, I focused instead on authenticated enumeration. Adding the Domain to the Hosts File I added the domain name to /etc/hosts so that the tools on my attack machine could resolve it correctly. Validating the Provided Credentials Before continuing, I confirmed that the credentials supplied by the room were valid. The successful authentication confirmed that j.smith was a valid domain user. SMB Share Enumeration I checked the available SMB shares to see whether the account could access any files containing credentials, scripts, backups, or configuration data. The only custom share that stood out was: I connected to it using smbclient. The share was empty, so there was nothing useful to retrieve from it. Enumerating Domain Users Next, I listed the domain users to understand what accounts existed in the environment. Apart from the default domain accounts, the main users were: The descriptions suggested that the accounts belonged to different levels of the IT and Help Desk teams. At this point, I did not have credentials for the other users, but the account names would be useful later. Testing RDP Access Since RDP was open, I checked whether j.smith was allowed to log in remotely. The credentials worked over RDP, so I connected to the system using xfreerdp3. Screenshot 2026-08-05 at 00-35-39 Discovering a KeePass Database While looking through the j.smith profile, I found a file named: The file was located in the Documents folder and was clearly a KeePass database. Since password managers often contain credentials for other users or services, this became the next thing to investigate. I wanted a local copy of the file, so I reconnected through RDP with one of my Linux directories mounted as a shared drive. The shared drive appeared inside the Windows session, allowing me to copy the KeePass database directly to my attack machine. Screenshot 2026-08-05 at 00-38-02 Opening the KeePass Database I first tried opening the database locally. Screenshot 2026-08-05 at 00-39-13 The database asked for authentication, and I did not have the master password. I briefly looked into cracking it, but that approach did not work with the tools available in my setup. Instead of spending more time on that path, I checked whether KeePass was installed on the Windows system. Screenshot 2026-08-05 at 00-43-23 KeePass was already installed, so I opened it directly from the j.smith desktop. Screenshot 2026-08-05 at 00-44-34 The database was already loaded and gave three authentication options: I selected the Windows user account option. Because the database had been tied to the Windows profile, the current j.smith session was able to unlock it without knowing the master password. Screenshot 2026-08-05 at 00-46-30 Inside the database, I found credentials for another domain user: This gave us a new account to test and provided the next step in the lateral movement path. Validating the t.jones Credentials Before connecting through RDP, I validated the recovered credentials using NetExec. The credentials worked successfully, so I connected to the target as t.jones. Connecting as t.jones Screenshot 2026-08-05 at 00-50-41 After logging in, I checked the desktop, documents, running applications, and other accessible locations, but I could not find anything useful. Screenshot 2026-08-05 at 00-52-16 At this point, I was stuck with the t.jones account, so I decided to enumerate the Active Directory environment using BloodHound. Collecting BloodHound Data I used NetExec to collect the BloodHound data through LDAP. The collection completed successfully and generated a ZIP file containing the Active Directory data. I started BloodHound, uploaded the ZIP file, and marked t.jones as owned. After checking the outbound permissions of t.jones, I could not find any useful privilege-escalation path from that account. However, while checking the other users, I noticed that r.williams had interesting permissions. The next objective was to compromise the r.williams account. Enumerating Domain Users I listed the domain users again using the t.jones credentials. The two accounts that were still worth testing were: I added them to a file named users.txt. Testing for Password Reuse Since t.jones and r.williams were both Help Desk users, I tested whether the same password had been reused across their accounts. The password did not work for svc.helpdesk, but it worked for r.williams. The recovered credentials were: I marked r.williams as owned in BloodHound and continued checking the permissions available from this account. Password Reuse Leads to Further Privilege Escalation After compromising multiple user accounts, we discovered that r.williams was also using the same password. Password reuse is one of the most common weaknesses in Active Directory environments because compromising one account often leads to the compromise of additional users. Since we now have valid credentials for r.williams, we can mark the account as Owned in BloodHound to visualize the newly available attack paths. Screenshot 2026-08-05 at 01-04-42 After recalculating the graph, BloodHound reveals a very interesting relationship. The r.williams user has the AddAllowedToAct permission over the DC01$ computer account. This permission allows us to modify the Resource-Based Constrained Delegation (RBCD) configuration of the Domain Controller, which is a well-known privilege escalation technique in Active Directory. Understanding Resource-Based Constrained Delegation (RBCD) Before abusing this permission, it is important to understand what Resource-Based Constrained Delegation actually is. Traditional Kerberos delegation is configured on the account that performs the delegation. Resource-Based Constrained Delegation works differently. Instead of configuring the delegating account, the target computer itself specifies which computers are allowed to impersonate users when connecting to it. This trust relationship is stored inside the Active Directory attribute: If an attacker can modify this attribute on a computer object, they can authorize another computer account under their control to impersonate any domain user, including Domain Administrators, when authenticating to that computer. For this attack we have: | Object | Purpose | |---------|---------| | DC01$ | Target computer we want to compromise | | r.williams | User that has permission to modify DC01
#39;s delegation settings | | Pentestnotes$ | Machine account we will create and fully control | The overall attack consists of four stages: Create a machine account we control. Configure RBCD on the Domain Controller. Request a Kerberos ticket while impersonating the Administrator. Authenticate to the Domain Controller using that Kerberos ticket. Creating a Machine Account To abuse RBCD we first need a computer account that we completely control. By default, Active Directory allows authenticated users to create a limited number of machine accounts through the MachineAccountQuota setting (default value: 10). This behaviour is intended to simplify domain joins but is frequently abused during Active Directory attacks. Impacket provides the addcomputer utility which creates a new computer account using our compromised credentials. Output: Our newly created computer account is: Creating our own machine account is important because we fully control its credentials. Later, Kerberos will authenticate this machine and allow it to request delegated tickets on behalf of other users. Configuring Resource-Based Constrained Delegation Now that we own a computer account, we can instruct the Domain Controller to trust it for delegation. Using the permissions inherited from r.williams, we modify the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on the DC01$ computer object. Output: Let's understand what happened. Originally, the msDS-AllowedToActOnBehalfOfOtherIdentity attribute was empty, meaning no computer was trusted to impersonate users when connecting to DC01$. After executing the command, our Pentestnotes$ machine account becomes trusted by the Domain Controller. This means Kerberos will now allow our machine account to request service tickets for other users, including Administrator, by using the Kerberos S4U2Self and S4U2Proxy extensions. This trust relationship is the core of the entire RBCD attack. Requesting a Kerberos Service Ticket Now that delegation has been configured, we can request a Kerberos ticket while impersonating the Administrator account. Impacket's getST utility performs this automatically. Internally, the tool performs two Kerberos extensions: S4U2Self – Requests a service ticket while pretending to be another user. S4U2Proxy – Exchanges that ticket for a service ticket to another service that our delegated computer is allowed to access. We execute: Breaking down the output: A Ticket Granting Ticket (TGT) is first obtained for Pentestnotes$. Kerberos performs S4U2Self, allowing our machine account to request a ticket while pretending to be Administrator. Kerberos then performs S4U2Proxy, which exchanges that ticket for a valid CIFS service ticket to DC01. Finally, the ticket is saved locally inside a Kerberos credential cache (.ccache). Even though we never knew the Administrator's password, Kerberos issued us a valid service ticket because DC01 now trusts our machine account for delegation. Loading the Kerberos Ticket Linux Kerberos-aware tools use the environment variable KRB5CCNAME to determine which Kerberos credential cache should be used. We simply export the ticket that was generated in the previous step. We can verify that the ticket has been loaded correctly. Output: The output confirms that our current Kerberos session is authenticated as Administrator for the CIFS service running on DC01. Since Kerberos relies on tickets rather than passwords, any Kerberos-aware tool can now authenticate using this cached ticket. Updating Local Name Resolution Before connecting to the Domain Controller, we need to ensure that DC01.ctf.local resolves correctly. Add the following entry to the local /etc/hosts file. This step is important because Kerberos authentication is Service Principal Name (SPN) aware. The hostname used during authentication must match the hostname embedded inside the Kerberos ticket. If the hostname cannot be resolved correctly, Kerberos authentication will fail even though the ticket itself is completely valid. Authenticating as Domain Administrator With the Kerberos ticket loaded, we can authenticate to the Domain Controller without supplying a password or NTLM hash. Impacket's psexec supports Kerberos authentication using cached tickets. The -k option instructs Impacket to authenticate using Kerberos instead of NTLM, while -no-pass tells the tool not to prompt for credentials because our authentica