ADCS-010: ESC7 - Vulnerable CA ACLs

Platform
Active Directory
Category
AD Certificate Services
Severity
Critical
Zero Trust pillar
Identity (weight 3)
Golden fixtures
3
Branch coverage
Observed: fixtures prove the verdicts they exercise
Provenance
baseline

What it checks

Guerrilla enumerates every enterprise Certification Authority published under CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=<forest-root>. For each pKIEnrollmentService object it connects to the CA via ICertAdmin2::GetCAProperty / certutil -getacl semantics and reads the CA security descriptor stored at HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<CA Name>\Security. The descriptor is parsed into individual ACEs. Each ACE is evaluated for two rights defined in certsrv.h: CA_ACCESS_ADMIN (0x1, "Manage CA") and CA_ACCESS_OFFICER (0x2, "Issue and Manage Certificates", also called Certificate Manager). Trustee SIDs are resolved and tested for membership outside the expected privileged set (Enterprise Admins, Domain Admins on the CA host domain, BUILTIN\Administrators on the CA, the CA service account, and any explicitly approved certificate manager group). Any non-conforming ACE produces a finding. The check also records the CA DNS name, CA configuration string (HOSTNAME\CA Name), template publications, and whether EDITF_ATTRIBUTESUBJECTALTNAME2 is currently set on the CA EditFlags so that ESC6 chaining risk can be reported alongside.

Why it matters

ManageCA is the single most powerful right inside Active Directory Certificate Services. A principal holding ManageCA can: enable EDITF_ATTRIBUTESUBJECTALTNAME2 (creating an ESC6 universal SAN-injection condition across every template the CA issues), grant itself ManageCertificates so it can approve its own pending requests, publish or republish certificate templates, change officer rights to bypass enrollment agent restrictions, and modify CA policy modules. ManageCertificates alone is enough to neutralize the Manager Approval (msPKI-Enrollment-Flag CT_FLAG_PEND_ALL_REQUESTS) control that defenders rely on to keep dangerous templates from being silently issued. The combination of the two rights yields an unauthenticated path to a Domain Admin or Domain Controller certificate that is fully signed by an Enterprise CA trusted by every machine in the forest. Unlike many ADCS misconfigurations, ESC7 is a delegation problem rather than a template problem, so it survives template hardening: an attacker with ManageCA can re-create the vulnerable condition on demand.

Attack path

Step 1: Discovery. The attacker runs Certipy find -u user@domain -p pass -dc-ip <DC> -vulnerable, or BloodHound with the Certipy collector, and identifies an Enterprise CA where a controlled principal (a help desk group, a PKI operations team, a stale delegation) holds ManageCA or ManageCertificates. Step 2a (ManageCA path): The attacker uses Certipy ca -ca <CA> -add-officer <controlled-user> -u user@domain -p pass to grant itself ManageCertificates, then Certipy ca -ca <CA> -enable-template SubCA (or any disabled template) to republish a template that allows client authentication and arbitrary SAN. Alternatively the attacker runs Certipy ca -ca <CA> -enable-edit-flag EDITF_ATTRIBUTESUBJECTALTNAME2 to convert the entire CA into an ESC6 condition where any User template can be requested with a san:upn=Administrator@domain attribute. Step 2b (ManageCertificates path): The attacker submits a request against a template that normally requires CA Manager approval (commonly an Enrollment Agent or a high-value client-auth template). The request goes pending. The attacker then runs Certipy ca -ca <CA> -issue-request <RequestId> to approve and issue the certificate without any other approver involvement. Step 3: PKINIT or Schannel authentication. The attacker uses Certipy auth -pfx admin.pfx -domain <domain> to obtain a TGT for the high-value account via PKINIT, or extracts the NTLM hash via the U2U + UnPAC-the-Hash flow. From here the attacker has domain-level credentials usable for DCSync, lateral movement, or persistence. Step 4: Cleanup. The attacker uses Certipy ca to roll back the EditFlags or remove the added officer rights, leaving behind only an issued certificate that can be reused until the CA CRL is updated or the certificate is explicitly revoked.

How Guerrilla assesses it

Guerrilla locates each enterprise CA via the pKIEnrollmentService objects in the configuration partition. For each CA it issues a DCOM call to ICertAdmin2::GetCASecurity (the same RPC interface used by certutil -getacl -config "<config string>") and parses the returned SECURITY_DESCRIPTOR. ACE rights are decoded against the certsrv.h flag set: CA_ACCESS_ADMIN, CA_ACCESS_OFFICER, CA_ACCESS_READ, CA_ACCESS_ENROLL. Trustee SIDs are resolved through the global catalog. Any ACE granting ADMIN or OFFICER to a SID outside the approved tier-zero allowlist (configurable via the Guerrilla policy file, default: BUILTIN\Administrators, Domain Admins, Enterprise Admins, NT AUTHORITY\SYSTEM, the CA gMSA or service account) produces a finding. The check also queries the CA EditFlags via the same RPC channel to record whether EDITF_ATTRIBUTESUBJECTALTNAME2 is already set, and inspects published templates so that the report ties ESC7 exposure to concrete downstream ESC1, ESC2, and ESC6 conditions on the same CA. Fallback path: if RPC to the CA is blocked, the check enumerates the cACertificate and certificateTemplates attributes on the pKIEnrollmentService object and reports that CA ACL detail is unavailable, which itself is a finding.

Recommended value

ManageCA and ManageCertificates permissions restricted to designated CA administrators only

Remediation

Review CA security permissions using certsrv.msc > Properties > Security tab or certutil -getacl. Remove ManageCA permissions from non-administrative principals. Remove ManageCertificates from any principal that is not an authorized certificate manager. Document all principals with CA management permissions. Implement separation of duties between CA administrators and certificate managers.

Fixture-proven verdicts

Every verdict below is proven by a golden fixture in the module's gating test suite. This table derives from the last green run; it cannot be edited by hand.

Verdict scenarios for ADCS-010
ScenarioExpected verdict
cleanPASS
known-badFAIL
throttledNot Assessed

Framework mappings

NIST SP 800-53
AC-6, AC-6(1), AC-5
ANSSI
vuln_adcs_esc7
MITRE ATT&CK
T1649