# ADCS Misconfiguration Discovery

> Techniques for identifying misconfigured Active Directory Certificate Services, including vulnerable certificate templates, enrollment permissions, and ESC attack paths.

- **URL:** https://hackindex.io/platforms/active-directory/vulnerability-discovery/adcs-misconfiguration-discovery
- **Path:** Active Directory > Vulnerability Discovery
- **Up:** [Vulnerability Discovery](https://hackindex.io/platforms/active-directory/vulnerability-discovery.md)
- **Published:** 2026-04-30
- **Updated:** 2026-08-11

Active Directory Certificate Services misconfigurations are among the most impactful privilege escalation paths in modern AD environments. Vulnerable certificate templates allow low-privileged users to request certificates on behalf of other accounts, including Domain Admins. Several escalation paths exist depending on template and CA configuration: these are catalogued as ESC1 through ESC8.

This page covers detection only. For how to abuse confirmed findings see [ADCS Exploitation](https://hackindex.io/platforms/active-directory/exploitation/adcs-exploitation).

## Confirm ADCS is deployed

Before running any template enumeration, confirm a Certificate Authority is present in the environment. If no CA exists, ADCS-based techniques including Shadow Credentials will not work.

**Check for ADCS deployment**

```bash
# nxc: check for ADCS via LDAP
nxc ldap $TARGET_IP -u $USER -p $PASSWORD -M adcs

# BloodyAD: query CA objects directly
bloodyAD -d $DOMAIN -u $USER -p $PASSWORD --host $TARGET_IP get search --filter '(objectClass=pKIEnrollmentService)' --attr cn dNSHostName
# LDAP  10.10.10.10  389  DC01  [+] Found PKI Enrollment Services
# LDAP  10.10.10.10  389  DC01  CA Name: corp-DC01-CA
# LDAP  10.10.10.10  389  DC01  DNS Hostname: dc01.corp.local
```

## Certipy: full ADCS enumeration

Certipy is the primary tool for ADCS enumeration. The `find` command queries all certificate templates and CA settings, then flags vulnerable configurations with an ESC identifier. The `-vulnerable` flag filters output to only show confirmed misconfigurations.

**Certipy: enumerate and find vulnerabilities**

```bash
# Full enumeration: saves output to JSON and text
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP

# Filter to vulnerable templates and CA settings only
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -vulnerable

# Pass-the-Hash
certipy find -u $USER@$DOMAIN -hashes :$NTHASH -dc-ip $TARGET_IP -vulnerable

# Kerberos authentication
certipy find -u $USER@$DOMAIN -k -dc-ip $TARGET_IP -vulnerable

# Output to stdout only
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -vulnerable -stdout
# Certificate Templates
#   Template Name: UserAuthentication
#   Enabled: True
#   Client Authentication: True
#   Enrollee Supplies Subject: True
#   Certificate Authorities: corp-DC01-CA
#   Permissions
#     Enrollment Permissions
#       Enrollment Rights: CORP.LOCAL\Domain Users
#   [!] Vulnerabilities
#     ESC1: 'CORP.LOCAL\Domain Users' can enroll, enrollee supplies subject and template allows client authentication
```

## ESC1: enrollee supplies subject

ESC1 is the most common and most directly exploitable ADCS misconfiguration. It requires three conditions to be true simultaneously on the same template. Each condition must be confirmed before attempting exploitation.

- The template allows Client Authentication (EKU includes Smart Card Logon, Client Authentication, or PKINIT)
- The template allows the enrollee to supply the Subject Alternative Name (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT is set)
- Low-privileged users or Domain Users have Enrollment rights on the template

When all three are true, any domain user can request a certificate for an arbitrary UPN (including a Domain Admin) and use it to obtain a TGT as that account.

## ESC4: write access on template

ESC4 exists when a low-privileged account has write access on a certificate template object. This does not directly enable certificate abuse, but it allows modifying the template to introduce ESC1 conditions. Certipy flags this when `WriteDacl`, `WriteOwner`, or `WriteProperty` exists on a template for Domain Users or similar principals.

## ESC8: NTLM relay to AD CS HTTP endpoint

ESC8 is present when the CA's web enrollment interface is running over HTTP without Extended Protection for Authentication enabled. This allows an NTLM relay attack against the enrollment endpoint to request a certificate on behalf of any coerced account. The CA web enrollment endpoint is typically at `http://<CA_HOST>/certsrv`.

**Check CA web enrollment endpoint**

```bash
# Check if CA web enrollment is running over HTTP
curl -I http://$CA_HOST/certsrv/

# nxc: check for web enrollment
nxc ldap $TARGET_IP -u $USER -p $PASSWORD -M adcs

# Certipy flags ESC8 automatically in find output
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -vulnerable -stdout | grep -A5 ESC8
# Certificate Authorities
#   CA Name: corp-DC01-CA
#   DNS Name: dc01.corp.local
#   Web Enrollment: Enabled
#   [!] Vulnerabilities
#     ESC8: Web Enrollment is enabled and Request Disposition is set to Issue
```

**ESC2**: Any Purpose EKU or no EKU defined on a template with low-privilege enrollment rights. Functions like ESC1 but the certificate can be used for any purpose.  
**ESC3**: Template has Certificate Request Agent EKU and a second template allows enrollment on behalf of another user. Allows enrolling as any user through a two-step process.  
**ESC5**: Write access on the CA object in AD (`pKIEnrollmentService` or `certificationAuthority`). Allows enabling disabled templates, adding enrollment officers, or modifying CA flags.  
**ESC6**: CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag set, allowing any template to accept a custom SAN regardless of template settings: functions like ESC1 domain-wide.  
**ESC7**: Low-privileged account has ManageCA or ManageCertificates rights on the CA, allowing modification of CA settings or approval of pending requests.

**Check CA-level flags (ESC6 / ESC7)**

```bash
# Certipy catches these automatically: check find output
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -vulnerable -stdout | grep -E 'ESC6|ESC7|EDITF_ATTRIBUTESUBJECTALTNAME2|ManageCA'

# Manual CA flag check via BloodyAD
bloodyAD -d $DOMAIN -u $USER -p $PASSWORD --host $TARGET_IP get search --filter '(objectClass=certificationAuthority)' --attr name flags
# [!] Vulnerabilities
#     ESC6: CA has EDITF_ATTRIBUTESUBJECTALTNAME2 flag set
```

Any confirmed ESC finding is directly exploitable. ESC1 is a single-command escalation to Domain Admin. ESC8 requires coercion and relay but works in environments where no template misconfiguration exists. For exploitation steps see [ADCS Exploitation](https://hackindex.io/platforms/active-directory/exploitation/adcs-exploitation), [ADCS ESC2/3/5/7](https://hackindex.io/platforms/active-directory/exploitation/adcs-esc2-esc3-esc5-esc7), and [ADCS ESC9/10](https://hackindex.io/platforms/active-directory/exploitation/adcs-esc9-esc10).

## ESC9: CT_FLAG_NO_SECURITY_EXTENSION

ESC9 is present when a template has `CT_FLAG_NO_SECURITY_EXTENSION` set in its enrollment flags, meaning certificates issued from it do not embed the `szOID_NTDS_CA_SECURITY_EXT` extension that binds the cert to the issuing AD account. Without this extension, Kerberos PKINIT maps the certificate purely by its UPN. If `StrongCertificateBindingEnforcement` on the DC is not set to `2` (full enforcement), a certificate with any UPN will authenticate as that account.

Exploitation requires GenericWrite on a domain account to modify its UPN before requesting the certificate.

#### Kali (Certipy)

**Detect ESC9**

```bash
# Certipy auto-detects ESC9 in find output
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -vulnerable -stdout | grep -A8 ESC9

# Check StrongCertificateBindingEnforcement on DC
# 0 = disabled, 1 = audit mode, 2 = full enforcement (not vulnerable)
nxc smb $TARGET_IP -u $USER -p $PASSWORD -x 'reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement'
# [!] Vulnerabilities
#     ESC9: Template 'VulnerableUserAuth' has 'CT_FLAG_NO_SECURITY_EXTENSION' flag and
#           'StrongCertificateBindingEnforcement' is not set to 2
#
# HKLM\SYSTEM\CurrentControlSet\Services\Kdc
#     StrongCertificateBindingEnforcement    REG_DWORD    0x1
```

#### Windows

**Detect ESC9 from Windows**

```powershell
# Check binding enforcement on DC (run on DC or via PSRemoting)
reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement
# 0 = disabled (vulnerable), 1 = audit (vulnerable), 2 = enforced (safe)

# Check template flag via certutil
certutil -template | Select-String -Pattern 'CT_FLAG_NO_SECURITY_EXTENSION|msPKI-Enrollment-Flag'
```

## ESC10: weak certificate mapping

ESC10 covers two conditions where the DC uses legacy certificate-to-account mapping that an attacker can exploit:

- **ESC10a**: `StrongCertificateBindingEnforcement = 0` on the DC. No binding enforcement at all: any certificate with a UPN matching a domain account authenticates as that account. Works with any client authentication template, no special template flag required.
- **ESC10b**: `CertificateMappingMethods` includes legacy SubjectName mapping bits (`0x4` or `0x2`). The DC maps certificates using the certificate Subject CN or Issuer+Subject in addition to UPN. Requires GenericWrite on an account.

#### Kali (Certipy)

**Detect ESC10**

```bash
# Certipy auto-detects ESC10 in find output
certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -vulnerable -stdout | grep -A8 ESC10

# Manual: check both registry values on DC
nxc smb $TARGET_IP -u $USER -p $PASSWORD -x 'reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement'
nxc smb $TARGET_IP -u $USER -p $PASSWORD -x 'reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v CertificateMappingMethods'
# [!] Vulnerabilities
#     ESC10a: 'StrongCertificateBindingEnforcement' is set to 0
#
# StrongCertificateBindingEnforcement    REG_DWORD    0x0
# CertificateMappingMethods              REG_DWORD    0x1f
```

#### Windows

**Detect ESC10 from Windows**

```powershell
# Check both relevant KDC registry values on DC
reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement
reg query HKLM\SYSTEM\CurrentControlSet\Services\Kdc /v CertificateMappingMethods
# CertificateMappingMethods with bit 0x4 (value includes 4) = SubjectName mapping = ESC10b
```

## References

- [Certipy: GitHub](https://github.com/ly4k/Certipy) - find command reference and ESC vulnerability detection
- [NetExec (nxc): GitHub](https://github.com/Pennyw0rth/NetExec) - adcs module for CA and template enumeration
- [Certified Pre-Owned: SpecterOps](https://posts.specterops.io/certified-pre-owned-d95910965cd2) - Original ESC1-ESC8 research and taxonomy
- [Certipy 4.0: ESC9, ESC10 (ly4k)](https://research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-new-adcs-and-domain-escalation-techniques-34d1c26f0dc6) - ESC9 and ESC10 research, Certipy 4.0 release post
