ADCS-001: CA Server Inventory
- Platform
- Active Directory
- Category
- AD Certificate Services
- Severity
- Info
- Zero Trust pillar
- Identity (weight 1)
- Golden fixtures
- 2
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
The check queries CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=tld via LDAP and enumerates every pKIEnrollmentService object. For each CA it records: - name (CN of the pKIEnrollmentService object) - dNSHostName (the host running certsvc) - distinguishedName - flags (pKIEnrollmentService flags, includes EDITF_ATTRIBUTESUBJECTALTNAME2 when ESC6 is present) - certificateTemplates (multi-valued attribute listing every template published by this CA) - cACertificate (the CA certificate itself, parsed to extract subject, issuer, validity, and key usage) The Enrollment Services container is the authoritative source for Enterprise CAs because the CA writes itself there during install via certutil -installdefaulttemplates and ICertAdmin2::SetCAProperty. Standalone CAs do not register here; ADCS-001 will not see them and that gap is called out in the finding. The check also cross-references CN=NTAuthCertificates and CN=AIA to spot CAs trusted for authentication or chain building that are not in Enrollment Services (a tampering indicator).
Why it matters
Every published ADCS attack surface (ESC1 SAN spoofing, ESC2 Any Purpose EKU, ESC3 enrollment agent, ESC4 template ACL, ESC5 PKI object ACL, ESC6 EDITF_ATTRIBUTESUBJECTALTNAME2, ESC7 CA role abuse, ESC8 HTTP enrollment relay, ESC9 no security extension, ESC10 weak certificate mapping, ESC11 RPC encryption, ESC13 OID group link, ESC14 explicit mapping, ESC15 schema v1, ESC16 security extension disabled) requires the attacker to know which CA to target. Defenders need the same inventory in reverse: an undocumented CA is a candidate for a rogue CA implant (NTAuthCertificates write turns any attacker key into a forest-trusted issuer), and a CA running an unsupported OS (Windows Server 2012 R2 and earlier reached end-of-support) cannot receive patches for ADCS RCE and elevation-of-privilege fixes. A complete inventory is also a prerequisite for tier-0 scoping: every Enterprise CA is by definition Tier-0 because compromise of certsvc yields the ability to mint authentication certificates for any principal in the forest.
Attack path
1. Enumeration: an attacker with any authenticated user context queries the Enrollment Services container with certipy find -u user@domain -p pass -dc-ip 10.0.0.1, Certify.exe find, or LDAP (Get-ADObject -SearchBase "CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration,DC=domain,DC=tld" -Filter *). The container is readable by Authenticated Users by default. 2. Triage: the attacker pivots from the CA list to per-CA enumeration: certipy find dumps each CAs flags, web enrollment endpoints, and the published template ACLs in one pass. 3. Target selection: the attacker picks the CA that publishes the most permissive template (ESC1 to ESC16) or the CA with EDITF_ATTRIBUTESUBJECTALTNAME2 set (ESC6, single-flag domain takeover). 4. Exploitation: certipy req issues a certificate against the chosen CA and template. Depending on the misconfiguration the resulting certificate authenticates as Domain Admin, a Domain Controller, or any chosen principal. 5. Persistence: with a Domain Admin authentication certificate, the attacker can re-authenticate via PKINIT indefinitely. The certificate survives password resets because it is bound to the public key, not the password. The inventory step is fast and noisy on the network but quiet on the host. Defenders who do not monitor LDAP reads of the Configuration NC will not see step 1.
How Guerrilla assesses it
Guerrilla calls Get-ADObject -SearchBase (Get-ADRootDSE).configurationNamingContext -LDAPFilter "(objectClass=pKIEnrollmentService)" -Properties name, dNSHostName, distinguishedName, flags, certificateTemplates, cACertificate. The result is parsed in memory: certificateTemplates is a multi-valued string array of template CN values; flags is decoded against the pKIEnrollmentService flag enum (the EDITF_ATTRIBUTESUBJECTALTNAME2 bit 0x00040000 surfaces here for cross-reference by ADCS-007 / ESC6). For each CA the check resolves the dNSHostName to an FQDN, optionally queries the host for OS version via Get-ADComputer when the AD object is reachable, and counts published templates. The finding always reports PASS at this stage; downstream ADCS-002 through ADCS-019 walk the same inventory to flag specific ESC conditions.
Recommended value
Complete CA inventory documented with CA type, role, OS version, and published templates for each CA server
Remediation
Enumerate all CA servers by querying the PKI Enrollment Services container in AD (CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=Configuration). Document each CA's type (Enterprise/Standalone), role (Root/Subordinate), hostname, operating system version, and published certificate templates. Verify that all CA servers are running supported OS versions and have current patches.
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.
| Scenario | Expected verdict |
|---|---|
| clean | PASS |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- CM-8, CM-8(1), IA-5(2)
- MITRE ATT&CK
- T1649