Skip to main content
Synced from an Obsidian vault

For graph and advanced features, download the full Intel Codex Vault and open it in Obsidian.

Active Directory Pentesting SOP (Authorized)

Authorized environments only. This SOP covers defensive assessment of Active Directory environments.


Table of Contents


Pre-Engagement & Authorization

Active Directory testing reaches the highest-trust assets in the environment (Domain Controllers, replication APIs, the KDC's krbtgt key). Without explicit, written authorization for each privileged path you intend to walk, a single mis-scoped Kerberoast or DCSync rehearsal becomes a CFAA / Computer Misuse Act / Cybercrime Directive matter — see Legal & Ethics for the canonical legal framework. Engagement-time logistics (time windows, blackout schedule, rollback verification) are captured separately in §1; this section is the authorization gate that must close before §1 begins.

Authorization Checklist

  • Signed Rules of Engagement enumerates which privilege tiers are in-scope: workstation / server admin, Domain Admin, Enterprise Admin, Schema Admin, krbtgt key (Golden Ticket simulation). Anything not listed is out of scope.
  • Sacrificial accounts and a sacrificial host pool are identified in writing — testing uses these, not real users or live workstations.
  • Hash-extraction techniques explicitly authorized or denied: DCSync (DRSUAPI replication), NTDS.dit + SYSTEM hive offline export, LSASS dump on member servers, DPAPI master-key extraction.
  • Kerberos delegation testing scope set: Kerberoasting volume cap, AS-REP roasting opt-in list, S4U2Self / S4U2Proxy abuse on which hosts, RBCD write attempts on which OUs.
  • Lateral movement boundaries: which forests, trusts, and child domains are reachable; which are off-limits. Cross-forest or cross-tenant pivots require separate written authorization.
  • Blue-team coordination confirmed with whoever runs Microsoft Defender for Identity (formerly ATA / Azure ATP), Defender XDR, the SIEM, and the SOC bridge. Names plus 24/7 contacts captured. Emergency-stop signal agreed.
  • Recovery preconditions met: tested DC system-state backup, AD Recycle Bin enabled, replication healthy (repadmin /replsummary), and a documented krbtgt reset procedure if Golden Ticket simulation is in scope.

Lab Environment Requirements

  • Standalone AD lab forest matching the target's functional level (2016 / 2019 / 2022 — relevant for Kerberos AES-only enforcement, claims, and PAC behavior). Do not rehearse against the target's DCs.
  • Sacrificial DC with at least one replica peer so destructive primitives (DCSync, AdminSDHolder ACL flips, krbtgt rotation) can be observed without quorum loss.
  • BloodHound CE collector (github.com/SpecterOps/BloodHound; legacy BloodHoundAD/BloodHound 4.x archived upstream [verify 2026-04-26]) run end-to-end against the lab first to confirm collector version, ingest schema, and SharpHound options match the target's PowerShell / .NET tolerance.
  • Coercion primitives (PetitPotam, Coercer, DFSCoerce, PrinterBug) verified on a lab MS-RPRN / MS-EFSR / MS-DFSNM listener before being pointed at production — coercion can hang or crash legacy print spoolers.
  • Golden Ticket, Silver Ticket, and Diamond / Sapphire Ticket forging tested in the lab against a sacrificial krbtgt; never extract or forge against a production krbtgt without dedicated written approval and a krbtgt-rotation runbook.
  • AD Certificate Services abuse (ESC1–ESC15 family [verify 2026-04-26]) rehearsed against a lab CA — Certipy / certutil enrollment requests on production CAs are loud and may issue real certificates that need revocation.

Disclosure-Ready Posture

Stand up the evidence pipeline before the first ticket request, not after the report deadline. Capture every SPN read, ACL diff (Get-DomainObjectAcl before/after), GPO-version delta, AdminSDHolder modification, and SACL change at the moment it happens — chain-of-custody per Collection Log (UTC timestamps, source IP, operator handle, SHA-256 of each artifact). Kerberos ticket exports (.kirbi, ccache) hold replayable credentials: encrypt at rest, store separately from the report deliverable, and schedule destruction in the engagement letter — OPSEC framing per OPSEC. Password-spraying attempts get logged with timestamp, source IP, and targeted sAMAccountName so the blue team can correlate against 4625 / 4771 events. Coordinate a SACL-preservation request with the SOC up front — 4662 (DS-Replication-Get-Changes), 4768 / 4769 (TGT / TGS), 4624 Type 3, and Defender for Identity alerts are the primary corroboration. Defang any IOC that ships in the final write-up and route the hand-off through Reporting & Disclosure; tickets and hashes never travel in the same channel as the executive summary.


1. Engagement Setup

Pre-Engagement

  • Obtain written authorization (signed Rules of Engagement)
  • Define scope: domains, forests, trusts, target OUs/hosts
  • Identify test accounts vs production accounts
  • Set time windows and blackout periods (avoid business-critical hours)
  • Establish emergency contacts (IT, security team, change management)
  • Confirm rollback procedures exist
  • Determine if testing lab environment or limited production scope

Objectives (Examples)

  • Identify misconfigurations enabling lateral movement and privilege escalation
  • Validate detection/monitoring efficacy for AD attack paths
  • Test privileged group memberships and delegation
  • Review tiering model implementation
  • Assess Kerberos security (Kerberoasting, AS-REP roasting)
  • Evaluate GPO security and deployment

2. Domain Enumeration (Read-Only)

Basic Domain Information

# Domain information
Get-ADDomain
Get-ADForest

# Domain Controllers
Get-ADDomainController -Filter *

# Domain trusts
Get-ADTrust -Filter *
nltest /domain_trusts

# Forest trusts
Get-ADForest | Select-Object -ExpandProperty Domains

User Enumeration

# All domain users
Get-ADUser -Filter * -Properties *

# Enabled users only
Get-ADUser -Filter {Enabled -eq $true} -Properties *

# Users with AdminCount=1 (protected accounts)
Get-ADUser -Filter {AdminCount -eq 1} -Properties AdminCount

# Users with password not required
Get-ADUser -Filter {PasswordNotRequired -eq $true}

# Users with password never expires
Get-ADUser -Filter {PasswordNeverExpires -eq $true}

# Users with no password expiration and enabled
Get-ADUser -Filter {(PasswordNeverExpires -eq $true) -and (Enabled -eq $true)}

# Service Principal Names (for Kerberoasting)
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName

# Pre-Windows 2000 compatible access
Get-ADUser -Filter * -Properties PrimaryGroupID | Where-Object {$_.PrimaryGroupID -eq 515}

Group Enumeration

# All domain groups
Get-ADGroup -Filter * -Properties *

# Privileged groups
Get-ADGroupMember "Domain Admins"
Get-ADGroupMember "Enterprise Admins"
Get-ADGroupMember "Schema Admins"
Get-ADGroupMember "Administrators"
Get-ADGroupMember "Account Operators"
Get-ADGroupMember "Backup Operators"
Get-ADGroupMember "Print Operators"
Get-ADGroupMember "Server Operators"

# Nested group memberships (recursive)
Get-ADGroupMember "Domain Admins" -Recursive

# Groups with AdminCount=1
Get-ADGroup -Filter {AdminCount -eq 1}

Computer Enumeration

# All domain computers
Get-ADComputer -Filter * -Properties *

# Domain Controllers
Get-ADComputer -Filter {PrimaryGroupID -eq 516} -Properties OperatingSystem

# Servers
Get-ADComputer -Filter {OperatingSystem -like "*Server*"} -Properties OperatingSystem

# Workstations
Get-ADComputer -Filter {OperatingSystem -like "*Windows 10*" -or OperatingSystem -like "*Windows 11*"}

# Computers with unconstrained delegation
Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation

# Computers with constrained delegation
Get-ADComputer -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo

OU Structure

# List all OUs
Get-ADOrganizationalUnit -Filter * | Select-Object Name,DistinguishedName

# Check GPO links per OU
Get-ADOrganizationalUnit -Filter * | Select-Object Name,LinkedGroupPolicyObjects

3. BloodHound Analysis

Data Collection

Using SharpHound (Windows):

# SharpHound CE collector — pair with the BloodHound CE backend version
# https://github.com/SpecterOps/SharpHound (legacy BloodHoundAD/BloodHound is archived)

# Run collection (all methods)
.\SharpHound.exe -c All

# Stealthy collection (avoid DCOnly)
.\SharpHound.exe -c Session,Trusts,ACL,Container,Group,LocalAdmin,RDP,DCOM,PSRemote

# Specify domain
.\SharpHound.exe -c All -d domain.local

# Exclude Domain Controllers from session enumeration (less noisy)
.\SharpHound.exe -c All --ExcludeDCs

Verify the SharpHound CE collection-method names against the installed collector — the CE flag set has shifted from legacy SharpHound across releases [verify 2026-04-26].

Using BloodHound.py (Linux):

# Install — the upstream is `dirkjanm/BloodHound.py`; PyPI `bloodhound` package is the same project [verify 2026-04-26]
pip install bloodhound

# Run collection
bloodhound-python -u username -p password -d domain.local -dc dc01.domain.local -c All

# With NTLM hash
bloodhound-python -u username --hashes :NTLMhash -d domain.local -dc dc01.domain.local -c All

Confirm the BloodHound.py output schema matches your BloodHound CE backend version — bloodhound-python historically produced legacy-schema JSON; CE-compatible output may require the --zip / CE-mode flag in current releases [verify 2026-04-26].

Import & Analysis

  1. Start Neo4j database (BloodHound CE bundles Neo4j+Postgres in Docker Compose; standalone Neo4j is only needed for legacy 4.x):
sudo neo4j console
# Navigate to http://localhost:7474
# Default creds: neo4j/neo4j (forced password change on first login)
  1. Start BloodHound CE (Docker Compose is the canonical install since the 2023 CE release):
# Reference: https://github.com/SpecterOps/BloodHound (CE — Postgres + Neo4j + UI)
# Legacy BloodHound 4.x JS desktop client is end-of-life; CE web UI replaces it.
# `BloodHound --no-sandbox` only applies to the legacy Electron client [verify 2026-04-26].
  1. Import collected data: upload the SharpHound CE ZIP via the BloodHound CE web UI (legacy "drag .json into the desktop GUI" flow only applies to BloodHound 4.x).

Pre-Built Queries to Run

Shortest Paths:

  • Shortest Paths to Domain Admins
  • Shortest Paths to High Value Targets
  • Shortest Paths from Owned Principals
  • Shortest Paths from Kerberoastable Users

Domain Information:

  • Find all Domain Admins
  • Find Workstations where Domain Users can RDP
  • Find Servers where Domain Users can RDP
  • Find Computers where Domain Users are Local Admin

Kerberos:

  • List all Kerberoastable Accounts
  • AS-REP Roastable Users (Do not require Pre-Authentication)

Delegation:

  • Find Computers with Unconstrained Delegation
  • Find Computers with Constrained Delegation
  • Shortest Paths from Computers with Unconstrained Delegation

ACLs:

  • Find Principals with DCSync Rights
  • Users with Foreign Domain Group Membership
  • Groups with Foreign Domain Group Membership

Custom Cypher Queries

// Users with path to Domain Admins (excluding direct members)
MATCH (u:User),(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}),
p=shortestPath((u)-[*1..]->(g))
WHERE NOT (u)-[:MemberOf]->(g)
RETURN p

// Computers with sessions from privileged (Tier-0) users
// BloodHound CE: high-value is exposed via `system_tags CONTAINS 'admin_tier_0'`.
// Legacy BloodHound 4.x: `g.highvalue = true` (kept for old datasets).
MATCH (c:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group)
WHERE g.system_tags CONTAINS 'admin_tier_0'
RETURN c.name, u.name, g.name

// Users with GenericAll on computers
MATCH (u:User)-[:GenericAll]->(c:Computer)
RETURN u.name, c.name

// Find owned users with paths to Tier-0 (high-value) targets
MATCH (u:User {owned:true}),(g:Group)
WHERE g.system_tags CONTAINS 'admin_tier_0'
WITH u, g
MATCH p=shortestPath((u)-[*1..]->(g))
RETURN p

4. Privilege Escalation Paths

Kerberoasting

Identify targets:

# PowerShell
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName,MemberOf

Request service tickets (for offline cracking):

# Using Rubeus
.\Rubeus.exe kerberoast /outfile:kerberoast_hashes.txt

# Using Invoke-Kerberoast (PowerView)
Invoke-Kerberoast -OutputFormat Hashcat | fl

Crack with hashcat:

hashcat -m 13100 kerberoast_hashes.txt wordlist.txt

Remediation recommendations:

  • Use strong passwords for service accounts (25+ characters)
  • Use Group Managed Service Accounts (gMSA)
  • Monitor for unusual TGS requests

AS-REP Roasting

Identify targets:

# Users with "Do not require Kerberos preauthentication"
Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth

Request AS-REP hashes:

# Using Rubeus
.\Rubeus.exe asreproast /outfile:asrep_hashes.txt

# Using Impacket (Linux)
GetNPUsers.py domain.local/ -usersfile users.txt -dc-ip 10.0.0.1

Crack with hashcat:

hashcat -m 18200 asrep_hashes.txt wordlist.txt

Remediation:

  • Enable Kerberos pre-authentication for all accounts
  • Monitor for AS-REP requests without pre-auth

Unconstrained Delegation

Find computers/users with unconstrained delegation:

# Computers
Get-ADComputer -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation

# Users
Get-ADUser -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation

Risk:

  • Any service on these systems can impersonate any user
  • If admin connects, attacker can extract TGT and impersonate them

Remediation:

  • Remove unconstrained delegation (use constrained instead)
  • Protect sensitive accounts with "Account is sensitive and cannot be delegated"
  • Monitor TGT requests from delegation-enabled systems

Constrained Delegation

Find accounts with constrained delegation:

Get-ADComputer -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo
Get-ADUser -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo

Risk:

  • Can impersonate any user to specific services
  • With protocol transition (TrustedToAuthForDelegation / "Use any authentication protocol"), can request tickets on behalf of any user

Remediation:

  • Prefer Resource-Based Constrained Delegation (RBCD): the resource owner controls who can delegate, expressed via msDS-AllowedToActOnBehalfOfOtherIdentity on the target account — flipping the trust direction relative to classic Constrained Delegation.
  • Audit msDS-AllowedToActOnBehalfOfOtherIdentity writes for unexpected principals.
  • Monitor for S4U2Self/S4U2Proxy requests (Event 4769 with Service Name mismatch).

Resource-Based Constrained Delegation (RBCD) abuse

# Find computers where the configured delegators are non-default principals
Get-ADComputer -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
Where-Object { $_.'msDS-AllowedToActOnBehalfOfOtherIdentity' }

ms-DS-MachineAccountQuota defaults to 10 on a fresh AD install — any authenticated user can join up to 10 computer accounts to the domain and chain that into RBCD takeovers (classic Powermad → Rubeus s4u path). Audit the value:

Get-ADDomain | Select-Object -ExpandProperty DistinguishedName |
ForEach-Object { Get-ADObject -Identity $_ -Properties ms-DS-MachineAccountQuota }

Verify the 10-default applies to your forest functional level / install vintage and that no GPO has reduced it [verify 2026-04-26]. Microsoft guidance is to set the quota to 0 outside lab/imaging scenarios.

AD CS Abuse (ESC1–ESCn)

The Certified Pre-Owned paper (SpecterOps, 2021) introduced ESC1–ESC8; the inventory has expanded since (ESC9, ESC10, ESC11, ESC13, ESC14, ESC15+ documented across 2022–2025) [verify 2026-04-26 — confirm current upper bound against SpecterOps' updated whitepaper]. Treat any AD CS environment as in-scope for an authorized AD assessment.

Enumerate templates and CAs (Certipy):

# Reference: https://github.com/ly4k/Certipy
# Find vulnerable templates / misconfigured CAs
certipy find -u user@domain.local -p 'Password!' -dc-ip 10.0.0.1 -vulnerable

# Common ESC findings (paraphrased — confirm exact ESC IDs against current Certipy output):
# ESC1 — Subject in request, EnrolleeSuppliesSubject + Client Auth EKU
# ESC2 — Any Purpose EKU
# ESC3 — Enrollment Agent EKU
# ESC4 — Vulnerable template ACL (write to template)
# ESC6 — EDITF_ATTRIBUTESUBJECTALTNAME2 on the CA (deprecated by KB5014754)
# ESC7 — Vulnerable CA ACL (ManageCA / ManageCertificates)
# ESC8 — NTLM relay to AD CS web enrollment (HTTP/HTTPS)
# ESC9/10/11/13/14/15+ — see SpecterOps blog for current set [verify 2026-04-26]

Patching context: Microsoft KB5014754 (May 2022) introduced certificate strong-mapping; full enforcement was moved repeatedly and is currently in the rollout window — verify the enforcement date for your build [verify 2026-04-26].

Remediation pointers:

  • Remove EnrolleeSuppliesSubject + Client Auth EKU combinations on templates not intended for SAN-flexible enrollment.
  • Lock down ManageCA / ManageCertificates to a minimal Tier-0 group.
  • Disable AD CS web enrollment over HTTP and require Extended Protection for Authentication (EPA) on HTTPS endpoints to block NTLM relay (ESC8).
  • Audit certificate issuance with Event ID 4886/4887 on the CA.

Coercion Primitives

NTLM relay attacks against AD CS / LDAP / SMB rely on coerced authentication. Tooling consolidated significantly through 2023–2024; verify current canonical repos before use:

PrimitiveTriggerCanonical repo [verify 2026-04-26]
PetitPotamMS-EFSR EfsRpcOpenFileRaw / EfsRpcEncryptFileSrvgithub.com/topotam/PetitPotam
PrinterBugMS-RPRN RpcRemoteFindFirstPrinterChangeNotificationExgithub.com/leechristensen/SpoolSample
DFSCoerceMS-DFSNM NetrDfsAddStdRootgithub.com/Wh04m1001/DFSCoerce
Coercer (consolidator)All of the above + auto-detectiongithub.com/p0dalirius/Coercer

Coercion can hang or crash legacy print spoolers and DFS Namespace servers. Test in lab against the same patch level before production use; have a rollback contact on standby.


5. ACL Abuse & Dangerous Permissions

Common ACL Attack Paths

GenericAll:

  • Full control over object
  • Can reset passwords, modify group membership, etc.

WriteDACL:

  • Can modify permissions on object
  • Grant yourself GenericAll, then exploit

WriteOwner:

  • Can take ownership of object
  • Then grant permissions

GenericWrite:

  • Can write to most attributes
  • For users: modify scriptPath, servicePrincipalName
  • For computers: can perform RBCD attack

ForceChangePassword:

  • Can reset user password without knowing current password

Find Dangerous ACLs

Using PowerView:

# Download PowerView
# https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1

# Find ACLs where non-standard principals have control
Find-InterestingDomainAcl -ResolveGUIDs

# Find ACLs for specific user
Get-DomainObjectAcl -Identity "Domain Admins" -ResolveGUIDs

# Find users with WriteDACL on Domain Admins
Get-DomainObjectAcl -Identity "Domain Admins" -ResolveGUIDs | Where-Object {$_.ActiveDirectoryRights -match "WriteDacl"}

Using BloodHound:

  • Pre-built queries under "Dangerous Privileges"
  • Review edges: GenericAll, WriteDacl, WriteOwner, GenericWrite

DCSync Rights

Find principals with DCSync rights:

# PowerView
Get-DomainObjectAcl "DC=domain,DC=local" -ResolveGUIDs | Where-Object {
($_.ObjectType -match 'replication') -or
($_.ActiveDirectoryRights -match 'GenericAll')
}

Risk:

  • Allows replication of AD data (including password hashes)
  • Equivalent to Domain Admin

Remediation:

  • Only Domain Controllers and specific backup systems should have this right
  • Monitor for DS-Replication-Get-Changes events (4662)

6. Group Policy Object (GPO) Review

Enumerate GPOs

# List all GPOs
Get-GPO -All

# GPOs linked to specific OU
Get-GPInheritance -Target "OU=Servers,DC=domain,DC=local"

# Find GPOs with specific settings
Get-GPOReport -All -ReportType HTML -Path C:\GPOReport.html

GPO Security Issues

Check for:

  • Authenticated Users with edit rights on GPOs
  • GPOs with password/credential settings
  • Unrestricted software installation policies
  • Weak LAPS configuration
  • Disabled security settings (Windows Firewall, Defender)

Find GPOs modifiable by non-admins:

# Using PowerView
Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {
($_.ActiveDirectoryRights -match "WriteProperty|GenericAll|GenericWrite|WriteDacl|WriteOwner") -and
($_.SecurityIdentifier -match "S-1-5-21-.*-[0-9]{4,}")
}

LAPS (Local Administrator Password Solution)

Two products coexist in 2026: Legacy LAPS (separate MSI, attribute ms-Mcs-AdmPwd) and Windows LAPS (in-box on Windows 11 / Server 2022 and back-ported to Windows 10/Server 2019/2022 via April 2023 update [verify 2026-04-26]; attributes msLAPS-Password, msLAPS-EncryptedPassword, msLAPS-PasswordExpirationTime). Migration to Windows LAPS is recommended; both attributes may be present during transition.

Check if legacy LAPS is deployed:

Get-ADComputer -Filter * -Properties ms-Mcs-AdmPwd | Where-Object {$_."ms-Mcs-AdmPwd" -ne $null}

Check if Windows LAPS is deployed:

Get-ADComputer -Filter * -Properties msLAPS-Password,msLAPS-EncryptedPassword,msLAPS-PasswordExpirationTime |
Where-Object { $_.'msLAPS-Password' -or $_.'msLAPS-EncryptedPassword' }

Check who can read LAPS passwords:

# Using PowerView — repeat for msLAPS-Password / msLAPS-EncryptedPassword to cover Windows LAPS
Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {
$_.ObjectType -like "ms-Mcs-AdmPwd" -or $_.ObjectType -like "msLAPS-*"
} | Select-Object ObjectDN,SecurityIdentifier

7. Password Policy & Account Security

Domain Password Policy

Get-ADDefaultDomainPasswordPolicy

# Fine-Grained Password Policies
Get-ADFineGrainedPasswordPolicy -Filter *

Check for weak policies:

  • Minimum password length < 14 characters
  • Password history < 24
  • Maximum password age > 60 days
  • Lockout threshold disabled or > 5 attempts

Stale Accounts

# Users not logged in for 90+ days
$90days = (Get-Date).AddDays(-90)
Get-ADUser -Filter {LastLogonDate -lt $90days} -Properties LastLogonDate

# Computers not logged in for 90+ days
Get-ADComputer -Filter {LastLogonDate -lt $90days} -Properties LastLogonDate

# Disabled accounts still in privileged groups
Get-ADGroupMember "Domain Admins" | Get-ADUser | Where-Object {$_.Enabled -eq $false}

8. Service Accounts & Credentials

Service Account Checks

# Accounts with SPNs (service accounts)
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName,PasswordLastSet,PasswordNeverExpires

# Check for old password last set dates
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties PasswordLastSet |
Where-Object {$_.PasswordLastSet -lt (Get-Date).AddYears(-1)}

Red flags:

  • Service accounts in Domain Admins
  • Service accounts with PasswordNeverExpires
  • Service accounts with interactive logon rights
  • SPNs on privileged accounts

Credentials in SYSVOL/Scripts

Check for passwords in Group Policy Preferences (cpassword):

# Search SYSVOL for cpassword attribute (Groups.xml)
findstr /S /I cpassword \\domain.local\sysvol\domain.local\policies\*.xml

Check scripts for hardcoded credentials:

Get-ChildItem \\domain.local\SYSVOL\domain.local\scripts -Recurse -Include *.ps1,*.bat,*.vbs |
Select-String -Pattern "password","pwd","pass"

9. Monitoring & Detection Review

Event Log Analysis

Check if important events are logged:

# Audit policy
auditpol /get /category:*

# Check for PowerShell logging
Get-ItemProperty HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
Get-ItemProperty HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription

Key events to monitor:

  • 4624 (Successful logon)
  • 4625 (Failed logon)
  • 4672 (Special privileges assigned)
  • 4768/4769 (Kerberos TGT/TGS requests)
  • 4776 (NTLM authentication)
  • 4662 (DCSync - replication operation)
  • 7045 (Service installed)

Protected Users Group

# Check if high-value accounts are in Protected Users
Get-ADGroupMember "Protected Users"

Benefits:

  • No NTLM authentication
  • No DES or RC4 in Kerberos
  • No delegation
  • TGT max lifetime 4 hours

10. Attack Simulation (Controlled Testing)

Red Team TTPs to Test Detection For

Initial Access:

  • Password spraying (low-volume, controlled)
  • AS-REP roasting
  • Kerberoasting

Lateral Movement:

  • Pass-the-Hash (in test environment)
  • Pass-the-Ticket
  • Overpass-the-Hash

Privilege Escalation:

  • ACL abuse (WriteDACL → GenericAll)
  • Unconstrained delegation exploitation
  • GPO modification

Persistence:

  • Golden Ticket — test environment only; never forge against a production krbtgt without a krbtgt-rotation runbook (see "krbtgt reset playbook" below)
  • Silver Ticket — service-account TGS forgery
  • Diamond / Sapphire Ticket — modified-PAC variants of Golden, more PAC-validation-evasive [verify 2026-04-26 — implementation specifics evolve with Rubeus / Impacket releases]
  • DCSync — replication-rights abuse to extract krbtgt and other secrets; equivalent to DA in impact

Detection blue-team context: the canonical AD-aware monitoring product was rebranded Microsoft Defender for Identity (formerly Azure Advanced Threat Protection / Azure ATP, formerly Advanced Threat Analytics / ATA — ATA reached end-of-life 2026-01-31 [verify 2026-04-26]). Coordinate test windows with whoever runs Defender for Identity and Defender XDR.

krbtgt reset playbook

If Golden Ticket simulation is in scope, ensure the customer has the canonical reset twice with a delay runbook ready (Microsoft / SpecterOps publish on this; the second reset must wait at least one full Kerberos ticket lifetime — default 10 hours — after the first so existing TGTs can renew once and be replaced rather than be invalidated mid-flight). Microsoft's New-KrbtgtKeys.ps1 reference script automates this. After a real Golden Ticket compromise (not a simulation), rotate twice immediately even at the cost of session disruption.

Safety:

  • Coordinate with SOC/detection team
  • Use test accounts and canary systems
  • Monitor for alerts during tests
  • Document all actions with timestamps

11. Common Misconfigurations Checklist

  • Domain/Enterprise Admins with more members than necessary
  • Service accounts in privileged groups
  • Computers with unconstrained delegation
  • Users with "Password never expires" enabled
  • Weak password policy (< 14 chars, no complexity)
  • LAPS not deployed or improperly configured
  • Authenticated Users can modify GPOs
  • No Protected Users group usage for VIPs
  • AdminSDHolder not monitored for modifications
  • Stale accounts (90+ days inactive) not disabled
  • Pre-Windows 2000 Compatible Access group populated
  • Service accounts with interactive logon rights
  • Credentials in SYSVOL scripts/GPP
  • PowerShell logging disabled
  • No monitoring for DCSync (4662 events)

12. Evidence Collection

For each finding, document:

  • Object path (DN)
  • Exact PowerShell/tool command used
  • Full output (sanitize if needed)
  • Timestamp (UTC)
  • Screenshot for BloodHound paths
  • Risk level and business impact

File structure:

/Evidence/{engagement_id}/AD/
├── bloodhound/
│ ├── 20251005_bloodhound_data.zip
│ └── screenshots/
├── enumeration/
│ ├── 20251005_domain_admins.txt
│ ├── 20251005_kerberoastable_users.txt
│ └── 20251005_unconstrained_delegation.txt
├── gpo/
│ ├── 20251005_gpo_report.html
│ └── 20251005_sysvol_creds.txt
├── acls/
│ └── 20251005_dangerous_acls.txt
└── hashes/
└── evidence_hashes.txt

Hash all files:

Get-FileHash *.txt,*.html,*.zip | Export-Csv hashes.csv

13. Reporting

Finding Format

Title: Service Accounts with Unconstrained Delegation
Severity: Critical
Affected Objects:
- SQLSVC@domain.local (CN=SQLSVC,OU=Service Accounts,DC=domain,DC=local)
- WEBSVC@domain.local (CN=WEBSVC,OU=Service Accounts,DC=domain,DC=local)

Description:
Service accounts configured with unconstrained delegation can be abused to
impersonate any domain user, including Domain Admins, if they authenticate
to the compromised system.

Impact:
If an attacker compromises the SQL or Web servers, they can extract TGTs
from memory for any user who authenticates, leading to full domain compromise.

Evidence:
Get-ADUser -Filter {TrustedForDelegation -eq $true} -Properties TrustedForDelegation
Output: [screenshot/paste]

Attack Path (BloodHound):
[Screenshot showing path from SQLSVC to Domain Admins]

Remediation:
1. Remove unconstrained delegation from service accounts
2. Implement constrained or resource-based constrained delegation instead
3. Add sensitive accounts to Protected Users group
4. Enable "Account is sensitive and cannot be delegated" for VIP accounts

Verification:
1. Re-run: Get-ADUser -Filter {TrustedForDelegation -eq $true}
2. Verify no service accounts have TrustedForDelegation=True
3. Confirm Protected Users group contains Domain/Enterprise Admins

Remediation Priority

  1. Critical: Unconstrained delegation, DCSync rights to non-DCs, DA credentials in SYSVOL
  2. High: Kerberoastable privileged accounts, weak ACLs on admin groups, no LAPS
  3. Medium: Stale privileged accounts, weak password policy, missing audit logging
  4. Low: Informational findings, hardening recommendations

Canonical legal/ethics framework lives in Legal & Ethics; OPSEC framework in OPSEC. This section captures only AD-specific operational guardrails — do not re-derive CFAA / Computer Misuse Act / Cybercrime Directive content here.

  • Read-only enumeration first: Gather data before testing exploitability
  • Coordinate with stakeholders before password attacks or GPO modifications
  • Use test accounts for exploitation testing (not production accounts)
  • Monitor for impact: Watch for service disruptions, lockouts, replication issues
  • Stop immediately if Domain Controllers show instability — replication failures during a test are a stop-the-engagement event, not a "we'll fix it tomorrow" issue
  • Document everything for audit trail and legal defensibility (chain-of-custody per Collection Log)
  • Respect scope: Do not pivot to out-of-scope domains/forests without approval — cross-forest and cross-tenant pivots require separate written authorization
  • Hand off the report through Reporting & Disclosure; never ship Kerberos tickets, NTLM hashes, or NTDS.dit extracts in the same channel as the executive summary

15. Tools Reference

ToolPurposeLink
BloodHound CEAD relationship mapping (current SpecterOps fork; replaces legacy BloodHoundAD/BloodHound 4.x)github.com/SpecterOps/BloodHound
SharpHound (CE)BloodHound CE data collector (Windows)github.com/SpecterOps/SharpHound
BloodHound.pyBloodHound collector (Linux)github.com/dirkjanm/BloodHound.py [verify 2026-04-26]
PowerView (PowerSploit)AD enumeration (PowerShell) — unmaintained since 2018; functional but signature-richgithub.com/PowerShellMafia/PowerSploit
PowerView.py / dsinternals / ldeepModern Python successors for AD enumeration (cross-platform, less AV-flagged)github.com/the-useless-one/pywerview [verify 2026-04-26]
RubeusKerberos abuse toolkitgithub.com/GhostPack/Rubeus
ImpacketPython AD toolkit (now under Fortra)github.com/fortra/impacket
NetExec (nxc)Successor to deprecated CrackMapExec; SMB/LDAP/WinRM/MSSQL sweepsgithub.com/Pennyw0rth/NetExec
CertipyAD CS (ESC1–ESCn) enumeration & abusegithub.com/ly4k/Certipy
CoercerMS-RPRN / MS-EFSR / MS-DFSNM coercion (PetitPotam, DFSCoerce, PrinterBug variants consolidated)github.com/p0dalirius/Coercer
ADReconAD data aggregationgithub.com/adrecon/ADRecon
PingCastleAD security auditpingcastle.com
Purple KnightAD security assessmentpurple-knight.com

16. Reference Resources

Comprehensive Knowledge Bases

Attack Technique Deep Dives

Defense & Hardening

Cheat Sheets & Quick References


17. Common Pitfalls

  • ❌ Running SharpHound with DCOnly in production (generates excessive traffic)
  • ❌ Not coordinating with SOC before testing (causes alert fatigue)
  • ❌ Using production admin accounts for testing (contaminates evidence)
  • ❌ Requesting too many Kerberos tickets at once (triggers detections)
  • ❌ Not checking scope before enumerating trusts (cross-domain pivots)
  • ❌ Forgetting to sanitize credentials in reports/screenshots
  • ❌ Relying only on BloodHound (manual validation is critical)
  • ❌ Not testing detection coverage (pentest should validate monitoring)

AD pentesting reaches the highest-trust assets in the environment. The canonical legal framework is in Legal & Ethics; this section names only the AD-specific exposures.

  • Authorization scope is per-tier. A signed RoE that authorizes "internal pentest" without naming Domain Admin / Enterprise Admin / krbtgt simulation does not implicitly authorize Golden Ticket forging or DCSync against production. Get each privileged path in writing.
  • Hash and ticket material is regulated data in some jurisdictions. Treat NTDS.dit extracts, LSASS dumps, and .kirbi / ccache exports as sensitive personal data under GDPR-equivalent regimes — encrypt at rest, restrict access, schedule destruction in the engagement letter.
  • Coercion and relay primitives can disrupt production. PetitPotam / DFSCoerce / PrinterBug calls have crashed legacy spoolers and DFS Namespace servers in the wild. Test against the same patch level in lab first; have a rollback contact on standby.
  • AD CS misuse can issue real certificates. Certipy enrollment requests against a production CA produce live, trusted certificates that need explicit revocation. Lab-rehearse first; coordinate revocation with the customer's PKI team.
  • krbtgt is uniquely sensitive. Never extract or forge against a production krbtgt without a tested rotation runbook. After a real Golden Ticket compromise (not simulation), rotate twice immediately even at session-disruption cost.
  • Cross-domain / cross-forest / cross-tenant pivots require separate written authorization. Trust enumeration that reads trust objects is generally in scope; traversing the trust to query objects in the other forest is usually not.

OPSEC framing (operator handle, sacrificial-host pool, IOC defang in the report) lives in OPSEC.


Analysis:

Pentesting & Security:

Engagement governance:

  • Legal & Ethics - Canonical CFAA / CMA / Cybercrime Directive framework
  • OPSEC - Operator handle, sacrificial accounts, IOC defang
  • Collection Log - Chain-of-custody for tickets, hashes, NTDS extracts
  • Reporting & Disclosure - Out-of-band hand-off of credentials, defanged report delivery

Version: 1.1 Last Updated: 2026-04-26 Review Frequency: Quarterly (fast-rotating attacker tradecraft per CLAUDE.md watchlist)