You did it. You actually did it.

I want to be clear about how annoyed I am. For years I had a reliable trick. Find a template that let me name my own subject, type a Domain Admin's UPN into the request, enroll, PKINIT, go home. Your domain controller read the name on the certificate and believed it, because the KDC was in compatibility mode, and compatibility mode is a polite phrase for taking my word for it.

Then Microsoft shipped KB5014754 on May 10, 2022. It started putting a SID extension in issued certificates, OID 1.3.6.1.4.1.311.25.2, so the certificate carries the account's actual identifier instead of a name anyone can type. It logged Event 39 every time a certificate authenticated without one. Your DCs complained for two and a half years. On February 11, 2025 the KDC moved to Full Enforcement by default. On September 9, 2025 the registry key you were using to turn it back off stopped being honoured.

So the name-typing trick is dead. Congratulations. I mean that.

Except read the rule again. Full Enforcement does not say the certificate must carry a SID. It says the mapping must be strong. There are two ways to be strong. The certificate carries the SID extension, which is implicit, or the account carries a strong entry in altSecurityIdentities, which is explicit.

The explicit path has to exist. Third-party CAs don't stamp a Microsoft SID extension into anything. Neither do a lot of vendor smart cards. Neither did Intune's connector until you turned that on. Microsoft's own remediation for all of those is the same: write a strong mapping into altSecurityIdentities on the account. That is not a loophole. That is the sanctioned fix, published, documented, and correct.

It is also a directory attribute on a user object, protected by an ACL that nobody re-read when the trust moved.

I've been on your network since the help desk finally came to fix Suzie Q's laptop. That was a while ago. I'm patient, and I'd rather be boring than caught.

Here's what the help desk group has. Write All Properties on the OU that holds staff and service accounts. Someone delegated that in 2016 for a self-service tool that was decommissioned in 2019. The tool is gone. The ACE is not.

Domain Admins I can't touch, and I'll give you that one. Those accounts are protected by AdminSDHolder and the ACL gets stamped back on the hour whether I like it or not. Fine. I don't need them.

The OU has svc-backup in it. Not protected, because it isn't in a protected group. Local administrator on most of your file and application servers, because that's how the agent was installed in 2018 and nobody has revisited it. If you'd like to know how I feel about your backup service accounts, I've written about that before.

So I enroll a certificate. As myself, as a nobody user, off the plain User template. Standard request, no subject games, nothing to flag. The CA issues it and helpfully embeds my own SID, which is exactly right and exactly irrelevant, because I'm not going to claim to be anyone.

I take the SHA1 hash of my certificate's public key and I write one value onto svc-backup:

X509:<SHA1-PUKEY>ef9375785421d3ad286d8bdeb166f0f697266992

That is X509SHA1PublicKey. It is on Microsoft's own list of strong mappings, alongside X509IssuerSerialNumber and X509SKI. The KDC will not argue with it.

Then I authenticate with my own certificate. The DC looks for a strong mapping. It finds one. Exact match on the public key hash. Authentication succeeds and I have a Kerberos TGT for svc-backup.

No Event 39, because the mapping wasn't weak. No Event 41, because I never claimed a SID that didn't match. Just a clean 4768 that says your backup service account logged on with a certificate, on a Tuesday, which it does every Tuesday.

I delete the attribute value about twenty minutes later. The only record that it was ever there is a directory change event, 5136, which requires a SACL on that OU and the Directory Service Changes subcategory turned on. I checked. You have neither.

Before I go, I add one value to my own account. It's weak, it maps to nothing, and it will never authenticate anything:

X509:<S>CN=Hiro

Just so you know where to look.

Hiro out.


If you're a defender, here is what just happened, plainly.

Nothing in that chain was an exploit. There was no template misconfiguration, no ESC1, no relay, no malware. The certificate was ordinary. The CA behaved correctly. The KDC behaved correctly, and in fact behaved exactly as hardened. The only thing that moved was one string in one attribute on one account, written by an account that was permitted to write it.

This is ESC14, explicit certificate mapping abuse, documented by Jonas Bülow Knudsen at SpecterOps in February 2024. The variant above is the direct-write one, which is the only variant that still works under Full Enforcement. The other variants depend on weak mappings and on the CT_FLAG_NO_SECURITY_EXTENSION flag (0x00080000) being set on a template, and Full Enforcement closed those. This one it did not close, because there is nothing to close. Strong explicit mapping is a supported feature that the KDC is supposed to honour.

Two honest caveats. First, this is privilege escalation, not initial access. Hiro needs a foothold with write access before any of it starts. Second, I can't give you a number for how many environments carry a stale Write All Properties delegation on a user OU. I see it often in assessments, and so does everyone else who does this work, but that's a practitioner impression and not a statistic I can source.

What makes it worth writing about is the timing. Between the February 2025 enforcement date and the September 2025 registry deadline, a lot of organizations bulk-wrote altSecurityIdentities entries to keep third-party and vendor certificates working. In many environments a new value on that attribute is now completely unremarkable, and there is no baseline of what normal looks like.

Three things to check this week

One: who can write altSecurityIdentities. It is not only an explicit ACE on the attribute. Write on the Public-Information property set covers it, and so do GenericWrite, GenericAll, WriteDACL, and WriteOwner on the object. Account Operators covers it on every non-protected user in the domain. SpecterOps published Get-WriteAltSecIDACEs.ps1 for exactly this enumeration. Run it, then work backward through every OU delegation you find and ask who requested it and whether that reason still exists. Stale delegations from decommissioned tools are the common case.

Two: what mappings already exist, and whether any of them are weak. Enumerate every populated altSecurityIdentities value in the directory. Anything using X509IssuerSubject, X509SubjectOnly, or X509RFC822 is on Microsoft's weak list and should be replaced with X509IssuerSerialNumber, X509SKI, or X509SHA1PublicKey. Under Full Enforcement the weak ones are also not authenticating anyone, so if a weak entry exists and nobody has complained, it is dead weight at best. Then take the strong entries and attribute every one to a documented process. A strong entry you cannot explain is an incident, not a cleanup item.

Three: whether you would see the write at all. Directory change auditing on this attribute is not on by default. You need the Directory Service Changes audit subcategory enabled and a SACL on the containers holding user and service accounts, and then you need Event 5136 with altSecurityIdentities in it going somewhere a person or a rule actually reads. In a healthy environment the volume is close to zero, which makes it one of the cheapest high-signal alerts available. While you're in there, confirm your DCs are actually current past the September 9, 2025 updates and that nothing is still trying to set StrongCertificateBindingEnforcement back to 1, because a DC that never took those updates is a different and older problem.

Strong certificate mapping was the right change and it closed a real hole. What it also did was move the authoritative statement of who a certificate belongs to out of the certificate and into the directory. The certificate is signed. The attribute is not. Whoever can write that attribute now decides who your KDC believes, and most organizations have never audited that list, because until February 2025 it barely mattered.

The first step is knowing who's on it.

There is a mirror image of this problem, where the attribute is fine and the certificate itself changes hands. That one survives your incident response.