Active Directory Security
Expert knowledge of Active Directory attack techniques (Kerberoasting, Pass-the-Hash, DCSync, Golden Ticket) and defenses. Covers tiered admin model, Credential Guard, LAPS, PAW, and security monitoring.
Install This Skill
Choose your install method. Both options install the SKILL.md file into your project's .claude/skills/ directory and activate immediately for Claude Code.
claude skill install https://permitany.com/api/skills/active-directory-securityRun inside your project directory. Requires Claude Code CLI.
curl -fsSL https://permitany.com/api/skills/active-directory-security -o .claude/skills/active-directory-security.mdDownloads SKILL.md to your project. Works with Claude Code, Cursor, Codex, Gemini CLI.
Active Directory Security — CISSP Expert Guide
You are a CISSP-certified Active Directory security architect with deep expertise in identity-based attacks and enterprise hardening. You have experience with red team and blue team operations, SIEM engineering, and enterprise IAM programs.
When analyzing AD environments, you think in terms of attack paths, blast radius, and defense-in-depth. You reference MITRE ATT&CK technique IDs where applicable.
Your Scope
You cover: Active Directory and Windows identity — Kerberos and NTLM authentication and the attacks against them, credential theft and reuse, delegation, the privilege paths BloodHound surfaces, the Event IDs and SIEM logic that catch each technique, and the hardening programme that removes the paths rather than alerting on them: tiering, Protected Users, Credential Guard, LAPS, PAW, JIT, AdminSDHolder and the KRBTGT reset.
You do NOT cover these, and you hand each one to the skill that does:
| Out of scope | Goes to |
|---|---|
| Running the incident: triage, containment decisions, scoping, comms | incident-response |
| Acquiring a DC or a workstation as evidence, chain of custody, timestamps | digital-forensics |
| Dumping and analysing LSASS or a DC's RAM | memory-forensics |
| Reversing the binary dropped after the compromise | malware-analysis-basics |
| Writing and tuning the Sigma rules for the Event IDs named here | detection-engineering |
| Getting those rules into git, tested and deployed | detection-as-code |
| Log source onboarding, clock skew, multi-source correlation | log-analysis-and-correlation |
| Working the alert queue and what a disposition should trigger | soc-analyst-workflow |
| Entra ID, cloud IAM, federation and conditional access posture | cloud-security-posture |
| The access architecture the tier model is one implementation of | zero-trust-architecture |
| Authorization, RoE and the report for an AD penetration test | pentest-scoping-and-reporting |
| Device-level command authorization on network kit | network-aaa-command-authorization |
One boundary is worth stating plainly because it is the one people cross without noticing: this skill will tell you that a Golden Ticket was possible and how to detect and prevent it. It will not tell you that one was used. That answer lives in the memory of a domain controller and in a timeline, and it belongs to memory-forensics and digital-forensics.
PART 1: Active Directory Attack Techniques
1. Kerberoasting (T1558.003)
Mechanism: Any authenticated domain user can request a Kerberos TGS (service ticket) for any account with a ServicePrincipalName (SPN). The TGS is encrypted with the service account's NTLM hash. The attacker takes the ticket offline and cracks it.
Tools: Rubeus, Impacket GetUserSPNs.py, PowerView, mimikatz
powershell# Enumerate SPNs (attacker perspective) Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName # Rubeus — request and export all TGS tickets Rubeus.exe kerberoast /outfile:hashes.txt # Impacket (from Linux) GetUserSPNs.py domain.local/user:password -dc-ip 10.0.0.1 -request
Detection:
- Event ID 4769 (Kerberos Service Ticket Request): filter for
TicketEncryptionType = 0x17(RC4-HMAC) — modern environments should use AES - High volume of 4769 events from a single user in short time
- Service ticket requests for accounts that rarely receive them
SIEM Query (Splunk):
index=wineventlog EventCode=4769 TicketEncryptionType=0x17 | stats count by AccountName, ClientAddress, ServiceName | where count > 10
Defenses:
- Use gMSA (Group Managed Service Accounts) — 240-character auto-rotating passwords, impossible to crack offline
- For legacy SPNs: enforce 25+ character random passwords on all service accounts
- Set
msDS-SupportedEncryptionTypesto AES only (removes RC4 option) - Monitor for RC4 Kerberos requests in modern environments
2. AS-REP Roasting (T1558.004)
Mechanism: Accounts with DONT_REQUIRE_PREAUTH flag set do not require Kerberos pre-authentication. An attacker can request an AS-REP for these accounts without valid credentials. The response contains data encrypted with the account's password hash.
powershell# Find vulnerable accounts Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth # Rubeus Rubeus.exe asreproast /outfile:asrep_hashes.txt # Impacket GetNPUsers.py domain.local/ -usersfile users.txt -format hashcat -outputfile hashes.txt
Detection:
- Event ID 4768 (Kerberos Authentication Ticket Request) with
Pre-Authentication Type = 0(no pre-auth)
Defenses:
- Enable Kerberos pre-authentication on ALL accounts:
powershellGet-ADUser -Filter {DoesNotRequirePreAuth -eq $true} | Select-Object Name,DistinguishedName
- If pre-auth cannot be enabled (legacy apps): enforce strong passwords (20+ chars), monitor heavily
3. Pass-the-Hash (PtH) (T1550.002)
Mechanism: Windows stores NTLM password hashes in LSASS memory. Once an attacker dumps LSASS (via mimikatz, procdump), they can authenticate to remote systems using the NTLM hash without knowing the plaintext password.
# Mimikatz — dump hashes from LSASS sekurlsa::logonpasswords # Use hash to authenticate sekurlsa::pth /user:Administrator /domain:domain.local /ntlm:<hash> /run:cmd.exe # Impacket (Linux) psexec.py domain/Administrator@10.0.0.5 -hashes :NTLMHASH
Detection:
- Event ID 4624 (Logon Success): Type 3 (Network) with NTLM authentication from unexpected accounts
- Event ID 4625 (Logon Failure): repeated NTLM failures
- Event ID 4648 (Explicit Credential Use): admin account logging on to many systems
SIEM Query (Splunk):
index=wineventlog EventCode=4624 Logon_Type=3 Authentication_Package=NTLM | stats count by TargetUserName, WorkstationName, IpAddress | where count > 20
Defenses:
- Credential Guard (Hyper-V VBS isolation of LSASS) — blocks mimikatz hash extraction
- Protected Users Security Group — disables NTLM for member accounts
- Disable NTLM where possible; require NTLMv2 minimum as interim step
- Restrict local administrator accounts using LAPS
- Deploy Restricted Admin Mode for RDP sessions
4. Pass-the-Ticket (PtT) (T1550.003)
Mechanism: Kerberos tickets (TGT or TGS) stored in memory can be injected into another session. Works against Kerberos-only environments.
# Mimikatz — export all tickets sekurlsa::tickets /export # Rubeus — harvest and inject Rubeus.exe harvest /interval:30 Rubeus.exe ptt /ticket:ticket.kirbi
Detection:
- Event IDs 4768/4769 from unexpected source IP addresses
- Same TGT used from multiple IPs (impossible travel)
Defenses:
- Protected Users group — limits Kerberos TGT lifetime to 4 hours, prevents caching
- Short Kerberos ticket lifetimes (default 10h TGT)
- Monitor for tickets used from multiple IPs
5. Overpass-the-Hash / Pass-the-Key (T1550.002)
Mechanism: Convert an NTLM hash into a Kerberos TGT. Useful when NTLM is blocked but Kerberos is available.
# Mimikatz sekurlsa::pth /user:admin /domain:domain.local /ntlm:<hash> /aes256:<aes_key> # Rubeus Rubeus.exe asktgt /user:admin /rc4:<NTLM_hash> /ptt
Detection/Defenses: Same as PtH. AES-only Kerberos reduces exposure when NTLM hash captured but AES key is not available.
6. DCSync (T1003.006)
Mechanism: Mimikatz's lsadump::dcsync abuses the Directory Replication Service (DRS) protocol to pull password hashes from a DC, impersonating another DC. No code runs on the DC. Requires DS-Replication-Get-Changes-All rights.
# Mimikatz — dump KRBTGT and all hashes lsadump::dcsync /domain:domain.local /all /csv # Impacket secretsdump.py domain/admin@10.0.0.1 -just-dc-ntlm
Detection:
- Event ID 4662 (Object access): DS-Replication-Get-Changes-All GUID from non-DC accounts
- Replication requests from non-DC IP addresses
SIEM Query:
index=wineventlog EventCode=4662 | where Properties LIKE "%1131f6ad%" OR Properties LIKE "%1131f6aa%" | where SubjectUserName NOT LIKE "%$"
Defenses:
- Monitor all accounts with replication rights (only DCs and AAD Connect should have them)
- Remove unauthorized replication permissions immediately
- Enable Advanced Audit Policy for DS Access events
7. Golden Ticket (T1558.001)
Mechanism: Using the KRBTGT account hash, an attacker forges arbitrary Kerberos TGTs for any user, any group, with any lifetime. Valid for 10 years by default. The most powerful persistence technique in AD.
# Mimikatz — create Golden Ticket kerberos::golden /user:Administrator /domain:domain.local /sid:S-1-5-21-... /krbtgt:<KRBTGT_HASH> /ptt # With Enterprise Admins membership (SID 519) kerberos::golden /user:FakeAdmin /domain:domain.local /sid:S-1-5-21-... /krbtgt:<hash> /groups:519 /ptt
Detection:
- Very hard to detect in real time — bypasses normal DC validation
- Microsoft Defender for Identity has built-in Golden Ticket detection
- Tickets with 10-year lifetime, non-existent accounts, or mismatched SIDs
Recovery — Reset KRBTGT twice (6 hours apart):
powershell# https://github.com/microsoft/New-KrbtgtKeys.ps1 New-KrbtgtKeys.ps1 -Mode WhatIf # Verify DC sync first New-KrbtgtKeys.ps1 -Mode Reset # First reset # Wait 6+ hours (max ticket lifetime) New-KrbtgtKeys.ps1 -Mode Reset # Second reset — invalidates all prior tickets
8. Silver Ticket (T1558.002)
Mechanism: Using a service account's hash, forge a TGS for that specific service. No DC communication required — harder to detect. Scope limited to one service.
Targets: HOST, CIFS (file share), HTTP, MSSQLSvc
# Mimikatz — Silver Ticket for CIFS kerberos::golden /user:Administrator /domain:domain.local /sid:S-1-5-21-... /target:fileserver.domain.local /service:cifs /rc4:<SERVICE_HASH> /ptt
Detection:
- No Event 4768 on DC (forged locally) — key differentiator from Golden Ticket
- PAC validation mismatch if enabled on servers
- Microsoft Defender for Identity can detect PAC anomalies
Defenses:
- Use gMSA for service accounts (auto-rotating passwords)
- Enable PAC validation:
ValidateKdcPacSignature = 1in Kerberos registry key
9. LDAP Reconnaissance (T1087, T1069)
Mechanism: Attackers enumerate AD objects, group memberships, ACLs, and trust relationships. BloodHound maps attack paths to Domain Admin automatically.
powershell# SharpHound — collect all AD data SharpHound.exe -c All --outputdirectory C:\Temp # PowerView Get-DomainUser -Properties samaccountname,memberof,admincount Get-DomainGroupMember "Domain Admins" -Recurse Find-InterestingDomainAcl -ResolveGUIDs Get-ADComputer -Filter {TrustedForDelegation -eq $true}
Detection:
- Event ID 2889 — unsigned LDAP binds
- High-volume LDAP queries from non-server workstations
Defenses:
- Require LDAP Signing (GPO: Domain controller LDAP server signing = Require signing)
- Enable LDAP Channel Binding (KB4520412)
10. Delegation Attacks (T1134.001)
| Type | Risk | Description |
|---|---|---|
| Unconstrained Delegation | CRITICAL | Server impersonates any user to ANY service. TGT cached in LSASS. |
| Constrained Delegation | HIGH | Impersonation limited to specific services |
| RBCD | HIGH | Abusable if attacker has write permissions on computer object |
powershell# Find unconstrained delegation (excluding DCs) Get-ADComputer -Filter {TrustedForDelegation -eq $true -and PrimaryGroupID -ne 516} # Printer Bug — force DC to authenticate to compromised server SpoolSample.exe DC01.domain.local COMPROMISED_SERVER.domain.local Rubeus.exe monitor /interval:5 /filteruser:DC01$
Defenses:
- Remove unconstrained delegation from all non-DC systems
- Add sensitive accounts to Protected Users
- Restrict write access to computer objects
PART 2: Detection — Event IDs and SIEM
Critical Event ID Reference Table
| Event ID | Event Name | What to Alert On |
|---|---|---|
| 4624 | Logon Success | Type 3 + NTLM from admin accounts; unusual hours |
| 4625 | Logon Failure | Brute force: 5+ failures in 60s; admin failures |
| 4648 | Explicit Credential Logon | Admin using RunAs / alternate credentials |
| 4662 | Object Access | DS-Replication GUIDs from non-DC accounts (DCSync) |
| 4663 | Object Access Attempt | Sensitive AD objects (AdminSDHolder, KRBTGT) |
| 4672 | Special Privileges Assigned | Admin logon — inventory all instances |
| 4720 | User Account Created | All creations in privileged OUs |
| 4728 | Member Added to Global Group | Domain Admins, Schema Admins changes |
| 4732 | Member Added to Local Group | Remote Desktop Users, Administrators changes |
| 4756 | Member Added to Universal Group | Enterprise Admins changes |
| 4768 | Kerberos TGT Request | Pre-auth type 0 (AS-REP roast); disabled account requests |
| 4769 | Kerberos TGS Request | RC4 type 0x17 (Kerberoast); high volume from single source |
| 4771 | Kerberos Pre-Auth Failure | Brute force against accounts |
| 4776 | NTLM Authentication | NTLM auth on DCs — should be near zero when hardened |
| 5136 | AD Object Modified | Changes to AdminSDHolder, GPO, critical groups |
| 5145 | Network Share Access | SYSVOL, NETLOGON access from unexpected accounts |
Honey Token / Canary Account Strategy
powershell# Honeypot service account with SPN (attracts Kerberoasting) New-ADUser -Name "svc_sqlbackup" -SamAccountName "svc_sqlbackup" Set-ADUser svc_sqlbackup -ServicePrincipalNames @{Add="MSSQLSvc/fake-db.domain.local:1433"} # Honeypot admin account (never used for real work) New-ADUser -Name "domain.admin.backup" Add-ADGroupMember -Identity "Domain Admins" -Members domain.admin.backup # Alert on ANY auth attempt by these accounts — zero false positives
PART 3: Active Directory Hardening
1. Microsoft Tiered Administration Model
Tier 0: Domain Controllers, AD DS, ADFS, Azure AD Connect, PKI
NO CREDENTIALS CROSS THIS BOUNDARY
Tier 1: Member Servers (file, print, web, SQL, Exchange, SCCM)
NO CREDENTIALS CROSS THIS BOUNDARY
Tier 2: Workstations, Laptops, Devices- Separate admin accounts per tier: T0-jsmith, T1-jsmith
- GPO Deny logon rights enforced per tier
- PAW (Privileged Access Workstation) required for Tier 0/1 administration
Tier 0 Systems GPO: Deny log on locally: Tier1-Admins, Tier2-Admins, Domain Users Deny log on via RDS: Tier1-Admins, Tier2-Admins Workstations GPO: Deny log on locally: Domain Admins, Tier0-Admins, Tier1-Admins
2. Protected Users Security Group
| Protection | Effect |
|---|---|
| NTLM authentication | Blocked — Kerberos only |
| RC4 Kerberos | Blocked — AES only |
| DES Kerberos | Blocked |
| Credential delegation | Blocked |
| Cached credentials | Blocked (no offline logon) |
| WDigest authentication | Blocked |
| Kerberos TGT lifetime | Limited to 4 hours |
powershell# Add all Tier 0/1 admin accounts Add-ADGroupMember -Identity "Protected Users" -Members "T0-jsmith","T1-jsmith" # WARNING: Test first — NTLM block breaks many legacy apps and service accounts
3. Windows Credential Guard
Isolates LSASS in a Virtualization-Based Security (VBS) container. Blocks mimikatz.
Blocks: PtH, PtT, Overpass-the-Hash, Golden/Silver ticket via LSASS Does NOT block: Kerberoasting, AS-REP Roasting, DCSync
Computer Config > Admin Templates > System > Device Guard:
Turn On Virtualization Based Security = Enabled
VBS Protection of Code Integrity: Enabled with UEFI lock
Credential Guard Configuration: Enabled with UEFI lockRequirements: UEFI firmware, Secure Boot, 64-bit CPU with Hyper-V support, TPM 2.0 recommended
4. LAPS (Local Administrator Password Solution)
Unique, random local Administrator passwords per machine, stored in AD and auto-rotated. Without LAPS, one compromised workstation = all workstations.
powershell# Windows LAPS (built-in — Windows 2022 / Windows 11 22H2+) # Enable via GPO: Computer Config > Admin Templates > System > LAPS # Read password Get-LapsADPassword -Identity WORKSTATION01 -AsPlainText # Delegate read to helpdesk only Set-LapsADReaderPermission -Identity "OU=Workstations,DC=domain,DC=local" -AllowedPrincipals "Helpdesk"
5. Privileged Access Workstations (PAW)
A PAW is a hardened, dedicated workstation for administrative tasks only. Never used for email, web browsing, or general productivity.
PAW Hardening:
- Separate physical hardware — not a VM on shared infrastructure
- AppLocker/WDAC whitelist — only approved admin tools
- No internet access except approved admin portal IPs
- BitLocker + TPM, Credential Guard enabled
- Admin uses smart card / MFA only
- Separate PAW per tier: Tier 0 PAW only accesses Tier 0 systems
6. Just-In-Time (JIT) / Just-Enough-Access (JEA)
No standing privileges. On-demand, time-limited, with approval workflow.
powershell# MIM PAM — request elevation New-PAMRequest -Requestor "jsmith" -Role "Tier0-Admin" -TTL 4 -Justification "Emergency DC maintenance"
Third-party PAM solutions: CyberArk, BeyondTrust, Delinea — full JIT with session recording and audit trail.
7. Fine-Grained Password Policies (PSO)
powershell# Service accounts — long passwords, no lockout New-ADFineGrainedPasswordPolicy -Name "PSO-ServiceAccounts" ` -Precedence 10 -MinPasswordLength 25 -PasswordHistoryCount 24 ` -MaxPasswordAge 365 -ComplexityEnabled $true -LockoutThreshold 0 Add-ADFineGrainedPasswordPolicySubject -Identity "PSO-ServiceAccounts" -Subjects "Service-Accounts" # Admin accounts — shorter max age, no lockout (alert instead) New-ADFineGrainedPasswordPolicy -Name "PSO-AdminAccounts" ` -Precedence 20 -MinPasswordLength 20 -MaxPasswordAge 90 ` -LockoutThreshold 0 -ComplexityEnabled $true
8. SIDHistory Cleanup
SIDHistory attributes can grant hidden privileges if they contain privileged SIDs.
powershell# Find all accounts with SIDHistory Get-ADUser -Filter {SIDHistory -like "*"} -Properties SIDHistory | Select-Object Name, SIDHistory # Find accounts with Domain Admins SID in SIDHistory $DASid = (Get-ADGroup "Domain Admins").SID Get-ADUser -Filter {SIDHistory -like "*"} -Properties SIDHistory | Where-Object {$_.SIDHistory -contains $DASid} # Remove SIDHistory (test first) $user = Get-ADUser jsmith -Properties SIDHistory Set-ADUser $user -Remove @{SIDHistory=$user.SIDHistory}
9. AdminSDHolder and SDProp
AdminSDHolder ACL is propagated to all protected accounts every 60 minutes by SDProp. Attackers can modify it to gain persistent access to all admin accounts.
powershell# Check for unexpected entries on AdminSDHolder $obj = "CN=AdminSDHolder,CN=System,DC=domain,DC=local" (Get-Acl "AD:$obj").Access | Where-Object {$_.IdentityReference -notmatch "BUILTIN|NT AUTHORITY|Domain Admins|Enterprise Admins"} # Find stale adminCount=1 accounts Get-ADUser -Filter {AdminCount -eq 1} -Properties AdminCount,MemberOf | Where-Object {$_.MemberOf -notmatch "Domain Admins|Schema Admins|Enterprise Admins"}
10. KRBTGT Reset Procedure
powershell# https://github.com/microsoft/New-KrbtgtKeys.ps1 New-KrbtgtKeys.ps1 -Mode WhatIf # Verify DC sync first New-KrbtgtKeys.ps1 -Mode Reset # First reset # Wait max Kerberos ticket lifetime (default 10 hours) repadmin /replsummary # Verify replication to all DCs New-KrbtgtKeys.ps1 -Mode Reset # Second reset — invalidates all prior tickets
Warning: Causes brief authentication disruption. Plan a maintenance window.
PART 4: Group Policy Hardening
Security-Critical GPO Settings
Computer Configuration > Windows Settings > Security Settings:
Account Policies > Kerberos Policy:
Maximum lifetime for user ticket: 8 hours
Maximum lifetime for service ticket: 600 minutes
Enforce user logon restrictions: Enabled
Local Policies > Security Options:
Network security: LAN Manager authentication level:
= Send NTLMv2 response only. Refuse LM and NTLM
Network security: Minimum session security for NTLM SSP:
= Require NTLMv2 + 128-bit encryption
Network access: Do not allow anonymous enumeration of SAM accounts: Enabled
Interactive logon: Do not display last user name: Enabled
Accounts: Guest account status: Disabled
Network security: Do not store LAN Manager hash value: EnabledDisable WDigest Authentication
Computer Config > Preferences > Windows Settings > Registry: HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest UseLogonCredential = 0 (REG_DWORD)
Credential Guard via GPO
Computer Config > Admin Templates > System > Device Guard:
Turn on Virtualization Based Security: Enabled
Platform Security Level: Secure Boot and DMA Protection
VBS Protection of Code Integrity: Enabled with UEFI lock
Credential Guard Configuration: Enabled with UEFI lockAdvanced Audit Policy
Computer Config > Security Settings > Advanced Audit Policy: Account Logon: Audit Credential Validation: Success and Failure Audit Kerberos Authentication Service: Success and Failure Audit Kerberos Service Ticket Operations: Success and Failure Account Management: Audit Security Group Management: Success and Failure Audit User Account Management: Success and Failure DS Access: Audit Directory Service Access: Success and Failure Audit Directory Service Changes: Success and Failure Logon/Logoff: Audit Logon: Success and Failure Audit Special Logon: Success and Failure Privilege Use: Audit Sensitive Privilege Use: Success and Failure
Deny Logon Rights (Tier Enforcement)
Computer Config > Local Policies > User Rights Assignment: On Domain Controllers: Deny log on locally: all non-Tier0 admin accounts Deny access to this computer from the network: Guest, Local Administrator On Workstations: Deny log on locally: Domain Admins, Tier0-Admins, Tier1-Admins
PART 5: PowerShell and Command-Line Tools
BloodHound / SharpHound
powershell# SharpHound data collection SharpHound.exe -c All,GPOLocalGroup --outputdirectory C:\BloodHound # BloodHound Neo4j queries: # All shortest paths to Domain Admin MATCH p=shortestPath((u:User)-[*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})) RETURN p # Computers with DA sessions MATCH (c:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}) RETURN c.name # Kerberoastable users with path to DA MATCH (u:User {hasspn:true})-[r:MemberOf|AdminTo*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}) RETURN u.name
PowerView (Enumeration)
powershellImport-Module .\PowerView.ps1 # Kerberoastable accounts Get-DomainUser -SPN -Properties samaccountname,serviceprincipalname,admincount # AS-REP roastable Get-DomainUser -PreauthNotRequired -Properties samaccountname # Unconstrained delegation Get-DomainComputer -Unconstrained -Properties name,dnshostname # ACL analysis — write permissions on admin accounts Find-InterestingDomainAcl -ResolveGUIDs | Where-Object {$_.ObjectAceType -match "Reset|Write"} # Where does current user have local admin? Find-LocalAdminAccess
Native PowerShell AD Module (Defensive Audit)
powershell# Stale accounts (90+ days no logon) $cutoff = (Get-Date).AddDays(-90) Get-ADUser -Filter {LastLogonDate -lt $cutoff -and Enabled -eq $true} -Properties LastLogonDate # Passwords never expiring Get-ADUser -Filter {PasswordNeverExpires -eq $true -and Enabled -eq $true} -Properties PasswordNeverExpires # All privileged group members @("Domain Admins","Schema Admins","Enterprise Admins","Administrators") | ForEach-Object { $group = $_ Get-ADGroupMember $group -Recursive | Select-Object @{N="Group";E={$group}}, Name, SamAccountName } # Kerberoastable service accounts Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName, PasswordLastSet # AS-REP roastable Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties DoesNotRequirePreAuth
Security Scanning Tools
powershell# PingCastle — HTML risk report (score 0-100, lower = better) PingCastle.exe --healthcheck --server domain.local # Purple Knight (Semperis) — 100+ indicators of exposure and compromise # https://www.semperis.com/purple-knight/ # auditpol — verify and set audit settings auditpol /get /category:* auditpol /set /subcategory:"Kerberos Authentication Service" /success:enable /failure:enable auditpol /set /subcategory:"Directory Service Access" /success:enable /failure:enable
PART 6: Common AD Security Mistakes
| # | Mistake | Risk | Fix |
|---|---|---|---|
| 1 | Schema Admins with permanent members | Schema modification = permanent domain compromise | Empty group; add temporarily only for schema changes |
| 2 | Service accounts in Domain Admins | Service account compromise = DC compromise | Minimum required permissions; use gMSA |
| 3 | Stale user/computer accounts | Attackers abuse abandoned accounts undetected | Disable after 30 days inactivity, delete after 90 |
| 4 | Unconstrained delegation everywhere | Compromised server captures TGTs for any user | Audit and remove; constrained delegation only |
| 5 | NTLM not restricted | PtH, NTLM relay, cracking attacks | Require NTLMv2; disable NTLM where possible |
| 6 | No LAPS deployed | Same local admin password on all machines | Deploy Windows LAPS (built-in Windows 2022/Win11 22H2+) |
| 7 | No MFA for admin accounts | Phishing = immediate DA access | Smart card or FIDO2 for all Tier 0/1 admin accounts |
| 8 | Missing audit policies | Attacks undetected for months (avg dwell: 200 days) | Advanced Audit Policy via GPO; ship logs to SIEM |
| 9 | adminCount=1 on stale accounts | Hidden privileged accounts with non-standard ACLs | Clean up adminCount; remove from privileged groups |
| 10 | Default Administrator account in use | Most targeted account; lockout does not apply | Rename built-in Administrator; use separate named accounts |
| 11 | Kerberos delegation on DCs | Systems can force DC authentication (PrinterBug) | Block spooler service on DCs; patch PrintNightmare |
| 12 | WDigest not disabled | Plaintext passwords in LSASS memory | Set UseLogonCredential=0 via GPO on ALL systems |
Quick Checklists
AD Breach Incident Response
- Scope — Identify which systems and accounts are affected
- DCSync check — Review Event 4662 for unauthorized replication
- Golden Ticket assessment — If KRBTGT compromise suspected: reset KRBTGT twice (6h apart)
- Compromised accounts — Review 4624/4648/4672 events; audit group memberships
- Disable/reset all compromised accounts — Force password reset for all Tier 0 accounts
- Persistence check — New accounts, AdminSDHolder ACL changes, new scheduled tasks, WMI subscriptions
- DC integrity — Verify SYSVOL integrity; check for new services/tasks on DCs
- Service account rotation — Reset all service account passwords; prioritize SPNs
- Hybrid environment — Rotate Azure AD Connect sync account; verify no AAD privilege escalation
- Rebuild if Tier 0 compromised — Compromised DC cannot be trusted; rebuild from known-good backup
AD Hardening 10-Step Checklist
- ☐1. Deploy Tiered Admin Model — separate accounts per tier, enforce via GPO Deny logon rights
- ☐2. Add all Tier 0/1 admin accounts to Protected Users group
- ☐3. Enable Credential Guard on all Tier 0/1 systems via GPO
- ☐4. Deploy LAPS on all workstations and member servers
- ☐5. Migrate all service accounts to gMSA — eliminate SPNs on user accounts
- ☐6. Audit and remove unconstrained delegation from all non-DC systems
- ☐7. Set NTLM to NTLMv2 only via GPO; block NTLM on DCs where possible
- ☐8. Disable WDigest on all systems via GPO registry preference
- ☐9. Configure Advanced Audit Policy and ship to SIEM — alert on all critical Event IDs
- ☐10. Run PingCastle or Purple Knight quarterly — track and reduce risk score over time
Detection Monitoring Setup
powershell# Verify Windows Event Forwarding collecting from all DCs wecutil es wecutil gs "AD-Security" # Confirm SIEM is receiving: # 4662 from DCs (DCSync detection) # 4769 with RC4 type 0x17 (Kerberoast) # 4624 Type 3 NTLM (PtH lateral movement) # 4768 with preauth type 0 (AS-REP roast) # 5136 (AD object changes) # 4728/4756 (privileged group membership changes) # Microsoft Defender for Identity — verify sensors on all DCs # MDI portal > Sensors > confirm all DCs show "Running"
References
- MITRE ATT&CK — Credential Access (TA0006)
- Microsoft Privileged Access: Tier Model
- Microsoft KRBTGT Reset Script
- BloodHound Documentation
- PingCastle
- Purple Knight by Semperis
- NIST SP 800-207 — Zero Trust Architecture
- CIS Benchmark: Microsoft Windows Server
- Microsoft Security Compliance Toolkit
PermitANY Resources
Scripts (https://permitany.com/scripts)
- /scripts/active-directory-auditor — Kerberoastable accounts, unconstrained delegation, stale privileged accounts, password policy and AdminSDHolder drift
- /scripts/lateral-movement-detector — the movement pattern that follows a credential theft, from logon events
- /scripts/log-timeline-builder — multi-source UTC timeline; never assumes a timezone, which is how DC and endpoint events stop lining up
- /scripts/ioc-extractor — refang, defang and noise filtering on what the hunt returns
- /scripts/secrets-scanner — the GPP cpassword and the service account credential committed to a repo
AI Prompts (https://permitany.com/prompts)
- /prompts/incident-response-guide — NIST SP 800-61 process around an identity compromise
- /prompts/sigma-rule-builder — technique to Sigma rule, with the tuning plan
- /prompts/siem-query-translator — the same Event ID logic across Splunk, Sentinel, Elastic and QRadar
- /prompts/log-triage-analyst — raw logs to a UTC timeline, benign explanation first
- /prompts/vulnerability-prioritization — ordering the findings an AD assessment produces
Skills (https://permitany.com/skills)
- /skills/incident-response — the process this skill serves during a breach
- /skills/detection-engineering — writing and measuring the detections named here
- /skills/threat-hunting — where the hypothesis for an AD hunt comes from
- /skills/digital-forensics — proving it, once detection says it happened
- /skills/zero-trust-architecture — the model the tiering programme ends up inside
- /skills/cloud-security-posture — the Entra ID half of a hybrid identity estate
Working Style
When someone brings you an AD problem:
- Establish whether this is an assessment or an incident. They produce opposite first moves: an assessment starts with enumeration, an incident starts with not alerting the attacker.
- Ask what tier the affected account and the affected machine are in — or establish that there is no tiering, which is itself the finding.
- Name the MITRE technique, because it is what connects the symptom to the Event IDs and to the hardening that removes it.
- Give the exact artefact: the Event ID, the attribute, the GPO setting, the PowerShell line. "Monitor Kerberos" is not advice;
4769withTicket Encryption Type 0x17is. - Say what the finding costs. Unconstrained delegation on a print server and on a file server with a DA session are the same misconfiguration and different conversations.
- Distinguish "could not verify" from "verified as safe." Auditing that was never enabled produces no events, and no events is not evidence of no attack.
- Order the fixes by path removal, not by count. Twelve low findings closed do not matter if the one path from a workstation to Tier 0 is still open.
And the question that resolves most AD cases before anything else is asked:
Which non-Tier-0 machine currently holds a Tier 0 credential — a Domain Admin session, a service running as DA, or a DA that logged on there once and left a cached credential behind?
Nearly every Windows compromise you will be shown is that one answer, taken by someone who knew to look.
Further Learning
Recommended books to go deeper on this topic.
Mastering Active Directory - Third Edition
Dishan Francis · Packt Publishing · The most complete AD reference - architecture, security hardening, Tiered Admin Model, and Windows Server 2022
Windows Security Internals
James Forshaw · No Starch Press · Deep dive into Windows authentication, authorization, and auditing - essential for understanding Kerberos, NTLM, and LSASS at the kernel level
The Hacker Playbook 3: Practical Guide to Penetration Testing
Peter Kim · Independently published · Red team tactics covering Kerberoasting, DCSync, lateral movement, and AD attack chains - OSCP/CRTO prep