Skip to content

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.

Florian Amette7 min read

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:

  1. The SID security extension (szOID_NTDS_CA_SECURITY_EXT, OID 1.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.
  2. A strong explicit mapping in the account's altSecurityIdentities attribute: X509IssuerSerialNumber, X509SKI or X509SHA1PublicKey.
  3. 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:

ValueModeBehaviour
0DisabledNo strong mapping check. Support removed by the April 2023 update
1CompatibilityStrong mapping used when present; weak mapping allowed with event 39, unless the certificate predates the account (event 40, denied)
2Full EnforcementWeakly 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:

PowerShell
$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 50

The 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 (0x80000 in msPKI-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).
PowerShell
# 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\DisableExtensionList

To inspect a certificate on a client, check its extensions directly:

PowerShell
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:

PowerShell
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 -AutoSize

Also 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_EXTENSION from templates, and remove the OID from DisableExtensionList with certutil -setreg policy\DisableExtensionList -1.3.6.1.4.1.311.25.2 followed 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.
PowerShell
# 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:

PowerShell
Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel' `
    -Name CertificateMappingMethods -ErrorAction SilentlyContinue

Absent 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 CertificateMappingMethods returns 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

Related guides