Open
Conversation
certipy has no code for ESC5 (vulnerable PKI object access control): dangerous ACEs on the AD objects that make up AD CS itself -- the Public Key Services container tree (Enrollment Services, Certificate Templates, Certification Authorities, OID), each CA's own AD object and its underlying computer object, and NTAuthCertificates -- as opposed to a single certificate template (ESC4) or a CA's ManageCA/ManageCertificates security descriptor (ESC7). 'find' never queries any of these objects. Adds a new `esc5` subcommand with three actions: - audit (default-safe, read-only): resolves the authenticated identity's SID plus full group closure, walks every audited object's DACL, and reports which objects that identity already holds a qualifying right on (GenericAll/GenericWrite/WriteDacl/WriteOwner/ownership, plus WriteProperty scoped to cACertificate and Create-Child on containers), alongside every other grantee for defensive visibility. - exploit: if the identity holds a qualifying right on NTAuthCertificates, adds a self-signed rogue CA certificate to it -- a forest-wide trust change. Only ever ADDs, never touches existing trusted CAs, prompts for confirmation unless -force is given, and always writes a restore record before reporting success. The resulting CA .pfx hands off directly to `certipy-ad forge -ca-pfx` for weaponization rather than reimplementing certificate forging. - restore: undoes a prior exploit run by removing exactly the recorded certificate and nothing else, verified via before/after counts. Every other sub-case (container control, a CA's own object, a CA's computer object) is reported with manual next-step guidance pointing at existing certipy commands (template, ca, shadow) rather than auto-exploited, since those chain into separate, already-tooled attacks. Built on certipy's existing primitives rather than as a standalone script: Target/LDAPConnection for auth (Kerberos, hashes, certs, etc. all come for free), get_user_sids for the identity's group closure, lookup_sid/is_admin_sid for grantee resolution and -hide-admins filtering, and certipy.lib.certificate/files for the rogue CA and output handling.
esc5 command: audit and exploit ESC5 (vulnerable PKI object access control)esc5 command: audit and exploit ESC5 (vulnerable PKI object access control)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds support for ESC5
Why
findhas no code path for ESC5 ("Vulnerable PKI Object Access Control") — it enumeratescertificate templates, CAs, and issuance policies, and none of those queries touch the AD
objects ESC5 is actually about: the Public Key Services container tree (Enrollment
Services, Certificate Templates, Certification Authorities, OID), each CA's own AD object
and its underlying computer object, and NTAuthCertificates. This is a real gap — see
SpecterOps' "From DA to EA with ESC5" —
and today identifying it means falling back to BloodHound/ADSIEdit/PowerShell entirely
outside Certipy.
What
A new
esc5subcommand with three actions:audit(default-safe, read-only): resolves the authenticated identity's SID plusits full nested group closure, walks every audited object's DACL, and reports which
objects that identity already holds a qualifying right on —
GenericAll/GenericWrite/WriteDacl/WriteOwner/ownership, plusWritePropertyscoped specifically tocACertificate(resolved live from the schema) andCreate-Childon containers. Everyother grantee is still reported for defensive visibility (
-hide-adminsto suppresswell-known admins, matching
find's own flag).exploit: if the identity holds a qualifying right onNTAuthCertificates, adds aself-signed rogue CA certificate to it — a forest-wide trust change. Only ever
ADDs,never touches existing trusted CAs; prompts for confirmation unless
-force; alwayswrites a restore record (base64 DER + a standalone PFX) before reporting success. The
resulting CA
.pfxhands off directly toforge -ca-pfxfor weaponization rather thanreimplementing certificate forging here.
restore: undoes a priorexploitby removing exactly the recorded certificate andnothing else, verified via before/after counts on
NTAuthCertificates.Every other sub-case (container control, a CA's own object, a CA's computer object) is
reported with manual next-step guidance pointing at existing commands (
template,ca,shadow) rather than auto-exploited, since each of those chains into a separate,already-tooled attack.
Built on Certipy's existing primitives rather than as a bolt-on:
Target/LDAPConnectionfor auth (Kerberos, hashes, certs, LDAP signing/channel-binding options all come for free),
get_user_sidsfor the identity's group closure,lookup_sid/is_admin_sidfor granteeresolution, and
certipy.lib.certificate/filesfor the rogue CA and output handling.Testing
black/isort/flake8/pyrightall clean. Notests/directory exists in the repo toextend, so validation was done with throwaway scripts (not included in this diff):
ACE classification against hand-built
impacketsecurity-descriptor structures (genericrights, scoped
WriteProperty(cACertificate), scopedCreate-Child, inherited flags,denied ACEs), and a fully mocked-
LDAPConnectionrun ofaudit/exploit/restore,including the "no precondition, no
-force" refusal path and idempotent restore. Manuallyexercised
certipy esc5 -h/esc5 audit -hetc. for CLI correctness.Docs
Wiki updates for ESC5 (
06 - Privilege Escalation) and the command reference(
08 - Command Reference) are ready — sending as a patch against the wiki repo perCONTRIBUTING.md, separately from this PR since wikis don't support PRs.