Strong certificate mapping (KB5014754) in practice
Get certificate authentication ready for KB5014754 Full Enforcement: SID extension, altSecurityIdentities, KDC events 39/40/41 and the fixes that work.
Before May 2022, a domain controller mapped a certificate to an account mostly by name: the UPN in the Subject Alternative Name for user certificates, the DNS name for computer certificates. That made the certificate's contents the only thing between a requester and any identity whose name they could get onto a certificate. CVE-2022-26923 ("Certifried") showed how little it took: a user who could create a computer account could set its dNSHostName to a domain controller's name and obtain a certificate that mapped to the DC. KB5014754 is Microsoft's fix. It makes the KDC and Schannel demand a strong binding between certificate and account, and it has been fully enforced since 2025.
This guide covers what "strong" means in practice, how to find the certificates and mappings that fail it, how to fix each category, and what enforcement breaks. It assumes your templates are already clean, as covered in auditing certificate templates and the AD CS hardening pillar.
How strong mapping works
The KDC accepts a certificate for PKINIT under Full Enforcement only if one of the following binds it to the account:
- The SID security extension (
szOID_NTDS_CA_SECURITY_EXT, OID1.3.6.1.4.1.311.25.2). Enterprise CAs with the May 2022 or later update write the requester's SID into this extension for online templates, where the subject is built from Active Directory. - A strong explicit mapping in the account's
altSecurityIdentitiesattribute:X509IssuerSerialNumber,X509SKIorX509SHA1PublicKey. - A SID in the SAN as a URL of the form
tag:microsoft.com,2022-09-14:sid:<SID>, which later updates to KB5014754 added for certificates that cannot carry the extension. Confirm your DCs' update level supports it before relying on it.
The KDC behaviour was controlled by StrongCertificateBindingEnforcement under HKLM\SYSTEM\CurrentControlSet\Services\Kdc:
| Value | Mode | Behaviour |
|---|---|---|
| 0 | Disabled | No strong mapping check. Support removed by the April 2023 update |
| 1 | Compatibility | Strong mapping used when present; weak mapping allowed with event 39, unless the certificate predates the account (event 40, denied) |
| 2 | Full Enforcement | Weakly mapped certificates are denied |
Timeline, per KB5014754: May 10, 2022 introduced the SID extension and Compatibility mode with auditing events; February 2025 made Full Enforcement the default while still honouring an explicit value of 1; September 2025 removed Compatibility mode, so current DCs enforce regardless of the registry. If you still see the value in your baseline, it is documentation of history, not a control. The CertificateBackdatingCompensation value, which tuned the "certificate older than account" check in Compatibility mode, is likewise irrelevant once enforcement is permanent.
Schannel (TLS client certificate authentication to IIS, LDAPS and others) has its own switch, CertificateMappingMethods under HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel. The update changed its default to 0x18 (S4U2Self-based mapping), which routes Schannel through the same KDC checks. Setting it back to 0x1F re-enables weak UPN and subject mapping and should be treated as a finding.
Measure: KDC events 39, 40 and 41
Every DC logs certificate mapping problems in the System log from the Kerberos Key Distribution Center provider:
- 39: a certificate was valid but could not be strongly mapped. Warning in Compatibility mode, denial under Full Enforcement.
- 40: the certificate was issued before the account existed and no strong mapping exists. Denied.
- 41: the certificate's SID extension does not match the account's SID. Denied, and worth investigating: either the account was recreated, or someone is presenting a certificate issued to a different principal.
Collect them from all DCs:
$dcs = (Get-ADDomainController -Filter *).HostName
$events = foreach ($dc in $dcs) {
Get-WinEvent -ComputerName $dc -ErrorAction SilentlyContinue -FilterHashtable @{
LogName = 'System'
ProviderName = 'Microsoft-Windows-Kerberos-Key-Distribution-Center'
Id = 39, 40, 41
StartTime = (Get-Date).AddDays(-30)
}
}
$events | Group-Object Id, { $_.Properties[0].Value } |
Sort-Object Count -Descending |
Select-Object Count, Name -First 50The first property of each event is the account name. Grouping by event ID and account turns thousands of events into a short list of failing identities. Read one full event for each group: the message includes the certificate subject, issuer and serial number, which tells you which CA and template produced it.
Audit: certificates without the SID extension
For AD CS certificates, the question is which templates issue certificates without the extension. Three causes cover almost every case:
- Offline templates ("Supply in the request"): the CA cannot know which account the subject refers to, so it does not add the SID.
CT_FLAG_NO_SECURITY_EXTENSION(0x80000inmsPKI-Enrollment-Flag) on the template, which suppresses the extension. Combined with weak mapping this was the ESC9 class.- The extension disabled CA-wide through
DisableExtensionList, which suppresses it for every template (the ESC16 class).
# Templates that suppress the SID extension
$tplBase = "CN=Certificate Templates,CN=Public Key Services,CN=Services,$((Get-ADRootDSE).configurationNamingContext)"
Get-ADObject -SearchBase $tplBase -LDAPFilter '(objectClass=pKICertificateTemplate)' -Properties 'msPKI-Enrollment-Flag' |
Where-Object { $_.'msPKI-Enrollment-Flag' -band 0x80000 } | Select-Object Name
# CA-wide suppression (run against each CA): 1.3.6.1.4.1.311.25.2 must not be listed
certutil -config "ca01.corp.example\CORP-Issuing-CA" -getreg policy\DisableExtensionListTo inspect a certificate on a client, check its extensions directly:
Get-ChildItem Cert:\LocalMachine\My, Cert:\CurrentUser\My |
Where-Object { $_.EnhancedKeyUsageList.ObjectId -contains '1.3.6.1.5.5.7.3.2' } |
Select-Object Subject, Issuer, NotAfter,
@{n='SidExtension';e={ [bool]($_.Extensions | Where-Object { $_.Oid.Value -eq '1.3.6.1.4.1.311.25.2' }) }}Audit: altSecurityIdentities
Explicit mappings are common for smart cards issued by third-party card management systems, for cross-forest certificate logon and for service accounts that authenticate with a certificate. Classify them:
Get-ADObject -LDAPFilter '(altSecurityIdentities=*)' -Properties altSecurityIdentities, objectClass |
ForEach-Object {
foreach ($m in $_.altSecurityIdentities) {
$strength = switch -Regex ($m) {
'^X509:<I>.+<SR>' { 'Strong (IssuerSerial)' }
'^X509:<SKI>' { 'Strong (SKI)' }
'^X509:<SHA1-PUKEY>' { 'Strong (SHA1 public key)' }
'^X509:<RFC822>' { 'Weak (email)' }
'^X509:<I>.+<S>' { 'Weak (issuer+subject)' }
'^X509:<S>' { 'Weak (subject only)' }
'^Kerberos:' { 'Kerberos principal mapping' }
default { 'Unknown' }
}
[pscustomobject]@{ Account = $_.Name; Class = $_.objectClass; Strength = $strength; Mapping = $m }
}
} | Sort-Object Strength | Format-Table -AutoSizeAlso audit who can write the attribute. Write access to altSecurityIdentities on a privileged account lets an attacker map their own certificate to it, the ESC14 class. Include the attribute in your AD ACL review, and make sure Tier 0 accounts are protected by AdminSDHolder so a delegated ACE cannot linger on them.
Enforce: fix each category
- AD CS online templates: already strong once the CAs have the May 2022 update, as long as neither suppression flag is set. Remove
CT_FLAG_NO_SECURITY_EXTENSIONfrom templates, and remove the OID fromDisableExtensionListwithcertutil -setreg policy\DisableExtensionList -1.3.6.1.4.1.311.25.2followed by a CA service restart. Then reissue: existing certificates do not gain the extension, so trigger renewal through autoenrollment ("Reenroll All Certificate Holders" on the template) or wait for natural renewal if it falls inside your window. - Offline templates used for authentication: move the use case to an online template where possible. Otherwise add a strong explicit mapping per certificate, or put the SID in the SAN URL at request time.
- Weak explicit mappings: replace them with
X509IssuerSerialNumber. The serial number must be written in reversed byte order compared with how certificate viewers display it, which is the most common reason a new mapping fails with event 39.
# Build an IssuerSerialNumber mapping from a certificate file
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new('C:\temp\jdoe-card.cer')
$bytes = $cert.GetSerialNumber() # already little-endian (reversed)
$serial = -join ($bytes | ForEach-Object { $_.ToString('x2') })
# KB5014754 examples list the issuer RDNs in reverse order (DC=... first)
$rdns = $cert.Issuer -split ',\s*(?=\w+=)'
[array]::Reverse($rdns)
$issuer = $rdns -join ','
$map = "X509:<I>$issuer<SR>$serial"
$map # review before writing
# Set-ADUser jdoe -Add @{ altSecurityIdentities = $map }Test the resulting string against one account before scripting it across hundreds; the issuer DN format must match what the KDC compares, and the KB includes worked examples.
- Intune and third-party CAs: add the SID to the SAN as a URI (
tag:microsoft.com,2022-09-14:sid:<SID>); in Intune PKCS and SCEP profiles use the on-premises SID variable. For third-party CAs without that capability, use explicit strong mappings or import the vendor's KB5014754 guidance. - Recreated accounts (event 41): the old certificate carries the old SID. Revoke it and enroll a new one for the new account.
Verify
After fixes, the event query from the Measure step should trend to zero for event 39 and 40, and any remaining 41 events should be investigated individually. Check Schannel has not been loosened on servers:
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel' `
-Name CertificateMappingMethods -ErrorAction SilentlyContinueAbsent or 0x18 is expected. On the CA, confirm newly issued authentication certificates contain OID 1.3.6.1.4.1.311.25.2 by dumping one with certutil -dump <file>.cer. Add events 39, 40 and 41 to your DC monitoring permanently, as described in the AD event ID reference: after enforcement, a burst of 41s is a signal, not noise.
What it breaks
- Smart cards from third-party card management systems with UPN-only certificates stop logging on until each card has a strong mapping or is reissued.
- 802.1X and VPN using machine or user certificates through NPS fail for certificates from offline templates or non-Microsoft CAs without the SID. Wireless outages after enforcement are the most common complaint.
- Cross-forest certificate logon relying on name mapping needs explicit strong mappings in the resource forest.
- Accounts deleted and recreated with the same name cannot use certificates issued to the old object (event 41).
- Legacy devices and appliances that authenticate to LDAPS or IIS with client certificates via weak Schannel mapping fail after
CertificateMappingMethodsreturns to the secure default.
Related reading: the AD Certificate Services topic hub, Kerberos hardening for the rest of the KDC-side controls, and machine account quota, which removes the easy source of attacker-controlled computer accounts that Certifried relied on.
Frequently asked questions
Can I still set StrongCertificateBindingEnforcement to 1?
Not on domain controllers running current updates. Microsoft moved DCs to Full Enforcement by default in February 2025 and, per the KB5014754 timeline, removed support for the Compatibility mode setting with the September 2025 security update. On a fully patched DC the value is ignored and weakly mapped certificates are rejected. Fix the certificates and mappings rather than looking for a registry rollback.
Which altSecurityIdentities formats count as strong?
X509IssuerSerialNumber, X509SKI (subject key identifier) and X509SHA1PublicKey are strong because they identify one specific certificate or key. X509IssuerSubject, X509SubjectOnly and X509RFC822 are weak because an attacker who can get a certificate with a chosen subject or email address can satisfy them. Migrate weak entries to issuer and serial number or SKI.
Why do certificates from my Intune or third-party CA fail?
Certificates from standalone or third-party CAs, and from AD CS templates where the subject is supplied in the request, do not carry the SID security extension. Without it, the KDC needs a strong explicit mapping or a SID in a SAN URL. Intune PKCS and SCEP profiles can add the SID to the SAN as a URI using the on-premises SID variable, which is Microsoft's documented fix.
Strong certificate mapping (KB5014754) in practice