<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: active-directory</title><description>Posts tagged active-directory.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:08 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/active-directory/rss.xml" rel="self" type="application/rss+xml"/><item><title>The Twenty-Year Local Admin Password Crisis: From GPP cpassword to Windows LAPS</title><link>https://paragmali.com/blog/the-twenty-year-local-admin-password-crisis-from-gpp-cpasswo/</link><guid isPermaLink="true">https://paragmali.com/blog/the-twenty-year-local-admin-password-crisis-from-gpp-cpasswo/</guid><description>Microsoft published the AES key that &quot;protected&quot; Group Policy Preferences passwords. Twelve years later, MS14-025 still has not deleted the artefacts. Here is how Windows LAPS finally fixed the architecture -- and what it still cannot solve.</description><pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate><content:encoded>
**Eleven years separated Microsoft&apos;s December 2012 architectural articulation of the shared-local-admin problem from the April 11, 2023 in-box default.** Group Policy Preferences &quot;encrypted&quot; the local Administrator password with an AES key Microsoft published in its own protocol specification (2008-2014). MS14-025 disabled new authoring but deleted no SYSVOL artefacts (2014). Legacy LAPS shipped as a separate MSI with plaintext in `ms-Mcs-AdmPwd` (2015-2023). In-box Windows LAPS finally added CNG DPAPI encryption-at-rest, Microsoft Entra ID backup, and post-authentication rotation. The 2026 default is `BackupDirectory = 2` (AD) or `1` (Entra), `PasswordAgeDays` \&amp;lt;= 30, `ADPasswordEncryptionEnabled` left at its default `True` (the failure mode is silent fallback to plaintext when the domain functional level is below Windows Server 2016, not an off-by-default bit), `ADPasswordEncryptionPrincipal` overridden to a dedicated decryptor group, and `PostAuthenticationActions` left at default `3` (reset + sign out). The residual attack surface is delegated-decryptor compromise, the screenshotted-password OPSEC tail, unmanaged BYOD endpoints, and the multi-decade tail of un-cleaned SYSVOL `cpassword` XMLs that MS14-025 never deleted.
&lt;h2&gt;1. One Password, Fifty Thousand Laptops&lt;/h2&gt;
&lt;p&gt;In May 2012, a domain user with twelve lines of PowerShell could read the local Administrator password for every machine in the organisation. The tool was &lt;code&gt;Get-GPPPassword.ps1&lt;/code&gt; [@obscuresec-gpp-2012]. The &quot;encryption&quot; was AES-256-CBC with a 32-byte key Microsoft had published in its own protocol specification [@ms-gppref-aes-key] -- not leaked, &lt;em&gt;published&lt;/em&gt;, as a feature, so that third-party Group Policy implementations could read the format. Eleven years later, on April 11, 2023, Microsoft finally shipped the in-box fix [@tc-windows-laps-ga-2023].&lt;/p&gt;
&lt;p&gt;This is an article about those eleven years.&lt;/p&gt;

A lateral-movement technique in which an attacker uses the NTLM hash of a captured password directly in an authentication exchange, without recovering the cleartext. If the same local Administrator password is reused across a fleet, one dumped hash unlocks every machine. MITRE catalogues the technique as **T1550.002**.
&lt;p&gt;The pattern was old before 2012. Through the 2000s, the only practical way to provision the local Administrator account on a Windows fleet was to bake one shared password into the reference image and ship the image to every endpoint. Helpdesk knew the password. Pentesters guessed at it. And once Benjamin Delpy&apos;s Mimikatz had pulled the hash from a single phished workstation in 2011, the rest of the org fell to a single &lt;code&gt;psexec&lt;/code&gt; spray. Microsoft documented the threat model precisely in its December 2012 &lt;em&gt;Mitigating Pass-the-Hash&lt;/em&gt; whitepaper [@ms-pth-whitepaper], which named the shared local Administrator credential as the architectural enabler of the entire intrusion class [@mitre-t1550-002].&lt;/p&gt;
&lt;p&gt;Microsoft also had a &lt;em&gt;fix&lt;/em&gt;. It had shipped one in 2008 with Group Policy Preferences (GPP), the feature that could push a per-machine local-admin password from a Group Policy Object to every endpoint. GPP put the password in an XML file in SYSVOL. SYSVOL was world-readable to every authenticated user in the domain. Microsoft encrypted the password with AES-256-CBC -- and then published the key. The result, after a four-author weaponisation chain in mid-2012 [@sogeti-2012-wayback; @obscuresec-gpp-2012; @rewtdance-gpp-2012; @metasploit-gpp], was that GPP made the original problem &lt;em&gt;worse&lt;/em&gt;: instead of one shared password recoverable by physical access to a help-desk laptop, it was now one shared password recoverable by any authenticated domain user with a copy of &lt;code&gt;Get-GPPPassword.ps1&lt;/code&gt;. Microsoft &quot;patched&quot; it on May 13, 2014 with MS14-025 [@ms14-025-bulletin], which disabled new authoring but deleted nothing already deployed. Twelve years later, PingCastle still finds the artefacts in production AD [@pingcastle-rules].&lt;/p&gt;
&lt;p&gt;The first real fix was Generation 2: the legacy Microsoft LAPS, shipped May 1, 2015 as a separate MSI [@ms-advisory-3062591-wayback]. It stored a per-machine random password in the &lt;code&gt;ms-Mcs-AdmPwd&lt;/code&gt; attribute on the computer object, marked CONFIDENTIAL [@adsec-laps-2016]. The directory-side ACL was tighter than SYSVOL, but the deployment surface (install on every endpoint, extend the schema, delegate the OU) capped its real coverage; the password sat in plaintext in AD, one DCSync from &quot;plaintext everywhere&quot;; and a delegation pattern that helpdesks regularly issued -- &quot;All Extended Rights&quot; on the computer OU -- silently included read access to the CONFIDENTIAL attribute [@adsec-laps-2016]. SpecterOps modelled that bypass as the &lt;code&gt;ReadLAPSPassword&lt;/code&gt; BloodHound edge on August 7, 2018 [@specterops-bh2].&lt;/p&gt;
&lt;p&gt;Generation 3 -- Windows LAPS, in-box, no MSI -- shipped on Patch Tuesday April 11, 2023 [@tc-windows-laps-ga-2023] across Windows 11 22H2 and 21H2, Windows 10 22H2, Windows Server 2022, Windows Server 2019, and Windows Server Annual Channel. Windows Server 2016 was explicitly excluded [@ms-laps-overview]. The new architecture wrapped the password with CNG DPAPI&apos;s group key-protector against a configurable principal, exposed Microsoft Entra ID as a peer backup directory [@tc-entra-laps-ga-2023], and added a post-authentication rotation primitive that closed the screenshotted-password OPSEC tail on the &lt;em&gt;next&lt;/em&gt; managed-account logon [@ms-laps-policy-settings].&lt;/p&gt;
&lt;p&gt;The local Administrator account always has the well-known &lt;strong&gt;relative identifier (RID) 500&lt;/strong&gt; in the machine&apos;s SAM, irrespective of any administrative renaming. Renaming the account at the friendly-name level does not change its SID, which is why Windows LAPS resolves the target account by SID and not by name -- and why an empty &lt;code&gt;AdministratorAccountName&lt;/code&gt; policy still finds the right account even on a renamed-built-in host.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Microsoft knew the right architecture for managing local Administrator passwords in December 2012, when its own Pass-the-Hash whitepaper named the shared-credential pattern as the architectural enabler of lateral movement. It took until April 11, 2023 to ship that architecture as a Windows default. Eleven years is a long time. The intervening generations each solved part of the previous problem and introduced a new one. The 2026 baseline is, for the first time, an OS-default solution rather than an out-of-band one -- and for the first time, the residual attack surface is the actual surface rather than an artefact of incomplete shipping.&lt;/p&gt;
&lt;/blockquote&gt;

gantt
    dateFormat YYYY-MM-DD
    axisFormat %Y
    title Local-administrator password management on Windows, 1998-2026&lt;pre&gt;&lt;code&gt;section Generation 0 -- Imaged-build era
Shared local admin password baked into image          :gen0, 1998-01-01, 2008-02-26

section Generation 1 -- GPP cpassword
Group Policy Preferences ships in WS2008 RTM           :g1a, 2008-02-27, 2014-05-12
Linda Moore re-posts &quot;Passwords in GPP (Updated)&quot;     :milestone, 2009-04-22, 1d
Sogeti / obscuresec / rewtdance / Metasploit chain    :crit, 2012-04-01, 2012-07-31
MS PtH whitepaper v1 (architecture articulated)       :milestone, 2012-12-01, 1d
MS14-025 disables new authoring (no remediation)      :milestone, 2014-05-13, 1d

section Generation 2 -- Legacy MSI LAPS
Microsoft LAPS GA (KB3062591 MSI)                      :g2a, 2015-05-01, 2023-04-10
Metcalf publishes All-Extended-Rights bypass           :milestone, 2016-08-01, 1d
SpecterOps BloodHound 2.0 ships ReadLAPSPassword edge :milestone, 2018-08-07, 1d

section Generation 3 -- In-box Windows LAPS
Windows LAPS ships in-box (AD backup)                  :crit, 2023-04-11, 2026-12-31
Windows LAPS with Entra ID GA                          :milestone, 2023-10-23, 1d
Win 11 24H2 passphrases and Automatic Account Mgmt    :milestone, 2024-10-01, 1d
Win 11 25H2 Administrator Protection (orthogonal)     :milestone, 2025-11-19, 1d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The article that follows traces the architecture of each generation, the attacks each one solved and each one enabled, and what &quot;standard local admin password management&quot; looks like as a 2026 default. To see why this took twenty years, we have to start in 1998, before Active Directory.&lt;/p&gt;
&lt;h2&gt;2. Origins: Why Every Workstation Had the Same Local-Admin Password (1998-2008)&lt;/h2&gt;
&lt;p&gt;Picture a system administrator in 2005. They are holding a CD-R labelled &lt;code&gt;Win-Build-7.iso&lt;/code&gt; and a sticky note with a 12-character password. Those two artefacts are the entire local-Administrator-credential lifecycle for ten thousand desktops. The CD will be cloned to a USB drive, the USB drive will reseed Norton Ghost, and Ghost will paint the build onto every new workstation the company buys for the next eight months. Each painted machine will boot with the sticky-note password as its built-in local Administrator. Helpdesk knows the password because they typed it into the image. Five hundred field technicians know the password because they have to be able to recover unmanaged laptops off-network. The pentester who shows up in March will know the password by Tuesday lunch.&lt;/p&gt;
&lt;p&gt;This was not a deviation. It was the architecture.&lt;/p&gt;

Every Windows machine ships with a built-in local Administrator account whose security identifier ends in the **relative identifier 500**. The RID is constant across machines, languages, and SKUs. Renaming the account changes the friendly name but not the RID, so identity-aware tooling (including Windows LAPS) resolves the account by SID rather than by name. Disabling the account is a configuration choice, not a deletion: the account remains in SAM and can be re-enabled at any time.
&lt;p&gt;The mechanics were a function of how Windows was deployed at scale. Microsoft Sysprep &lt;code&gt;/generalize&lt;/code&gt; strips a reference image&apos;s machine SID before duplication, but it leaves the SAM intact. Whatever local Administrator password sits in the reference image is the local Administrator password on every endpoint painted from that image. Imaging pipelines were built around this: Norton Ghost in the late 1990s, Microsoft Deployment Toolkit (MDT) and later System Center Configuration Manager Operating System Deployment in the 2000s, all assumed the same SAM. Sean Metcalf&apos;s December 2015 SYSVOL retrospective walks the era end-to-end and explains why every shop in the world ended up with a single password [@adsec-gpp-2015].&lt;/p&gt;
&lt;p&gt;The operational reality kept the pattern alive. Help-desk needed &lt;em&gt;one&lt;/em&gt; known credential to break-glass a laptop that had wandered off the corporate network for six months. Field technicians needed &lt;em&gt;one&lt;/em&gt; known credential to swap a failed hard drive on a roof-top kiosk in Houston without phoning home. A known-to-the-org local-admin password was the only realistic fallback path, and the alternative -- a different password per machine, stored somewhere retrievable -- required a &lt;em&gt;retrieval&lt;/em&gt; primitive Microsoft had not yet shipped.&lt;/p&gt;
&lt;p&gt;The threat model that made the trade-off catastrophic did not get articulated by Microsoft itself until December 2012, in version 1 of the Pass-the-Hash whitepaper [@ms-pth-whitepaper]. The chain was already common knowledge in offensive-security circles: phish a single user, run Benjamin Delpy&apos;s 2011-vintage Mimikatz to pull credentials from LSASS, capture the NT hash of the built-in &lt;code&gt;Administrator&lt;/code&gt; account, replay that hash to every other host via &lt;code&gt;psexec&lt;/code&gt; or &lt;code&gt;wmiexec&lt;/code&gt;, and pivot up to the first server an enterprise admin has touched. MITRE catalogues the default-account abuse as &lt;strong&gt;T1078.001&lt;/strong&gt; [@mitre-t1078-001] and the hash-replay step as &lt;strong&gt;T1550.002&lt;/strong&gt; [@mitre-t1550-002]. The whitepaper&apos;s recommended controls included exactly the architecture Microsoft would eventually ship as LAPS: per-machine random local-admin passwords, rotated frequently, retrievable only by an authorised principal.&lt;/p&gt;

The hard part was never the cryptography. It was the operations. A pre-2008 sysadmin who proposed &quot;let&apos;s give every workstation a random local-Administrator password&quot; was correctly told that the answer required, at minimum, a directory-scoped retrieval primitive that did not exist; an ACL model that could distinguish &quot;help-desk can read this for their own OU&quot; from &quot;any authenticated user can read this for the whole forest&quot;; and a rotation pipeline that did not depend on the workstation being on the corporate network. Microsoft would not ship those primitives until 2008 (GPP, badly), 2015 (legacy LAPS, well), and 2023 (Windows LAPS, with encryption-at-rest). Until then, &quot;do not get compromised&quot; was the entire mitigation.
&lt;p&gt;The third-party prehistory matters because it set the terms Microsoft would eventually use. PolicyMaker, the engineering parent of what became Group Policy Preferences, was a product of DesktopStandard Corporation that Microsoft acquired in October 2006 [@adsec-gpp-2015]. Thycotic was founded in 1996 by Jonathan Cogley and shipped its Secret Server vault from the mid-2000s [@kuppingercole-cogley]; Lieberman Software (later acquired by Bomgar in January 2018) had operated as Lieberman and Associates since 1978 [@wikipedia-lieberman]; Quest Software was founded in 1987 in Newport Beach, California and was a public company well before the mid-2000s LAPS prehistory began -- its August 14, 1999 NASDAQ IPO saw its shares surge to $47 in a single Wall Street session [@wikipedia-quest; @latimes-quest-ipo-1999]. None of those vendors solved the local-admin-on-every-Windows-machine problem from inside the OS, and Microsoft&apos;s own first-party tooling -- restricted groups, logon scripts, Group Policy Object security templates -- offered no rotation primitive at all. The gap was not a knowledge gap; it was a &lt;em&gt;first-party-feature&lt;/em&gt; gap.&lt;/p&gt;
&lt;p&gt;In February 2008, Microsoft shipped Windows Server 2008. With it came Group Policy Preferences -- and with GPP came a &quot;Local Users and Groups&quot; preference that could push a per-machine local-admin password from a domain GPO to every endpoint in scope. It was the first first-party rotation mechanism Microsoft had ever shipped. It made the problem dramatically worse.&lt;/p&gt;
&lt;h2&gt;3. Decoration Is Not Encryption: GPP cpassword (2008-2012)&lt;/h2&gt;
&lt;p&gt;Microsoft Server 2008 reached release-to-manufacturing in February 2008. Group Policy Preferences shipped with it. The new &quot;Local Users and Groups&quot; preference -- alongside Scheduled Tasks, Services, Data Sources, Drive Maps, and Printers -- could push a password from a GPO down to every endpoint in scope. The password went into an XML file in SYSVOL, the domain&apos;s replicated policy share. SYSVOL was world-readable to every authenticated user in the domain. The password was AES-256-CBC encrypted in the XML, in a field called &lt;code&gt;cpassword&lt;/code&gt;. The key was a 32-byte value published in &lt;code&gt;[MS-GPPREF]&lt;/code&gt; section 2.2.1.1.4 [@ms-gppref-aes-key], in Microsoft&apos;s own Open Specifications protocol corpus -- &lt;em&gt;as a feature&lt;/em&gt;, so that third-party Group Policy implementations could interoperate.&lt;/p&gt;

A file share replicated to every Domain Controller in an Active Directory domain, used to distribute Group Policy templates and logon scripts. The default share permissions allow **Read** access to every Authenticated User in the forest. Any file placed in SYSVOL is, operationally, readable by every domain user.

The XML attribute defined by `[MS-GPPREF]` that carries an encrypted password inside a Group Policy Preferences item. The encryption is AES-256-CBC with a 16-byte zero IV and a static 32-byte key published in the same protocol specification. The name is short for &quot;ciphertext password&quot; and was the canonical search term for finding deployed credentials in SYSVOL between 2012 and 2026.

A loadable component on each Windows endpoint that processes one class of Group Policy setting. Each preference type (Local Users and Groups, Scheduled Tasks, Services, etc.) is implemented by its own CSE, which runs during the Group Policy refresh cycle. CSEs read the policy XML out of SYSVOL, decrypt any `cpassword` field locally, and apply the setting to the host.
&lt;p&gt;Microsoft was not unaware. On April 22, 2009, the Group Policy Team blog re-posted (and updated) a piece by Linda Moore titled &lt;em&gt;&quot;Passwords in Group Policy Preferences (Updated)&quot;&lt;/em&gt; [@ms-gp-blog-grouppolicy-2009-wayback]. The phrasing is unambiguous.&lt;/p&gt;

the password is not secured. Because the password is stored in SYSVOL, all authenticated users have read access to it. -- Linda Moore, Group Policy Team blog, April 22, 2009 [@ms-gp-blog-grouppolicy-2009-wayback]
&lt;p&gt;The post recommended a list of mitigations: prefer secure mechanisms, audit who can read the SYSVOL share, prefer not to use the field at all. None of those mitigations could rotate the key. None could revoke the &lt;em&gt;static AES-256 key value&lt;/em&gt; published in &lt;code&gt;[MS-GPPREF]&lt;/code&gt;. Microsoft was telling its customers, in 2009, three years and eight months before the public weaponisation, that the credential they were storing was decryptable by every user in the domain by design.&lt;/p&gt;
&lt;p&gt;Three years later, the offensive-security community spent twelve weeks turning the publication into a default-on red-team primitive.&lt;/p&gt;
&lt;p&gt;In April and May of 2012, Emilien Girault of Sogeti ESEC published a Python decryptor on the firm&apos;s research blog [@sogeti-2012-wayback]. The site has since been retired and the canonical reference is the Wayback Machine capture. In mid-May 2012, Chris Campbell (@obscuresec) published &lt;code&gt;Get-GPPPassword.ps1&lt;/code&gt;, a PowerShell port that fetched the relevant XML from SYSVOL, decoded the base64, and called .NET&apos;s AES primitives with the published key [@obscuresec-gpp-2012]. The script was folded into PowerSploit at &lt;code&gt;Exfiltration/Get-GPPPassword.ps1&lt;/code&gt;, where its header still reads &lt;em&gt;&quot;Author: Chris Campbell (@obscuresec)&quot;&lt;/em&gt; [@powersploit-getgpppwd] and explicitly credits Emilien Girault for the underlying research. In June 2012, &lt;strong&gt;Ben Campbell&lt;/strong&gt; (the &lt;code&gt;rewtdance.blogspot.com&lt;/code&gt; blog handle), working with &lt;code&gt;scriptmonkey&lt;/code&gt; (a named collaborator with his own blog at &lt;code&gt;blog.owobble.co.uk&lt;/code&gt;), extended the attack to &lt;em&gt;all six&lt;/em&gt; XML wire-format carriers that &lt;code&gt;[MS-GPPREF]&lt;/code&gt; permits [@rewtdance-gpp-2012]. The rewtdance post body credits the collaboration verbatim: &lt;em&gt;&quot;Working with scriptmonkey (&lt;a href=&quot;http://blog.owobble.co.uk/&quot; rel=&quot;noopener&quot;&gt;http://blog.owobble.co.uk/&lt;/a&gt;), who already had a DC configured, we verified this theory.&quot;&lt;/em&gt; On July 25, 2012, the Metasploit module &lt;code&gt;post/windows/gather/credentials/gpp.rb&lt;/code&gt; landed [@metasploit-gpp] with five co-authors: Ben Campbell, Loic Jaquemet, scriptmonkey, theLightCosine, and mubix. A companion auxiliary scanner, &lt;code&gt;auxiliary/scanner/smb/smb_enum_gpp.rb&lt;/code&gt;, was authored independently by Joshua D. Abraham of Praetorian [@metasploit-smb-enum-gpp].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A widespread folk attribution credits &lt;code&gt;Get-GPPPassword.ps1&lt;/code&gt; to &quot;scriptjunkie.&quot; The primary sources do not support that claim. The PowerSploit script header credits Chris Campbell (@obscuresec) [@powersploit-getgpppwd]; the rewtdance June 2012 follow-up is by Ben Campbell with scriptmonkey as a named collaborator (scriptmonkey blogs at &lt;code&gt;blog.owobble.co.uk&lt;/code&gt;, not at rewtdance) [@rewtdance-gpp-2012]; the Metasploit &lt;code&gt;gpp.rb&lt;/code&gt; module&apos;s author field names Ben Campbell, Loic Jaquemet, scriptmonkey, theLightCosine, and mubix [@metasploit-gpp]; and the &lt;code&gt;smb_enum_gpp&lt;/code&gt; scanner is by Joshua D. Abraham [@metasploit-smb-enum-gpp]. No primary source ties &quot;scriptjunkie&quot; (Matt Weeks) to the GPP cpassword research chain at all. The names are similar; the people are different.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The whole exercise was twelve lines of code. The interesting part was not the cryptography. The interesting part was that the operation was &lt;em&gt;decryption-by-reference&lt;/em&gt;: with a published key, the AES envelope was not protecting a secret, it was carrying a secret in a format the protocol specification told everyone how to read.&lt;/p&gt;

```
4e 99 06 e8  fc b6 6c c9  fa f4 93 10  62 0f fe e8
f4 96 e8 06  cc 05 79 90  20 9b 09 a4  33 b6 6c 1b
```
These bytes are reproduced verbatim from Microsoft&apos;s published `[MS-GPPREF]` Group Policy Preferences specification [@ms-gppref-aes-key]. They have appeared in the public Microsoft Open Specifications corpus since the `[MS-GPPREF]` protocol document was first published as part of the Windows Server 2008 protocol-documentation programme; the earliest tangible third-party reuse of the key dates to the April-July 2012 Sogeti / obscuresec / rewtdance / Metasploit research chain [@sogeti-2012-wayback; @obscuresec-gpp-2012; @rewtdance-gpp-2012; @metasploit-gpp]. The key is *not* a secret; it is an interoperability primitive.
&lt;p&gt;{`&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ReadSucceeds[&quot;Read succeeds (silent CONTROL_ACCESS bypass)&quot;]
ReadFails[&quot;Read fails (correctly ACL-gated)&quot;]
Endpoint --&amp;gt; GPRefresh
GPRefresh --&amp;gt; Rotate
Rotate --&amp;gt; SAMWrite
Rotate --&amp;gt; ADWrite
ADWrite --&amp;gt; LDAPRead
LDAPRead --&amp;gt; Bypass
Bypass -- yes --&amp;gt; ReadSucceeds
Bypass -- no --&amp;gt; ReadFails
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The other structural limit was the directory&apos;s own integrity boundary. The password sat in plaintext in the directory. A stolen &lt;code&gt;NTDS.dit&lt;/code&gt; -- obtained via DCSync, NTDSUtil dump, or physical theft of a DC&apos;s disk -- exposed every managed local-Administrator password in the forest at once. There was no encryption-at-rest in legacy LAPS, by design. The trust model was &quot;the directory is tier 0 and DCSync is a domain-compromise event already,&quot; which is operationally true and architecturally lazy.&lt;/p&gt;
&lt;p&gt;Microsoft fixed both of those structural defects on April 11, 2023. The fix shipped in the operating system, with no MSI. We come to it next.&lt;/p&gt;
&lt;h2&gt;6. The In-Box Era: Windows LAPS (April 11, 2023 to Present)&lt;/h2&gt;
&lt;p&gt;Patch Tuesday, April 11, 2023. The April cumulative update for Windows 11 22H2 was KB5025239. The Windows 11 21H2 update was KB5025224. Windows 10 22H2 was KB5025221. Windows Server 2022 was KB5025230. Windows Server 2019 was KB5025229. The Server Annual Channel shipped it too. Windows Server 2016 was, and remains, explicitly excluded -- the per-SKU April-2023 cumulative-update KB numbers are catalogued in the Tenable retrospective on the Windows LAPS GA wave [@tc-windows-laps-ga-2023] and the official Microsoft LAPS overview page [@ms-laps-overview]. The MSI was gone. The &lt;code&gt;admpwd.dll&lt;/code&gt; Client-Side Extension was gone. In its place: &lt;strong&gt;exactly three&lt;/strong&gt; OS binaries -- &lt;code&gt;laps.dll&lt;/code&gt; for core LAPS logic, &lt;code&gt;lapscsp.dll&lt;/code&gt; for the Microsoft Intune Configuration Service Provider, and &lt;code&gt;lapspsh.dll&lt;/code&gt; for the &lt;code&gt;LAPS&lt;/code&gt; PowerShell module -- all shipped together, all part of the OS, all available without installing anything [@ms-laps-concepts-overview; @tc-windows-laps-ga-2023]. The Microsoft Learn &lt;code&gt;laps-concepts-overview&lt;/code&gt; page enumerates the three binaries verbatim and lists no fourth.&lt;/p&gt;
&lt;p&gt;The most consequential architectural change is the one most often missed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The legacy &lt;code&gt;admpwd.dll&lt;/code&gt; was a Group Policy CSE; its rotation cycle was driven by the GP refresh interval (90 minutes plus jitter on member computers). The new &lt;code&gt;laps.dll&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a CSE. It runs on a hard-coded in-process background timer of approximately one hour inside &lt;code&gt;laps.dll&lt;/code&gt; itself -- &lt;strong&gt;not&lt;/strong&gt; a Windows Task Scheduler task, and not configurable. The cited Microsoft Learn page is unambiguous: &lt;em&gt;&quot;Windows LAPS uses a background task that wakes up every hour to process the currently active policy. This task isn&apos;t implemented with a Windows Task Scheduler task and isn&apos;t configurable.&quot;&lt;/em&gt; The polling cycle is decoupled from the Group Policy refresh cycle entirely [@ms-laps-concepts-overview]. The implications: the rotation cadence is not configurable below one hour; reducing the GP refresh interval does not accelerate LAPS rotation; the Task Scheduler library will not show a LAPS task because there isn&apos;t one; and Windows LAPS will rotate a password on an off-network domain-joined machine the moment it re-establishes line-of-sight to a Domain Controller, regardless of whether a GP refresh has fired.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The new schema added six attributes to the &lt;code&gt;Computer&lt;/code&gt; object: &lt;code&gt;msLAPS-Password&lt;/code&gt; (the plaintext-fallback location), &lt;code&gt;msLAPS-EncryptedPassword&lt;/code&gt; (the CNG-DPAPI-wrapped ciphertext blob), &lt;code&gt;msLAPS-EncryptedPasswordHistory&lt;/code&gt; (rotation history), &lt;code&gt;msLAPS-PasswordExpirationTime&lt;/code&gt;, &lt;code&gt;msLAPS-EncryptedDSRMPassword&lt;/code&gt; (Directory Services Restore Mode account on a DC), and &lt;code&gt;msLAPS-EncryptedDSRMPasswordHistory&lt;/code&gt; [@ms-laps-concepts-overview]. The DSRM pair is a Windows-LAPS-only capability; legacy LAPS never covered Domain Controller DSRM accounts. The schema extension is performed once per forest by &lt;code&gt;Update-LapsADSchema&lt;/code&gt;, which is idempotent and coexists with the legacy &lt;code&gt;ms-Mcs-AdmPwd&lt;/code&gt; attribute [@ms-laps-mig-scenarios].&lt;/p&gt;
&lt;p&gt;A seventh attribute, &lt;code&gt;msLAPS-CurrentPasswordVersion&lt;/code&gt;, exists in the &lt;strong&gt;Windows Server 2025 forest schema&lt;/strong&gt; only. It is added automatically when the first Windows Server 2025 Domain Controller is promoted -- &lt;em&gt;not&lt;/em&gt; by running &lt;code&gt;Update-LapsADSchema&lt;/code&gt; -- and is used by &lt;code&gt;laps.dll&lt;/code&gt; to mitigate a virtual-machine-snapshot torn-state class. The attribute is read-only as far as the LAPS feature is concerned and is not part of the &lt;code&gt;ReadLAPSPassword&lt;/code&gt; BloodHound edge&apos;s calculus [@ms-laps-concepts-overview].&lt;/p&gt;
&lt;h3&gt;Encryption-at-rest with CNG DPAPI&lt;/h3&gt;
&lt;p&gt;The load-bearing addition is encryption of the password &lt;em&gt;before&lt;/em&gt; it leaves the client. The mechanism is the &lt;strong&gt;CNG DPAPI&lt;/strong&gt; group key-protector (still commonly called DPAPI-NG in Microsoft&apos;s older documentation) [@ms-cng-dpapi]. The client generates the new local-Administrator password, then wraps the plaintext against a security principal SID using the Active Directory Key Distribution Service (KDS) root key infrastructure. The wrapped blob is the only thing the LDAP write places into &lt;code&gt;msLAPS-EncryptedPassword&lt;/code&gt;. To decrypt, a reader Kerberos-authenticates to the KDC; only members of the configured principal group at decryption time can derive the protector. The directory itself never sees plaintext, and a stolen &lt;code&gt;NTDS.dit&lt;/code&gt; yields ciphertext only [@ms-laps-concepts-overview].&lt;/p&gt;

A protection mechanism in Windows&apos;s CNG (Cryptography API: Next Generation) Data Protection API in which a payload is encrypted against a security principal -- typically an AD group SID -- rather than against a local user. Decryption is gated by Kerberos authentication and the principal&apos;s group membership at the time of decryption [@ms-cng-dpapi]. Microsoft Learn currently spells the primitive *&quot;CNG DPAPI&quot;* on the canonical reference; older Microsoft documentation and Win32 references continue to use the shorthand *&quot;DPAPI-NG&quot;*. They are the same primitive.
&lt;p&gt;There are two policy settings that gate the encryption path, and the failure modes are operationally important.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Microsoft Learn&apos;s &lt;code&gt;laps-management-policy-settings&lt;/code&gt; page lists &lt;code&gt;ADPasswordEncryptionEnabled&lt;/code&gt; with a default of &lt;strong&gt;True&lt;/strong&gt; [@ms-laps-policy-settings]. The genuine failure mode is &lt;em&gt;not&lt;/em&gt; an unset default; it is silent fallback to plaintext in &lt;code&gt;msLAPS-Password&lt;/code&gt; when (a) the forest&apos;s Domain Functional Level is below Windows Server 2016, or (b) the &lt;code&gt;BackupDirectory&lt;/code&gt; value is not &lt;code&gt;2&lt;/code&gt; (AD). Configure the policy &lt;em&gt;explicitly&lt;/em&gt; anyway: the explicit configuration makes the choice visible to policy audits and forces the operator to verify the DFL prerequisite. Do not flip a bit that is already True; do verify the prerequisites that make True work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When &lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt; is unspecified, Windows LAPS wraps the password against the &lt;em&gt;Domain Admins&lt;/em&gt; group of the computer&apos;s domain [@ms-laps-concepts-overview; @ms-laps-policy-settings]. Most fleets do not want every Domain Admin to be a routine LAPS reader. Configure a dedicated, audited, minimum-membership decryption group (a common naming convention is &lt;code&gt;LAPS-DPAPI-Decryptors&lt;/code&gt;) and assign it explicitly. Decryption authority is delegated separately from LDAP read authority; minimising membership of the decryption group is the single most useful hardening lever on a Windows LAPS deployment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The backup-directory choice&lt;/h3&gt;

The CSP / GPO node `BackupDirectory` selects where Windows LAPS writes the rotated password. The three valid values are **0** (do not back up; passwords rotate locally but are not retrievable), **1** (Microsoft Entra ID via the `deviceLocalCredentials` resource on Microsoft Graph), and **2** (Active Directory via the `msLAPS-*` attribute set). The values are mutually exclusive per device; a hybrid-joined device can choose either backend but not both [@ms-laps-policy-settings; @ms-laps-entra-scenarios].
&lt;p&gt;The Entra-backup path went generally available on October 23, 2023 [@tc-entra-laps-ga-2023]. With &lt;code&gt;BackupDirectory = 1&lt;/code&gt;, the local LAPS component posts the rotated password to the &lt;code&gt;deviceLocalCredentials&lt;/code&gt; resource on the device object in Microsoft Entra ID via the Microsoft Graph API [@ms-graph-localcredinfo]. Retrieval is via &lt;code&gt;Get-LapsAADPassword&lt;/code&gt; (a thin wrapper over the Graph endpoint), the Entra portal Devices blade, or a direct &lt;code&gt;GET /directory/deviceLocalCredentials/{deviceId}&lt;/code&gt; call [@ms-laps-entra-scenarios].&lt;/p&gt;
&lt;p&gt;The Entra-backup path has a &lt;strong&gt;seven-day minimum&lt;/strong&gt; for &lt;code&gt;PasswordAgeDays&lt;/code&gt;. The AD-backup path&apos;s minimum is one day. A tier-0 fleet that targets daily rotation on Entra-joined endpoints will not get daily rotation -- Entra-side policy validation rejects the value. Section 7&apos;s baseline table reflects this asymmetry.&lt;/p&gt;
&lt;h3&gt;Policy surface and the FQ-anchored corrections&lt;/h3&gt;
&lt;p&gt;Windows LAPS is configurable via Group Policy (for AD-joined hosts), the LAPS Configuration Service Provider at &lt;code&gt;./Device/Vendor/MSFT/LAPS/Policies/*&lt;/code&gt; for Intune-managed hosts [@ms-laps-csp], local policy, or the legacy LAPS GPO if &lt;code&gt;PolicySourceMode&lt;/code&gt; selects emulation mode. The settings include &lt;code&gt;BackupDirectory&lt;/code&gt;, &lt;code&gt;PasswordComplexity&lt;/code&gt; (values 1 through 8), &lt;code&gt;PasswordLength&lt;/code&gt;, &lt;code&gt;PasswordAgeDays&lt;/code&gt;, &lt;code&gt;PostAuthenticationActions&lt;/code&gt;, &lt;code&gt;PostAuthenticationResetDelay&lt;/code&gt;, &lt;code&gt;AdministratorAccountName&lt;/code&gt;, &lt;code&gt;PassphraseLength&lt;/code&gt;, &lt;code&gt;ADPasswordEncryptionEnabled&lt;/code&gt;, &lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt;, and &lt;code&gt;ADBackupDSRMPassword&lt;/code&gt;. On Windows 11 24H2 and Windows Server 2025 and later, the policy surface adds Automatic Account Management settings: &lt;code&gt;AutomaticAccountManagementEnabled&lt;/code&gt;, &lt;code&gt;AutomaticAccountManagementNameOrPrefix&lt;/code&gt;, &lt;code&gt;AutomaticAccountManagementRandomizeName&lt;/code&gt;, &lt;code&gt;AutomaticAccountManagementTarget&lt;/code&gt;, and &lt;code&gt;AutomaticAccountManagementEnableAccount&lt;/code&gt; [@ms-laps-policy-settings; @ms-laps-account-modes].&lt;/p&gt;

The action Windows LAPS performs after the managed account has authenticated to the host. Valid values are **1** (reset the password), **3** (reset and sign out the interactive session; default), **5** (reset and reboot, with a one-minute reboot delay), and **11** (reset, sign out, and terminate remaining processes; Windows 11 24H2 / Windows Server 2025 and later). The action fires after `PostAuthenticationResetDelay` hours have elapsed since the authentication that triggered it [@ms-laps-policy-settings].
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A widespread misreading of the older Microsoft documentation lists &lt;code&gt;PostAuthenticationActions&lt;/code&gt; as a 1-2-3 enum. The correct enumeration per the current Microsoft Learn reference [@ms-laps-policy-settings] is &lt;strong&gt;1&lt;/strong&gt; (reset password), &lt;strong&gt;3&lt;/strong&gt; (reset + sign out; &lt;em&gt;default&lt;/em&gt;), &lt;strong&gt;5&lt;/strong&gt; (reset + reboot), and &lt;strong&gt;11&lt;/strong&gt; (reset + sign out + terminate remaining processes; Win 11 24H2 / Server 2025+). Value &lt;strong&gt;11&lt;/strong&gt; is &lt;em&gt;not&lt;/em&gt; &quot;force shutdown without warning&quot;; interactive users receive the same non-configurable two-minute warning as on value 3, and remaining processes are terminated after the warning expires. SMB sessions on the host are deleted on values 3 and 11.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;PostAuthenticationResetDelay&lt;/code&gt; defaults to &lt;strong&gt;24 hours&lt;/strong&gt;. The range is 0 to 24 hours; a value of 0 disables the post-authentication action entirely [@ms-laps-policy-settings]. A tier-0 fleet aiming to close the screenshotted-password OPSEC tail aggressively will configure this down to 1 hour; tier-2 deployments typically leave it at 8 or 24.&lt;/p&gt;
&lt;h3&gt;PasswordComplexity values 5 through 8 (Windows 11 24H2+ / Windows Server 2025+)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;PasswordComplexity&lt;/code&gt; values &lt;strong&gt;1 through 4&lt;/strong&gt; are character-class modes (uppercase only; uppercase plus lowercase; uppercase plus lowercase plus numbers; and -- value 4, the default -- all four character classes). Value &lt;strong&gt;5&lt;/strong&gt; is &lt;em&gt;not&lt;/em&gt; a &quot;no vowels or numbers&quot; mode, despite a common folk attribution; it is the &lt;strong&gt;&quot;improved readability&quot; four-class variant&lt;/strong&gt; of value 4, equivalent to value 4 with the visually ambiguous glyphs &lt;code&gt;I&lt;/code&gt;, &lt;code&gt;O&lt;/code&gt;, &lt;code&gt;Q&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;, &lt;code&gt;o&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt; removed and the symbols &lt;code&gt;:&lt;/code&gt;, &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt; added [@ms-laps-passwords-passphrases]. Microsoft&apos;s own documented example password for value 5 is &lt;code&gt;vnJ!!?MTb5=U7Y&lt;/code&gt; -- which retains vowels and digits 2 through 9. Values &lt;strong&gt;6, 7, and 8&lt;/strong&gt; are passphrase modes drawn from a Microsoft-curated wordlist derived from the EFF Diceware wordlists [@eff-dice; @eff-wordlists-2016] with internal modifications. The published word counts after Microsoft&apos;s curation are &lt;strong&gt;7776 / 1276 / 1276&lt;/strong&gt; for modes 6 / 7 / 8 respectively; the EFF originals (the EFF Long Wordlist, EFF Short Wordlist #1, and EFF Short Wordlist #2 published July 2016) are &lt;strong&gt;7776 / 1296 / 1296&lt;/strong&gt; [@eff-dice; @eff-wordlists-2016]. &lt;strong&gt;Values 5 through 8 are all gated on Windows 11 24H2 / Windows Server 2025 and later&lt;/strong&gt; -- not only values 6-8. The cited Microsoft Learn page reads verbatim for value 5: &lt;em&gt;&quot;The PasswordComplexity setting of &apos;5&apos; is only supported in Windows 11 24H2, Windows Server 2025, and later releases.&quot;&lt;/em&gt; [@ms-laps-passwords-passphrases]. Passphrase modes exist for DSRM-account scenarios where the password must be typed by a human under duress; the article&apos;s section 7 baseline recommends them for tier-0 break-glass accounts.&lt;/p&gt;
&lt;h3&gt;PowerShell surface and one important cmdlet name&lt;/h3&gt;
&lt;p&gt;The native &lt;code&gt;LAPS&lt;/code&gt; PowerShell module ships eight cmdlets the article calls out by name: &lt;code&gt;Get-LapsADPassword&lt;/code&gt;, &lt;code&gt;Reset-LapsPassword&lt;/code&gt;, &lt;code&gt;Update-LapsADSchema&lt;/code&gt;, &lt;code&gt;Set-LapsADAuditing&lt;/code&gt;, &lt;code&gt;Set-LapsADComputerSelfPermission&lt;/code&gt;, &lt;code&gt;Set-LapsADReadPasswordPermission&lt;/code&gt;, &lt;code&gt;Set-LapsADResetPasswordPermission&lt;/code&gt;, and &lt;code&gt;Find-LapsADExtendedRights&lt;/code&gt; [@ms-laps-ps-overview; @ms-laps-get-adpassword]. The auditing cmdlet is &lt;code&gt;Set-LapsADAuditing&lt;/code&gt; -- &lt;em&gt;not&lt;/em&gt; &lt;code&gt;Set-LapsADAuditingSettings&lt;/code&gt;, which does not exist as a cmdlet name [@ms-laps-set-adauditing]. The Entra-backup retrieval cmdlet is &lt;code&gt;Get-LapsAADPassword&lt;/code&gt;, a wrapper around Microsoft Graph.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A common copy-paste error in deployment runbooks is to write &lt;code&gt;Set-LapsADAuditingSettings&lt;/code&gt;. The cmdlet name is &lt;code&gt;Set-LapsADAuditing&lt;/code&gt; [@ms-laps-set-adauditing], and the cmdlet emits Directory Service audit event 4662 on configured attribute reads. The SACL it installs targets the LAPS attribute set; you still need the host-side Audit Directory Service Access subcategory enabled on Domain Controllers for the event to land in the Security log.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Migration coexistence&lt;/h3&gt;
&lt;p&gt;Legacy LAPS and Windows LAPS can coexist on the same host only if they target &lt;em&gt;different&lt;/em&gt; local accounts. The documented coexistence pattern is to run legacy LAPS against the built-in RID 500 Administrator while introducing Windows LAPS against a named secondary local-admin account, then retire the legacy MSI once Windows LAPS coverage is verified [@ms-laps-mig-scenarios]. The cross-pointer in section 11 details the seven-step migration sequence.&lt;/p&gt;

flowchart TD
    Tick[&quot;laps.dll background timer (~1 hr)&quot;]
    ReadPolicy[&quot;Read effective policy&lt;br /&gt;CSP &amp;gt; GPO &amp;gt; local &amp;gt; legacy emulation&quot;]
    BackupDir{&quot;BackupDirectory&lt;br /&gt;1 (Entra) / 2 (AD) / 0?&quot;}
    EntraPath[&quot;Write to Graph deviceLocalCredentials&lt;br /&gt;(min PasswordAgeDays = 7)&quot;]
    ADPath[&quot;Write to msLAPS-* attribute set&lt;br /&gt;(min PasswordAgeDays = 1)&quot;]
    EncryptionGate{&quot;ADPasswordEncryptionEnabled = True&lt;br /&gt;AND DFL ≥ Server 2016?&quot;}
    Encrypted[&quot;msLAPS-EncryptedPassword&lt;br /&gt;(DPAPI-NG, principal = ADPasswordEncryptionPrincipal)&quot;]
    Plaintext[&quot;msLAPS-Password (plaintext fallback)&quot;]
    SetSAM[&quot;Set SAM password on&lt;br /&gt;AdministratorAccountName (empty = RID 500)&quot;]
    Auth[&quot;Managed account authenticates&quot;]
    PAA{&quot;PostAuthenticationActions&lt;br /&gt;0 / 1 / 3 / 5 / 11?&quot;}
    Wait[&quot;Wait PostAuthenticationResetDelay (default 24 h)&quot;]
    Action1[&quot;1: reset password&quot;]
    Action3[&quot;3: reset + sign out, 2-min warning, DEFAULT&quot;]
    Action5[&quot;5: reset + reboot, 1-min delay&quot;]
    Action11[&quot;11: reset + sign out + terminate procs (24H2 / WS2025+)&quot;]
    Tick --&amp;gt; ReadPolicy
    ReadPolicy --&amp;gt; BackupDir
    BackupDir -- 1 --&amp;gt; EntraPath
    BackupDir -- 2 --&amp;gt; EncryptionGate
    BackupDir -- 0 --&amp;gt; SetSAM
    EncryptionGate -- yes --&amp;gt; Encrypted
    EncryptionGate -- no --&amp;gt; Plaintext
    EntraPath --&amp;gt; SetSAM
    Encrypted --&amp;gt; SetSAM
    Plaintext --&amp;gt; SetSAM
    SetSAM --&amp;gt; Auth
    Auth --&amp;gt; Wait
    Wait --&amp;gt; PAA
    PAA -- 1 --&amp;gt; Action1
    PAA -- 3 --&amp;gt; Action3
    PAA -- 5 --&amp;gt; Action5
    PAA -- 11 --&amp;gt; Action11
&lt;p&gt;With the in-box era settled, what does a 2026 deployment actually look like? A short list of policy settings, and a slightly longer list of footguns.&lt;/p&gt;
&lt;h2&gt;7. The 2026 Baseline as a Settings Table&lt;/h2&gt;
&lt;p&gt;Architecture is interesting. Audits are not. Here is the 2026 settings table that, in production, separates a deployment that meets its goal from one that quietly does not. Every row carries the policy node, the documented default, the recommended tier-2 value (a typical end-user fleet), the recommended tier-0 value (Domain Controllers and break-glass), and the citation. Cross-check the row against the Microsoft Learn policy-settings page before you ship it.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Policy&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Recommended (tier 2)&lt;/th&gt;
&lt;th&gt;Recommended (tier 0)&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;th&gt;Citation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BackupDirectory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt; (no backup)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt; (AD) for AD-joined and hybrid-joined; &lt;code&gt;1&lt;/code&gt; (Entra) for pure Entra-joined&lt;/td&gt;
&lt;td&gt;same as tier 2&lt;/td&gt;
&lt;td&gt;One directory per device; AD for hybrid where on-prem identity is canonical&lt;/td&gt;
&lt;td&gt;[@ms-laps-policy-settings]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PasswordComplexity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt; (all character classes)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;6&lt;/code&gt; (3-word passphrase) for accounts a human must type under duress (DSRM / break-glass); &lt;code&gt;4&lt;/code&gt; for automated retrieval&lt;/td&gt;
&lt;td&gt;Passphrases for human typing; character-set for tool-only retrieval. Values &lt;strong&gt;5 through 8&lt;/strong&gt; are gated on Windows 11 24H2 / Windows Server 2025 and later: value 5 is the &quot;improved-readability&quot; four-class variant of 4 (not a &quot;no vowels&quot; mode); values 6/7/8 are passphrase modes with Microsoft-curated EFF-derived wordlists of 7776 / 1276 / 1276 entries (EFF originals: 7776 / 1296 / 1296)&lt;/td&gt;
&lt;td&gt;[@ms-laps-passwords-passphrases; @eff-dice; @eff-wordlists-2016]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PasswordLength&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;14&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Eliminates the rainbow-table threat class&lt;/td&gt;
&lt;td&gt;[@ms-laps-passwords-passphrases]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PasswordAgeDays&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;30&lt;/code&gt; (1-day minimum AD; 7-day minimum Entra; 365-day max)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;30&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt; (AD) / &lt;code&gt;7&lt;/code&gt; (Entra; lower fails policy validation)&lt;/td&gt;
&lt;td&gt;Caps the blast radius of an undetected credential theft to one rotation window&lt;/td&gt;
&lt;td&gt;[@ms-laps-policy-settings]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PostAuthenticationActions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt; (reset + sign out)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;, or &lt;code&gt;11&lt;/code&gt; on Win 11 24H2+ if process termination is required&lt;/td&gt;
&lt;td&gt;Closes the screenshot-leak OPSEC tail on the next managed-account interactive logon. Value &lt;code&gt;11&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; &quot;force shutdown without warning&quot; -- it is reset + sign out + terminate remaining processes with the same two-minute warning as &lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;[@ms-laps-policy-settings]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PostAuthenticationResetDelay&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;24&lt;/code&gt; (hours)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trade-off between operational task completion and exposure window&lt;/td&gt;
&lt;td&gt;[@ms-laps-policy-settings]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ADPasswordEncryptionEnabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;True&lt;/code&gt; per Microsoft Learn&apos;s defaults table -- &lt;em&gt;not&lt;/em&gt; off-by-default&lt;/td&gt;
&lt;td&gt;&lt;code&gt;True&lt;/code&gt;, configured explicitly so the choice is visible in policy audits and the DFL prerequisite is verified&lt;/td&gt;
&lt;td&gt;same&lt;/td&gt;
&lt;td&gt;The genuine failure mode is silent fallback to plaintext when DFL is below Server 2016 or &lt;code&gt;BackupDirectory&lt;/code&gt; is not &lt;code&gt;2&lt;/code&gt;, &lt;em&gt;not&lt;/em&gt; a default-off bit&lt;/td&gt;
&lt;td&gt;[@ms-laps-policy-settings; @ms-laps-csp]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Domain Admins&lt;/code&gt; of the computer&apos;s domain when unspecified&lt;/td&gt;
&lt;td&gt;Dedicated &lt;code&gt;LAPS-DPAPI-Decryptors&lt;/code&gt; group, &lt;em&gt;not&lt;/em&gt; Domain Admins&lt;/td&gt;
&lt;td&gt;same, with PIM-gated activation&lt;/td&gt;
&lt;td&gt;Decryption authority is delegated separately from LDAP read; minimise membership&lt;/td&gt;
&lt;td&gt;[@ms-laps-concepts-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AdministratorAccountName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;empty (manages built-in RID 500)&lt;/td&gt;
&lt;td&gt;empty on Server SKUs; named account (e.g. &lt;code&gt;lapsadmin&lt;/code&gt;) on Client SKUs with the built-in disabled&lt;/td&gt;
&lt;td&gt;On Win 11 24H2 / WS2025+, prefer Automatic Account Management with random name and disabled-by-default&lt;/td&gt;
&lt;td&gt;Defeats predictable-RID-500 enumeration&lt;/td&gt;
&lt;td&gt;[@ms-laps-policy-settings; @ms-laps-account-modes]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ADBackupDSRMPassword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;False&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;n/a (member servers)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;True&lt;/code&gt; on Domain Controllers&lt;/td&gt;
&lt;td&gt;Brings DSRM-account management into LAPS scope -- a capability legacy LAPS never had&lt;/td&gt;
&lt;td&gt;[@ms-laps-concepts-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

Tier-0 deviations from the tier-2 baseline are narrow but consequential. (a) `PasswordAgeDays` to 1 (AD) or 7 (Entra) caps the undetected-theft window. (b) `PostAuthenticationResetDelay` to 1 hour aggressively rotates after legitimate use. (c) `ADPasswordEncryptionPrincipal` to a dedicated decryptor group with PIM-gated activation [@ms-entra-pim] -- not standing membership. (d) `ADBackupDSRMPassword = True` only on DCs, so the Directory Services Restore Mode account is in LAPS scope. (e) `PasswordComplexity = 6` on accounts that a human must type under duress (DSRM, ESAE break-glass), `4` everywhere else. The tier-0 baseline is more expensive operationally -- daily rotation and 1-hour post-auth delay create a non-trivial volume of password reads through the decryption group -- and the cost is the entire point. Anything cheaper does not warrant the tier-0 label.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The single most useful hardening move on a Windows LAPS deployment is to explicitly set &lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt; to a dedicated group with minimum membership. Default = Domain Admins of the computer&apos;s domain is operationally correct (Domain Admins should be the readers of last resort) but architecturally lazy (most fleets do not want their DA group to be the routine LAPS-read group). Name the group something searchable -- &lt;code&gt;LAPS-DPAPI-Decryptors&lt;/code&gt; is a defensible convention -- and put helpdesk LAPS-read permissions in &lt;em&gt;that&lt;/em&gt; group, gated by Entra PIM activation [@ms-entra-pim] for non-emergency reads.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The audit-primitives sub-table&lt;/h3&gt;
&lt;p&gt;The decision of which tool answers which question is, in practice, the difference between a LAPS deployment that meets its goal and one that quietly does not. The five (and a half) primitives:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Question it answers&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;BloodHound &lt;code&gt;ReadLAPSPassword&lt;/code&gt; edge&lt;/td&gt;
&lt;td&gt;Which principals can read the LAPS password on which computer objects, transitively across the graph?&lt;/td&gt;
&lt;td&gt;[@bloodhound-edge-readlaps]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PingCastle &lt;code&gt;A-LAPS-Not-Installed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Does this domain have any LAPS solution installed for the native local administrator account?&lt;/td&gt;
&lt;td&gt;[@pingcastle-rules]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PingCastle &lt;code&gt;A-LAPS-Joined-Computers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Can a user who manually domain-joined a computer (via &lt;code&gt;mS-DS-CreatorSID&lt;/code&gt; ownership) still read that computer&apos;s LAPS password?&lt;/td&gt;
&lt;td&gt;[@pingcastle-rules]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PingCastle &lt;code&gt;A-PwdGPO&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Does this domain still have residual GPP &lt;code&gt;cpassword&lt;/code&gt; artefacts in SYSVOL? (MITRE T1552.006)&lt;/td&gt;
&lt;td&gt;[@pingcastle-rules; @mitre-t1552-006]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows event 4662 on &lt;code&gt;msLAPS-*&lt;/code&gt; (SACL via &lt;code&gt;Set-LapsADAuditing&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Who read which LAPS attribute on which computer object, and when?&lt;/td&gt;
&lt;td&gt;[@ms-laps-set-adauditing; @ms-laps-ps-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra audit log + Graph &lt;code&gt;GET /directory/deviceLocalCredentials/{deviceId}&lt;/code&gt; reads&lt;/td&gt;
&lt;td&gt;Who retrieved which LAPS password from Microsoft Entra ID (&lt;code&gt;BackupDirectory = 1&lt;/code&gt;), and when?&lt;/td&gt;
&lt;td&gt;[@ms-graph-localcredinfo; @ms-laps-entra-scenarios]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;No Microsoft Defender for Identity alert in the current public taxonomy names LAPS specifically [@ms-defender-alerts]; instead, lean on the event 4662 SACL primitive plus advanced hunting in the &lt;code&gt;IdentityDirectoryEvents&lt;/code&gt; table for principal-pattern anomalies. Microsoft&apos;s Compromised Credentials and Lateral Movement categories surface the downstream behaviour when a stolen LAPS password gets used.&lt;/p&gt;
&lt;p&gt;{`
// In production, run: Get-LapsADPassword -Identity * | Where-Object {
//   $&lt;em&gt;.ExpirationTimestamp -lt (Get-Date) -or $&lt;/em&gt;.Source -eq &apos;Plaintext&apos;
// }
// This in-browser demo mirrors the same logic against an array of mock computer objects.&lt;/p&gt;
&lt;p&gt;const ONE_DAY_MS = 86400000;
const computers = [
  { name: &quot;WS-001&quot;, msLapsExpiry: Date.now() + 5 * ONE_DAY_MS, encrypted: true  },
  { name: &quot;WS-002&quot;, msLapsExpiry: Date.now() - 2 * ONE_DAY_MS, encrypted: true  },
  { name: &quot;WS-003&quot;, msLapsExpiry: null,                        encrypted: false },
  { name: &quot;WS-004&quot;, msLapsExpiry: Date.now() + 1 * ONE_DAY_MS, encrypted: false },
];&lt;/p&gt;
&lt;p&gt;const gaps = computers.flatMap(c =&amp;gt; {
  const issues = [];
  if (c.msLapsExpiry === null)           issues.push(&quot;no password stored&quot;);
  else if (c.msLapsExpiry &amp;lt; Date.now())  issues.push(&quot;expired (overdue rotation)&quot;);
  if (!c.encrypted)                      issues.push(&quot;plaintext (msLAPS-Password)&quot;);
  return issues.length ? [`${c.name}: ${issues.join(&quot;, &quot;)}`] : [];
});&lt;/p&gt;
&lt;p&gt;console.log(gaps.length === 0
  ? &quot;All computers have current, encrypted LAPS passwords&quot;
  : &quot;Coverage gaps:\n  &quot; + gaps.join(&quot;\n  &quot;));
`}&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;AdministratorAccountName&lt;/code&gt; decision deserves one paragraph of its own. On Server SKUs, the built-in Administrator (RID 500) is enabled by default, and leaving the policy empty manages it -- this is what most deployments want. On Client SKUs the built-in is disabled by default; many shops create a named admin account (a common convention is &lt;code&gt;lapsadmin&lt;/code&gt;) and set &lt;code&gt;AdministratorAccountName&lt;/code&gt; to that name. On Windows 11 24H2 and Windows Server 2025 and later, the better answer is Automatic Account Management: set &lt;code&gt;AutomaticAccountManagementEnabled = 1&lt;/code&gt;, &lt;code&gt;AutomaticAccountManagementRandomizeName = 1&lt;/code&gt;, and &lt;code&gt;AutomaticAccountManagementEnableAccount = 0&lt;/code&gt;, and the host will auto-create a randomised-name disabled-by-default local-admin account that Windows LAPS owns end to end [@ms-laps-account-modes]. The result is that an attacker enumerating local accounts cannot guess the LAPS-managed account name from RID 500, RID 1000, or any other predictable identifier.&lt;/p&gt;
&lt;p&gt;This is the baseline. But LAPS is not the only answer to &quot;who knows the local admin password.&quot; For three classes of fleet, the right answer is something else.&lt;/p&gt;
&lt;h2&gt;8. When LAPS Is Not the Right Tool&lt;/h2&gt;
&lt;p&gt;Three classes of fleet should not -- or should not &lt;em&gt;only&lt;/em&gt; -- run Windows LAPS. The first wants a workflow LAPS does not offer. The second wants no standing local admin at all. The third is orthogonal: it changes the in-session elevation surface without changing the recoverable break-glass.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Third-party Privileged Access Management (PAM) vaults.&lt;/strong&gt; Delinea Secret Server [@delinea-secretserver], CyberArk Endpoint Privilege Manager [@cyberark-epm], and BeyondTrust Password Safe are the dominant 2026 commercial offerings in the category. The case for running a PAM vault alongside (or instead of) Windows LAPS is rarely about cryptography and almost always about workflow. PAM vaults bring multi-factor authentication on checkout, full session recording, dual-approval gates for high-risk accounts, and cross-OS scope (Windows, macOS, Linux, network gear, hypervisors) under one ACL model. The total cost of ownership is higher than LAPS; the security model, properly deployed, is comparable. Many shops run both: Windows LAPS for the workstation floor, PAM for tier-0 break-glass with session recording. The split is a &lt;em&gt;workflow&lt;/em&gt; trade-off, not an architectural one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zero standing local admin plus Entra PIM JIT elevation.&lt;/strong&gt; Tier-0 fleets that have reached the &quot;no routine local admin&quot; architectural state disable the built-in RID 500 entirely and gate every admin operation through just-in-time elevation. Microsoft Entra Privileged Identity Management [@ms-entra-pim] supports the eligibility / activation / approval workflow at scale: an operator is &lt;em&gt;eligible&lt;/em&gt; for an admin role, &lt;em&gt;activates&lt;/em&gt; it for a bounded duration with optional MFA and ticket reference, and an &lt;em&gt;approver&lt;/em&gt; signs off on the activation if policy requires. Windows LAPS coexists in this model as the absolute-last-resort break-glass mechanism -- for the case where Entra itself is down, the network is partitioned, and a human has to walk to a console and type a password. The architectural alignment is with MITRE T1078.001 (Default Accounts) [@mitre-t1078-001]: if the default account is permanently disabled and only re-enabled under PIM workflow, the entire technique class is bounded by the PIM activation log.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows 11 25H2 Administrator Protection.&lt;/strong&gt; Per-elevation transient admin sessions arrived as a Tech Community preview in late 2025 [@tc-admin-protection-win11]. The feature creates a temporary, isolated &quot;shadow admin&quot; identity for the duration of each elevation prompt, brokering UAC-class elevation through a per-elevation token that is destroyed when the elevated process exits. &lt;strong&gt;This is orthogonal to LAPS, not a replacement.&lt;/strong&gt; Administrator Protection addresses in-session UAC elevation; Windows LAPS addresses the recoverable break-glass password for off-network and non-bootable recovery. The two systems answer different questions. Conflating them produces designs that drop LAPS in favour of Administrator Protection and then discover, six months later, that there is no recovery primitive for a laptop the user has dropped off the corporate network for a year.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Recommended method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;On-premises AD-joined, no Entra ID&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;A&lt;/strong&gt; -- in-box Windows LAPS with AD backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Entra hybrid-joined, on-prem AD authoritative&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;A&lt;/strong&gt; -- Microsoft&apos;s current hybrid recommendation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure Entra-joined, no on-prem AD&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;B&lt;/strong&gt; -- in-box Windows LAPS with Entra ID backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stuck on Windows Server 2016 (excluded from Windows LAPS)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt; -- legacy MSI LAPS until OS migration completes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In active migration from legacy LAPS to Windows LAPS&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;C&lt;/strong&gt; in side-by-side mode with different managed accounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-Windows scope (Linux, macOS, network gear) needs unified vaulting&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;D&lt;/strong&gt; -- third-party PAM vault, often alongside A/B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Regulated industry requiring session recording / MFA checkout&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;D&lt;/strong&gt; alongside A/B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tier-0 fleet with a zero-standing-credential goal and Entra ID P2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;E&lt;/strong&gt; -- PIM-gated JIT elevation layered on A or B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 11 fleet wanting in-session credential-theft mitigation&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;F&lt;/strong&gt; -- Administrator Protection alongside A/B (orthogonal)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYOD, workgroup, or unmanaged endpoints&lt;/td&gt;
&lt;td&gt;None of A through F -- &lt;em&gt;enrollment&lt;/em&gt; is the answer, not LAPS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

flowchart TD
    Start[&quot;Local-admin password problem for a fleet&quot;]
    BYOD{&quot;BYOD or unmanaged?&quot;}
    EnrollFirst[&quot;Enrollment is the answer, not LAPS&quot;]
    Join{&quot;AD-joined / hybrid / Entra-joined?&quot;}
    WS2016{&quot;Stuck on WS2016 or in migration?&quot;}
    Tier0{&quot;Tier 0 with zero-standing-credential goal?&quot;}
    CrossOS{&quot;Non-Windows scope or checkout workflow needed?&quot;}
    WinElev{&quot;Win 11 25H2 in-session elevation hardening?&quot;}
    MA[&quot;Method A: Windows LAPS, AD backup&quot;]
    MB[&quot;Method B: Windows LAPS, Entra backup&quot;]
    MC[&quot;Method C: legacy MSI LAPS&quot;]
    MD[&quot;Method D: PAM vault, alongside A/B&quot;]
    ME[&quot;Method E: PIM-gated JIT, layered on A/B&quot;]
    MF[&quot;Method F: Administrator Protection (orthogonal)&quot;]
    Start --&amp;gt; BYOD
    BYOD -- yes --&amp;gt; EnrollFirst
    BYOD -- no --&amp;gt; Join
    Join -- AD or hybrid --&amp;gt; MA
    Join -- pure Entra --&amp;gt; MB
    MA --&amp;gt; WS2016
    MB --&amp;gt; WS2016
    WS2016 -- yes --&amp;gt; MC
    WS2016 -- no --&amp;gt; Tier0
    Tier0 -- yes --&amp;gt; ME
    Tier0 -- no --&amp;gt; CrossOS
    CrossOS -- yes --&amp;gt; MD
    CrossOS -- no --&amp;gt; WinElev
    WinElev -- yes --&amp;gt; MF

The terminology is genuinely confusing. *Microsoft Entra hybrid joined* is a device join state: the workstation is joined to both an on-premises AD domain and Microsoft Entra ID, and both directories know about it. *Microsoft Entra hybrid runbook worker*, by contrast, is an Azure Automation primitive that runs Automation runbooks on a worker process inside an on-premises environment. They share a word and nothing else. Windows LAPS policy for hybrid-*joined* devices is a `BackupDirectory` choice (typically AD for on-prem-authoritative hybrid fleets, Entra for Entra-authoritative); Hybrid runbook workers are an Azure Automation concern and entirely outside the LAPS scope.
&lt;p&gt;All five answers above -- methods A through F -- have a structural ceiling. There is one bound none of them can break.&lt;/p&gt;
&lt;h2&gt;9. What LAPS Structurally Cannot Solve&lt;/h2&gt;
&lt;p&gt;Every recoverable-secret system has a privileged reader. Whether you call it &lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt;, a &quot;CyberArk vault admin,&quot; or a &quot;PIM eligible approver,&quot; somebody can break the glass -- which means somebody can compromise the glass. This is a lower bound, not an implementation defect.&lt;/p&gt;
&lt;p&gt;The eleven-year arc converged on a tight bound. It did not abolish the underlying problem. Four structural limits are worth naming, because each maps onto a real residual attack surface in 2026 deployments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bound 1: at least one reader exists, by construction.&lt;/strong&gt; Symbolically, $|\text{readers}| \geq 1$. CNG DPAPI&apos;s group-key-protector substitution does not eliminate the privileged class; it relocates the trust boundary. The boundary moves from &quot;every principal with LDAP read on the attribute&quot; (legacy LAPS) to &quot;every principal in the configured &lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt; group at decryption time&quot; (Windows LAPS). The relocation tightens the bound by orders of magnitude in typical fleets -- a &lt;code&gt;LAPS-DPAPI-Decryptors&lt;/code&gt; group with five members beats an &quot;All Extended Rights on the helpdesk OU&quot; delegation with five hundred -- but it does not move the bound to zero. The directory that stores the LAPS secret remains a tier-0 asset, and the decryptor group remains a tier-0 principal class.&lt;/p&gt;

Every recoverable secret has a privileged reader. The architectural game is to make the reader class small, audited, time-bounded, and reachable from the directory only through Kerberos. The game is not to make the reader class empty. That game has no winning move.
&lt;p&gt;&lt;strong&gt;Bound 2: the out-of-protocol OPSEC tail.&lt;/strong&gt; Once a plaintext password leaves the directory -- pasted into a helpdesk ticket, screenshotted into a Slack DM, stored in a shared KeePass database that the team forgot to rotate -- the protocol&apos;s rotation knob is the only remaining mitigation. &lt;code&gt;PostAuthenticationActions&lt;/code&gt; only fires after the &lt;em&gt;next managed-account interactive logon&lt;/em&gt; [@ms-laps-policy-settings]; pre-logon exposure is bounded only by &lt;code&gt;PasswordAgeDays&lt;/code&gt;. A password screenshotted into a chat log at 10:14 AM and never used is the password on that endpoint for the remainder of the configured rotation window, regardless of whether anyone has noticed the leak. The protocol does not, and cannot, solve &quot;the password is now in a chat log.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bound 3: unmanaged and BYOD endpoints.&lt;/strong&gt; A machine that is neither AD-joined nor Microsoft Intune-managed has no LAPS policy applied to it. Personal-device BYO MAM scope is outside the LAPS protection model entirely. The fix for these endpoints is enrollment, not LAPS. A non-trivial portion of the residual local-admin-password risk in 2026 is concentrated on the long tail of unmanaged endpoints that exist precisely because management was politically or contractually infeasible. The protocol does not solve this; &lt;em&gt;governance&lt;/em&gt; solves this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bound 4: verification asymmetry.&lt;/strong&gt; The directory&apos;s audit log says what it &lt;em&gt;chose&lt;/em&gt; to log. An unprivileged observer cannot verify enforcement from outside the directory. This is the structural ceiling that motivates external audit primitives -- PingCastle [@pingcastle-rules], BloodHound [@bloodhound-edge-readlaps], Defender for Identity [@ms-defender-alerts] -- because they sit outside the directory&apos;s own self-report. The bound cannot be closed inside the protocol; only an out-of-band attestation primitive can certify enforcement to a party that does not trust the directory.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Somebody has to break the glass. The decryptor group is the new tier-0 asset; LAPS bounds the problem, it does not abolish it. The eleven-year arc was a convergence on a tighter bound, not an arrival at a clean answer. The right framing for the 2026 baseline is &quot;the residual attack surface is now the &lt;em&gt;actual&lt;/em&gt; attack surface, rather than an artefact of incomplete shipping.&quot; That is real progress -- it just is not closure.&lt;/p&gt;
&lt;/blockquote&gt;

A structurally tighter design would have three properties: threshold cryptography so no single principal can decrypt (an $m$-of-$n$ Shamir secret-sharing scheme over the password protector, with $m \geq 2$ in tier-0 fleets); attestation-bound retrieval so the decryptor&apos;s device state is part of the decryption policy (Azure Managed HSM&apos;s secure-key-release policy grammar [@ms-mhsm-policy-grammar] is the closest shipping primitive that approaches this -- a key-release decision conditioned on attestation claims like `x-ms-attestation-type` or `tee:sevsnpvm`); and a ledger-of-reads so every retrieval is recorded on a tamper-evident substrate that the directory itself cannot rewrite (Azure Confidential Ledger [@ms-conf-ledger] is the closest shipping primitive on the Microsoft side). None of these three are wired into Windows LAPS in 2026. Each exists as an adjacent Microsoft product. The architectural integration -- a Windows LAPS that requires two `LAPS-DPAPI-Decryptors` members to co-sign a retrieval, attests the retrieving device&apos;s state at decryption time, and writes the retrieval event to an append-only ledger the directory cannot edit -- is engineering work that nobody has shipped.
&lt;p&gt;Some of those structural bounds map onto open problems with no clean 2026 answer. We close on six of them.&lt;/p&gt;
&lt;h2&gt;10. Open Problems in 2026&lt;/h2&gt;
&lt;p&gt;Six open problems in local-admin password management for which no first-party Microsoft answer ships in 2026. Each is one paragraph, framed as &quot;what is the question,&quot; &quot;what has been tried,&quot; and &quot;what is the current best partial result.&quot;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Open question&lt;/th&gt;
&lt;th&gt;What has been tried&lt;/th&gt;
&lt;th&gt;Current best partial result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Legacy SYSVOL &lt;code&gt;cpassword&lt;/code&gt; cleanup at scale&lt;/td&gt;
&lt;td&gt;MS14-025 (UI disable, no remediation); PingCastle scanning; community &lt;code&gt;Get-GPPDeployedPasswords&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Third-party scan-and-manual-delete; no first-party cmdlet ships in the OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-tenant / cross-directory LAPS coverage report&lt;/td&gt;
&lt;td&gt;Microsoft Intune compliance reports; manual &lt;code&gt;Get-LapsADPassword&lt;/code&gt; and &lt;code&gt;Get-LapsAADPassword&lt;/code&gt; joins&lt;/td&gt;
&lt;td&gt;DIY KQL across two directories; no unified portal report&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid-joined &lt;code&gt;BackupDirectory&lt;/code&gt; ambiguity&lt;/td&gt;
&lt;td&gt;Microsoft Learn guidance (&quot;AD for hybrid&quot;)&lt;/td&gt;
&lt;td&gt;Most shops configure both and reconcile downstream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Win 11 25H2 Administrator Protection and LAPS interaction&lt;/td&gt;
&lt;td&gt;Tech Community guidance; Microsoft Learn architectural notes&lt;/td&gt;
&lt;td&gt;Operate them as orthogonal, with no architectural integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LDAP channel binding / signing enforcement migration&lt;/td&gt;
&lt;td&gt;Microsoft KB4520412 enforcement push 2020-2024; cross-platform tool updates&lt;/td&gt;
&lt;td&gt;Some Linux pentest tooling still incomplete; &lt;code&gt;bloodyAD&lt;/code&gt; / &lt;code&gt;lapsv2decrypt&lt;/code&gt; lead the field [@kb4520412-canonical]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieval-event audit gap (cross-directory)&lt;/td&gt;
&lt;td&gt;Event 4662 SACL via &lt;code&gt;Set-LapsADAuditing&lt;/code&gt;; Entra audit log; Defender for Identity hunting&lt;/td&gt;
&lt;td&gt;DIY KQL unification across AD + Entra; no unified audit pane&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;1. Legacy SYSVOL cpassword cleanup at scale.&lt;/strong&gt; MS14-025 disabled new authoring twelve years ago; it never deleted what it patched [@ms14-025-bulletin]. No first-party &lt;code&gt;Find-GPPPassword&lt;/code&gt; or &lt;code&gt;Remove-GPPPassword&lt;/code&gt; cmdlet ships in the OS in 2026. PingCastle&apos;s &lt;code&gt;A-PwdGPO&lt;/code&gt; rule and Semperis Purple Knight&apos;s equivalent scanner fill the gap [@pingcastle-rules]. The 2026 answer is: scan with a third-party tool, rotate the discovered credentials in whatever account-management primitive owns them, then delete the XML. The open question is why Microsoft has not shipped this in the twelve years since the bulletin. The blast-radius argument from 2014 -- &quot;we cannot risk auto-deleting policy XMLs from SYSVOL&quot; -- is now strictly weaker than the cleanup-tail argument that the residual artefacts keep showing up on internal pentest reports a decade later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Cross-tenant and cross-directory LAPS coverage view.&lt;/strong&gt; No portal-level &quot;every Entra-joined and every AD-joined device that does not have a current LAPS password&quot; report exists. Microsoft Intune compliance reports help on the Intune-managed side; &lt;code&gt;Get-LapsADPassword -Identity *&lt;/code&gt; covers the AD side; &lt;code&gt;Get-LapsAADPassword&lt;/code&gt; covers the Entra side. There is no single pane that unifies them. The 2026 answer is custom KQL or PowerShell that joins the three result sets on a normalised device identifier. The bottleneck is identity: Intune device IDs, AD &lt;code&gt;objectGuid&lt;/code&gt; values, and Entra &lt;code&gt;deviceId&lt;/code&gt; values are three different surrogate keys, and a fleet&apos;s mapping table is its own engineering investment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Hybrid-joined &lt;code&gt;BackupDirectory&lt;/code&gt; ambiguity.&lt;/strong&gt; Microsoft Learn&apos;s current guidance is that hybrid-joined devices should typically use &lt;code&gt;BackupDirectory = 2&lt;/code&gt; (AD) when on-premises AD is the canonical identity store, and may use &lt;code&gt;BackupDirectory = 1&lt;/code&gt; (Entra) when Intune is the primary policy-delivery mechanism [@ms-laps-entra-scenarios]. In practice, the documentation hedges, and many shops configure both directions (one via GPO, one via Intune CSP) and rely on the per-device evaluation order to pick one. The result is a coverage-verification problem: a device that is &quot;configured for AD backup&quot; by GPO and &quot;configured for Entra backup&quot; by CSP can end up with the password in either backend, and the source of truth depends on policy precedence rules most operators do not memorise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Windows 11 25H2 Administrator Protection and LAPS interaction.&lt;/strong&gt; Administrator Protection&apos;s per-elevation transient admin tokens and Windows LAPS&apos;s recoverable break-glass password are operationally adjacent but architecturally disjoint [@tc-admin-protection-win11]. The documentation covers each feature on its own; the interaction matrix -- &quot;what does a LAPS-managed RID 500 look like under Administrator Protection on a Win 11 25H2 host&quot; -- is not laid out in one place. Tier-0 architects who want both behaviours have to assemble the answer from two product pages.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. LDAP channel binding and signing enforcement migration.&lt;/strong&gt; Microsoft has been hardening LDAP channel binding through a multi-year 2020-2024 enforcement push tracked under KB4520412 [@kb4520412-canonical]. The original March 10, 2020 update introduced Channel Binding Token (CBT) signing events 3039, 3040, and 3041; the manual enablement step was removed on November 14, 2023 for Windows Server 2022 and on January 9, 2024 for Windows Server 2019, after which the hardening became the default posture; starting with Windows Server 2022 23H2, all new versions ship with the full set of changes in the KB applied [@kb4520412-canonical]. Tooling that does not speak LDAPS-with-channel-binding will break when enforcement reaches its terminal state. Modern attack-graph tooling -- &lt;code&gt;bloodyAD&lt;/code&gt; [@bloodyad-repo] and the &lt;code&gt;lapsv2decrypt&lt;/code&gt; reference implementation [@lapsv2decrypt-repo] -- has tracked the changes. Not every Linux pentest stack has. Practitioners building Linux-based LAPS retrieval pipelines should validate their stack against the channel-binding-required posture before the enforcement wave reaches them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. The retrieval-event audit gap (cross-directory).&lt;/strong&gt; Active Directory does not natively log every read of &lt;code&gt;msLAPS-EncryptedPassword&lt;/code&gt;; &lt;code&gt;Set-LapsADAuditing&lt;/code&gt; installs a SACL that emits Directory Service event 4662 for configured attribute reads [@ms-laps-set-adauditing]. Microsoft Entra ID logs LAPS retrieval through its own audit log, surfaced via the Graph endpoint [@ms-graph-localcredinfo]. The two log streams have different schemas, different timestamp normalisations, and different principal identifiers. Cross-pane unification of &quot;who read which LAPS password when&quot; across both backends is a DIY engineering problem in 2026. Microsoft Defender for Identity surfaces some of the AD-side reads under the Compromised Credentials and Lateral Movement categories [@ms-defender-alerts] but does not name LAPS specifically in the public alert taxonomy.&lt;/p&gt;
&lt;p&gt;The threshold-cryptography open problem (an $m$-of-$n$ Shamir scheme over the LAPS password protector, with $m \geq 2$ in tier-0 fleets) is theoretically closed by the 1979 Shamir secret-sharing construction. The deployment-side block is that no Microsoft-shipped primitive wires the construction to the LAPS rotation pipeline. Adjacent shipping primitives (Azure Managed HSM key-release [@ms-mhsm-policy-grammar], Azure Confidential Ledger [@ms-conf-ledger]) exist on the Azure side, but the integration with on-premises LAPS clients is not on any public roadmap. The companion posts on DPAPI internals (#20) and Defender for Identity (#87) cover adjacent territory but do not close this gap.&lt;/p&gt;
&lt;p&gt;None of those six dissolves the architectural lesson the eleven-year arc taught: the right defaults take a decade to ship. Here is the practitioner field manual for the meantime.&lt;/p&gt;
&lt;h2&gt;11. Practitioner Field Manual and FAQ&lt;/h2&gt;
&lt;p&gt;What follows is a seven-step deployment list, three named sidebars that surface the most common misconceptions, and a seven-question FAQ. Lift the step list verbatim into your deployment runbook; the sidebars exist because the article would not be defensible without them.&lt;/p&gt;
&lt;h3&gt;The audit-and-migrate seven-step list&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Audit SYSVOL for &lt;code&gt;cpassword&lt;/code&gt; first.&lt;/strong&gt; Run PingCastle&apos;s &lt;code&gt;A-PwdGPO&lt;/code&gt; (MITRE T1552.006) [@pingcastle-rules; @mitre-t1552-006] before touching anything else. A Windows triage one-liner -- &lt;code&gt;findstr /s /i cpassword \\domain\SYSVOL\*.xml&lt;/code&gt; -- will land on most environments in under a minute. Remediate the discovered XML files (rotate the underlying account passwords, then delete the XMLs) before deploying Windows LAPS so the attack surface and the defence are not co-evolving in the same window.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extend the AD schema for Windows LAPS.&lt;/strong&gt; Run &lt;code&gt;Update-LapsADSchema&lt;/code&gt; once per forest from a Domain Admin context. The cmdlet is idempotent and coexists with the legacy &lt;code&gt;ms-Mcs-AdmPwd&lt;/code&gt; attribute on the same &lt;code&gt;Computer&lt;/code&gt; object [@ms-laps-mig-scenarios].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delegate.&lt;/strong&gt; Run &lt;code&gt;Set-LapsADComputerSelfPermission&lt;/code&gt; on each target OU so that computer accounts can write their own &lt;code&gt;msLAPS-*&lt;/code&gt; attributes. Audit existing &quot;All Extended Rights&quot; delegations with &lt;code&gt;Find-LapsADExtendedRights&lt;/code&gt; and remove any that do not have an explicit operational justification [@ms-laps-ps-overview]. This is the legacy-LAPS lesson applied to the new attribute set.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure encryption-at-rest.&lt;/strong&gt; Verify that the forest&apos;s Domain Functional Level is Windows Server 2016 or higher. Configure &lt;code&gt;ADPasswordEncryptionEnabled = 1&lt;/code&gt; &lt;em&gt;explicitly&lt;/em&gt; even though the default is True -- the explicit configuration makes the choice visible in policy audits and forces the operator to verify the DFL prerequisite [@ms-laps-policy-settings]. Assign &lt;code&gt;ADPasswordEncryptionPrincipal&lt;/code&gt; to a dedicated &lt;code&gt;LAPS-DPAPI-Decryptors&lt;/code&gt; group, not Domain Admins [@ms-laps-concepts-overview].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy policy.&lt;/strong&gt; GPO for AD-joined, Intune CSP for Entra-joined and hybrid-joined [@ms-laps-csp]. Settings as per section 7&apos;s baseline table. Validate via &lt;code&gt;Get-LapsADPassword -Identity &amp;lt;computer&amp;gt;&lt;/code&gt; against a representative sample of hosts after the first one-hour rotation timer has fired [@ms-laps-get-adpassword].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migrate from legacy LAPS.&lt;/strong&gt; Use the documented coexistence pattern: the legacy MSI&apos;s CSE keeps running against the built-in RID 500, the new in-box LAPS takes over against a named secondary local-admin account, then retire the legacy &lt;code&gt;ms-Mcs-AdmPwd&lt;/code&gt; schema readers and uninstall the MSI once Windows LAPS coverage is verified [@ms-laps-mig-scenarios]. The legacy MSI&apos;s installation is blocked on Windows 11 23H2 and later [@ms-laps-msi-download].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continuous audit.&lt;/strong&gt; PingCastle for coverage rules (&lt;code&gt;A-LAPS-Not-Installed&lt;/code&gt;, &lt;code&gt;A-LAPS-Joined-Computers&lt;/code&gt;, and the GPP &lt;code&gt;A-PwdGPO&lt;/code&gt;) [@pingcastle-rules]; BloodHound for the &lt;code&gt;ReadLAPSPassword&lt;/code&gt; edge across the graph [@bloodhound-edge-readlaps]; Defender for Identity for downstream behaviour under Compromised Credentials and Lateral Movement [@ms-defender-alerts]; and a custom KQL on the Entra audit log for &lt;code&gt;LapsPasswordRetrieved&lt;/code&gt; events. None of these is optional in a deployment that intends to detect compromise.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Sidebar A: MS16-072 is NOT the LAPS attribute-readability bulletin&lt;/h3&gt;
&lt;p&gt;A recurring misattribution credits MS16-072 / KB3163622 / CVE-2016-3223 (June 14, 2016) [@ms16-072-bulletin; @ms16-072-kb; @cve-2016-3223] with closing the legacy LAPS attribute-readability issue. It does not. MS16-072 is a Group Policy retrieval-context fix: it moved user-side GPO fetch into the &lt;em&gt;computer&apos;s&lt;/em&gt; security context to defeat a man-in-the-middle class on policy traffic. The actual LAPS attribute-readability issue -- &quot;All Extended Rights&quot; delegations silently including &lt;code&gt;CONTROL_ACCESS&lt;/code&gt; on the CONFIDENTIAL &lt;code&gt;ms-Mcs-AdmPwd&lt;/code&gt; attribute -- has no Microsoft-assigned CVE or bulletin. The canonical write-up is Sean Metcalf&apos;s August 2016 ADSecurity piece [@adsec-laps-2016], and the operational primitive is SpecterOps&apos;s &lt;code&gt;ReadLAPSPassword&lt;/code&gt; BloodHound edge [@bloodhound-edge-readlaps].&lt;/p&gt;
&lt;h3&gt;Sidebar B: &quot;Hybrid joined&quot; is not &quot;Hybrid Worker&quot;&lt;/h3&gt;
&lt;p&gt;Microsoft Entra &lt;em&gt;hybrid joined&lt;/em&gt; devices are workstations joined to both an on-premises AD domain and Microsoft Entra ID. The LAPS conversation about hybrid joined is a &lt;code&gt;BackupDirectory&lt;/code&gt; choice. Microsoft Entra &lt;em&gt;hybrid runbook workers&lt;/em&gt;, on the other hand, are an Azure Automation primitive -- worker processes that execute Automation runbooks against on-premises resources. They share a word and nothing else. A LAPS policy targeted at &quot;hybrid devices&quot; means hybrid joined; it has nothing to do with hybrid runbook workers. The article&apos;s section 8 includes the same disambiguation because operators conflate them with surprising frequency.&lt;/p&gt;
&lt;h3&gt;Sidebar C: How GPP cpassword still gets found in 2026&lt;/h3&gt;
&lt;p&gt;MS14-025 disabled new authoring but did not delete the artefacts [@ms14-025-bulletin]. The artefacts persist because SYSVOL replication is conservative -- nothing in the forest&apos;s design &lt;em&gt;deletes&lt;/em&gt; anything from SYSVOL just because the editor UI was hot-patched on the administrative workstation. A fresh PingCastle scan against a long-lived forest will routinely surface 2010-era &lt;code&gt;Groups.xml&lt;/code&gt; files [@pingcastle-rules], and the third-party scanner cohort is the only practical defence. The one-shot remediation pattern is: find with &lt;code&gt;A-PwdGPO&lt;/code&gt;, rotate the underlying password via the replacement tool (Windows LAPS for built-in local admin; a PAM vault for service accounts that were stored in GPP), then delete the &lt;code&gt;Groups.xml&lt;/code&gt; and let SYSVOL replication propagate the deletion.&lt;/p&gt;

No. Administrator Protection addresses in-session UAC-class elevation by brokering each elevation through a per-elevation transient shadow-admin identity [@tc-admin-protection-win11]; it does not provide a recoverable break-glass password for an off-network or non-bootable endpoint. The two systems are orthogonal and Microsoft recommends running them together on Windows 11 25H2 fleets. Replacing LAPS with Administrator Protection produces designs that lose the recovery primitive for laptops that have wandered off the corporate network for a year.

Defence in depth, plus a coverage-leak primitive. An LDAP reader who is not in `ADPasswordEncryptionPrincipal` gets only an opaque ciphertext blob [@ms-laps-concepts-overview] -- but the same reader can still enumerate which computer objects have a current `msLAPS-EncryptedPassword`, which gives them target-selection telemetry on managed-versus-unmanaged hosts. The canonical write-up of this class is Sean Metcalf&apos;s August 2016 ADSecurity piece on the legacy `ms-Mcs-AdmPwdExpirationTime` attribute [@adsec-laps-2016], and the architectural lesson carries forward to Windows LAPS unchanged.

Yes, in seconds. The 32-byte AES-256-CBC key is published verbatim in `[MS-GPPREF]` section 2.2.1.1.4 of Microsoft&apos;s Open Specifications corpus [@ms-gppref-aes-key] and that publication is permanent under the Open Specifications Promise. Any residual `Groups.xml` (or five sibling carriers including the asymmetric `Printers.xml` [@rewtdance-gpp-2012]) in SYSVOL that contains a `cpassword` attribute is operationally plaintext. The 2026 answer is to find them with PingCastle&apos;s `A-PwdGPO` rule [@pingcastle-rules] and remediate -- not to expect the artefacts to expire on their own.

No. The rotation cycle is the `PasswordAgeDays` interval (default 30 days, minimum 1 on AD backup, minimum 7 on Entra backup) [@ms-laps-policy-settings]. After authentication, `PostAuthenticationActions` (default `3` = reset + sign out) fires once the `PostAuthenticationResetDelay` window (default 24 hours) has elapsed. Value `11` (Windows 11 24H2 / Server 2025+) adds termination of remaining processes; it is *not* a forced shutdown without warning -- the standard two-minute warning still applies and SMB sessions are deleted.

Yes. LAPS rotates the password on a disabled account; the account simply cannot be used to log on until it is enabled. The break-glass runbook is: enable the account, retrieve the LAPS password, perform the recovery, rotate immediately, re-disable. On Windows 11 24H2 and Windows Server 2025 and later, Microsoft&apos;s recommendation is to enable Automatic Account Management with a randomised name and `AutomaticAccountManagementEnableAccount = 0` so the managed account ships disabled-by-default with a non-predictable name [@ms-laps-account-modes]. The pattern defeats predictable-RID-500 enumeration entirely.

Microsoft Entra ID. With `BackupDirectory = 1` [@ms-laps-policy-settings], the local LAPS component posts the rotated password to the `deviceLocalCredentials` resource on the Entra device object via Microsoft Graph [@ms-graph-localcredinfo]. Retrieval is via `Get-LapsAADPassword` (a wrapper around the Graph endpoint), the Microsoft Entra portal Devices blade, or a direct `GET /directory/deviceLocalCredentials/{deviceId}` call [@ms-laps-entra-scenarios]. Read permission requires the Cloud Device Administrator or Intune Service Administrator Entra role.

No. `CanReadGMSAPassword` is the edge for **Group Managed Service Accounts** -- a different Active Directory feature with a different ACL on a different attribute (`msDS-GroupMSAMembership`). The correct LAPS edge is **`ReadLAPSPassword`**, introduced in BloodHound 2.0 on August 7, 2018 [@specterops-bh2], and the current edge documentation covers both the legacy `ms-Mcs-AdmPwd` and the modern `msLAPS-*` attribute paths [@bloodhound-edge-readlaps].
&lt;p&gt;The companion posts in this series cover Pass-the-Hash itself (#76), DPAPI internals (#20), Microsoft Entra Privileged Identity Management (#90), Active Directory tiering (#72), Microsoft Defender for Identity (#87), and BloodHound (#77). Each of those is referenced in this article at the point where the topic would otherwise demand a digression; each has its own deep treatment elsewhere.&lt;/p&gt;
&lt;p&gt;Twenty years. Eleven years of which separated Microsoft&apos;s December 2012 articulation of the architecture from the April 11, 2023 in-box default [@ms-pth-whitepaper; @tc-windows-laps-ga-2023]. Four residual attack surfaces -- delegated-decryptor compromise, the pre-rotation OPSEC tail, BYOD endpoints, and the multi-decade MS14-025 cleanup tail [@ms14-025-bulletin] -- still resist the architecture rather than fall to it. One through-line: this is what shipping the right default a decade late looks like. The right defaults are now in the box. The directory is still tier 0. Somebody still has to break the glass. The architectural game from here is not to invent a new generation; it is to make sure the one we finally have is actually deployed, audited, and clean.&lt;/p&gt;
</content:encoded><category>windows</category><category>active-directory</category><category>laps</category><category>group-policy</category><category>identity</category><category>credential-theft</category><category>entra-id</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Pass-the-Hash to Pass-the-PRT: Twenty-Nine Years of Windows Credential Replay in One Family Tree</title><link>https://paragmali.com/blog/pass-the-hash-to-pass-the-prt-twenty-nine-years-of-windows-c/</link><guid isPermaLink="true">https://paragmali.com/blog/pass-the-hash-to-pass-the-prt-twenty-nine-years-of-windows-c/</guid><description>Pass-the-Hash, Pass-the-Ticket, Overpass-the-Hash, Pass-the-Certificate, and Pass-the-PRT are one architectural lineage. Each defense bought years; none closed the family.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><content:encoded>
Twenty-nine years of Windows credential-replay attacks -- Pass-the-Hash, Pass-the-Ticket, Overpass-the-Hash, Pass-the-Certificate, Pass-the-PRT -- are a single lineage, not five techniques. Each generation finds the next long-term authentication artefact that lives outside the latest Microsoft isolation boundary, then commoditises extraction in tooling that runs anywhere with local administrator. Credential Guard (2015) and KB5014754 (2022) bought years but not closure; Pass-the-PRT (Mollema + Delpy, 2020) already defeats both because the Primary Refresh Token lives in the CloudAP plug-in, which is not inside any current isolation scope. The next decade of Windows credential theft turns on whether Microsoft extends hypervisor-based isolation to CloudAP before commodity offensive tooling makes the attack universal.
&lt;h2&gt;1. Two Afternoons, Twenty-Nine Years Apart&lt;/h2&gt;
&lt;p&gt;On the afternoon of Tuesday, April 8, 1997, between 5:27 p.m. and 8:57 p.m. -- a window we can narrow to about three and a half hours from the file timestamps preserved in the patch he posted -- a researcher named Paul Ashton sat down with the Samba source tree and made the smallest possible change to &lt;code&gt;smbclient&lt;/code&gt;.The bracketing mtimes &lt;code&gt;Tue Apr  8 17:27:29 1997&lt;/code&gt; and &lt;code&gt;Tue Apr  8 20:57:43 1997&lt;/code&gt; are preserved verbatim in the unified diff&apos;s &lt;code&gt;***&lt;/code&gt; and &lt;code&gt;---&lt;/code&gt; header lines on Exploit-DB advisory 19197 [@ashton-exploitdb-19197]. You can still download the diff today and confirm the timestamps yourself. Where the unpatched client computed a network response from a typed-in password, his version read the password&apos;s LM hash from &lt;code&gt;smbpasswd&lt;/code&gt; on disk and fed it straight to the same encryption primitive, skipping the password entirely.&lt;/p&gt;
&lt;p&gt;He posted the diff to NTBugtraq the same evening with a five-line advisory: &quot;A modified SMB client can mount shares on an SMB host by passing the username and corresponding LanMan hash of an account that is authorized to access the host and share. The modified SMB client removes the need for the user to &apos;decrypt&apos; the password hash into its clear-text equivalent.&quot; [@ashton-exploitdb-19197]&lt;/p&gt;
&lt;p&gt;Twenty-nine years later, every Windows credential-replay attack in commodity offensive tooling is a direct descendant of that afternoon.&lt;/p&gt;
&lt;p&gt;Fast-forward to 2026. A Windows 11 23H2 laptop, hardened to Microsoft&apos;s published baseline. &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; on. KB5014754 strong certificate mapping in full enforcement. Conditional Access enabled, with Token Protection where supported. An attacker has local admin -- the same starting position the 1997 attack assumed.&lt;/p&gt;
&lt;p&gt;Two commands run on that machine, in the same paragraph. Mimikatz &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; returns empty NT hash and TGT buffers; Credential Guard has done its job. Then Mimikatz &lt;code&gt;dpapi::cloudapkd /unprotect&lt;/code&gt; returns a valid Primary Refresh Token session key and proof-of-possession material [@mollema-prt-digging]. On a &lt;em&gt;different&lt;/em&gt; machine across the internet, the attacker pastes that material into Dirk-jan Mollema&apos;s &lt;code&gt;roadtx prt&lt;/code&gt;, mints an &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; cookie, and authenticates to Entra ID as the laptop&apos;s user [@mollema-prt-abusing] [@roadtools-github]. Every Microsoft defense shipped in 2015, 2022, and 2024 is running. The attack still wins.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The empty buffer from &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; is the artefact of twenty-nine years of architectural lessons. The PRT extraction from &lt;code&gt;dpapi::cloudapkd&lt;/code&gt; is the architecture of the &lt;em&gt;next&lt;/em&gt; five-to-ten years. Both scenes are the same attack class. The credential changed; the protocol that consumes it changed; the long-term storage location changed; the lineage did not.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You will meet seven people in this article. Paul Ashton (1997, the patch). Hernan Ochoa (2008, the toolkit that put the technique inside Windows itself). Benjamin Delpy (2011, Mimikatz; and the Kerberos generations that followed). Sean Metcalf (2014, who named Overpass-the-Hash and wrote the practitioner reference that taught a generation of red and blue teams).&lt;/p&gt;
&lt;p&gt;Will Schroeder and Lee Christensen (2021, &quot;Certified Pre-Owned,&quot; the AD CS catalog that became Pass-the-Certificate). Oliver Lyak (2022, Certifried, the CVE that forced Microsoft to ship KB5014754). And Dirk-jan Mollema (2020, the Primary Refresh Token research this article argues is the most consequential credential-theft work since 2008). The cast is small. The lineage they built is the load-bearing structure of every Windows penetration test in 2026.&lt;/p&gt;
&lt;p&gt;How is it possible that the same attack works in 1997 and 2026? The answer is structural, not coincidental -- and once you see it, you cannot unsee it.&lt;/p&gt;
&lt;h2&gt;2. The Architectural Property the Family Shares&lt;/h2&gt;
&lt;p&gt;NTLM authentication never asks for the password as a string. It asks for a function of the hash. The hash &lt;em&gt;is&lt;/em&gt; the password.&lt;/p&gt;
&lt;p&gt;That sentence is the article&apos;s load-bearing claim, and the rest of this section is its proof.&lt;/p&gt;
&lt;p&gt;The Microsoft specification for the NTLM protocol -- &lt;code&gt;[MS-NLMP]&lt;/code&gt;, sections 3.3.1 and 3.3.2 -- writes the response computation in pseudocode. For NTLMv1, the server sends an 8-byte challenge; the client computes &lt;code&gt;NtChallengeResponse = DESL(ResponseKeyNT, challenge)&lt;/code&gt;, where &lt;code&gt;ResponseKeyNT = NTOWFv1(password) = MD4(UNICODE(password))&lt;/code&gt; [@ms-nlmp-3-3-1]. &lt;code&gt;DESL&lt;/code&gt; is a variant of DES that pads the 16-byte NT hash to 21 bytes with five zero bytes, splits the result into three 7-byte sub-keys, runs DES on the 8-byte challenge under each sub-key, and concatenates the three 8-byte ciphertexts to form a 24-byte response.&lt;/p&gt;
&lt;p&gt;NTLMv2 is more elaborate -- the response key is &lt;code&gt;NTOWFv2 = HMAC_MD5(MD4(UNICODE(password)), UNICODE(Uppercase(User) + UserDom))&lt;/code&gt;, and the proof string is &lt;code&gt;HMAC_MD5&lt;/code&gt; of the challenge concatenated with a target-info structure -- but the structural property is identical: the cleartext password appears in exactly one place in the entire protocol, the input to the hash function on the client. The verifier performs the same computation against the stored NT hash from the SAM or NTDS.dit, and compares. Neither side ever transmits the password [@ms-nlmp-3-3-2].&lt;/p&gt;
&lt;p&gt;This is what Microsoft means when its institutional documentation says Pass-the-Hash &quot;cannot be patched at the protocol level.&quot; There is nothing to patch.The same property holds for any challenge-response protocol whose verifier stores a determinable function of the password rather than the password itself: Kerberos with stored long-term keys, CHAP with shared secrets, OAuth client_credentials with shared secrets, every HMAC-based proof-of-possession scheme.&lt;/p&gt;
&lt;p&gt;The protocol takes a stored hash and produces a response. Swap the user&apos;s hash for the attacker&apos;s hash, and the protocol still produces a valid response, signed by the substituted key. The bug is not a bug; it is a documented property.&lt;/p&gt;

A family of Windows authentication protocols (NTLMv1 and NTLMv2) in which a server sends a random challenge and the client returns a response computed by applying a keyed cryptographic primitive (DES or HMAC-MD5) to that challenge under a key derived from the user&apos;s password. The verifier holds the same key and recomputes the response to confirm. The cleartext password is never transmitted [@ms-nlmp-3-3-1] [@ms-nlmp-3-3-2].

The 16-byte MD4 of the user&apos;s password as UTF-16 little-endian (`MD4(UNICODE(Passwd))` in the NLMP pseudocode). Unsalted by design, because NT was originally specified for an offline domain controller that has to verify against a fixed reference value. The NT hash is the long-term symmetric Windows authentication secret for every account, stored locally in the SAM and centrally in the NTDS.dit Active Directory database [@ms-nlmp-3-3-1].

The technique of authenticating to a service that uses NTLM (or any protocol descended from the same family) by feeding a stolen NT hash directly to the response-construction function, instead of typing a password the function would then hash. The terminology and the first working demonstration are due to Paul Ashton, NTBugtraq, April 1997 [@ashton-exploitdb-19197].

sequenceDiagram
    participant Client
    participant Server
    participant Verifier as SAM or NTDS.dit
    Client-&amp;gt;&amp;gt;Server: NTLM_NEGOTIATE
    Server-&amp;gt;&amp;gt;Client: NTLM_CHALLENGE with 8-byte nonce
    Note over Client: ResponseKeyNT equals NTOWFv1 of stored NT hash
    Note over Client: NtChallengeResponse equals DESL of ResponseKeyNT and nonce
    Client-&amp;gt;&amp;gt;Server: NTLM_AUTHENTICATE with response
    Server-&amp;gt;&amp;gt;Verifier: Look up stored NT hash for user
    Verifier--&amp;gt;&amp;gt;Server: Stored NT hash
    Note over Server: Recompute DESL of stored hash and nonce
    Server-&amp;gt;&amp;gt;Client: Authentication succeeds if responses match
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The hash is the password. Any long-term authentication artefact reachable by the process that uses it is replayable -- and every credential type the rest of this article discusses (Kerberos TGT, certificate private key, Primary Refresh Token session key) is a different instance of this same property. Defenses can isolate one artefact at a time; the property is intrinsic to the architecture.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ashton&apos;s 1997 patch was the protocol-disclosure proof. He swapped a single function call -- &lt;code&gt;SMBencrypt(pass, cryptkey, pword)&lt;/code&gt; became &lt;code&gt;E_P24(p21, cryptkey, pword)&lt;/code&gt;, where &lt;code&gt;p21&lt;/code&gt; is the user&apos;s LM hash read directly from &lt;code&gt;smbpasswd&lt;/code&gt; -- and Samba&apos;s &lt;code&gt;smbclient&lt;/code&gt; authenticated to NT 3.51 and NT 4.0 file servers without ever knowing the user&apos;s password [@ashton-exploitdb-19197]. You can read the patch in five minutes. It is also, in a precise sense, the first proof that NTLM&apos;s response computation is hash-equivalent: if substituting the hash works, then mathematically the hash is what the protocol wanted all along.&lt;/p&gt;
&lt;p&gt;And then nothing happened for eleven years.&lt;/p&gt;
&lt;p&gt;That gap deserves its own explanation, because the eleven-year interregnum is the cleanest failure mode in the lineage.&lt;/p&gt;
&lt;p&gt;Wikipedia&apos;s modern summary of the pre-2008 limitation reads: &quot;even after performing NTLM authentication successfully using the pass the hash technique, tools like Samba&apos;s SMB client might not have implemented the functionality the attacker might want to use. This meant that it was difficult to attack Windows programs that use DCOM or RPC. Also, because attackers were restricted to using third-party clients when carrying out attacks, it was not possible to use built-in Windows applications, like Net.exe or the Active Directory Users and Computers tool amongst others, because they asked the attacker or user to enter the cleartext password to authenticate, and not the corresponding password hash value.&quot; [@wikipedia-pass-the-hash]&lt;/p&gt;

Inside Microsoft the 1997 patch was treated as confirming a known property of LSASS-resident credentials, not as a new attack class. The institutional position was that any compromise yielding the hash already implied SYSTEM-equivalent access, and that the realistic chain was &quot;exfiltrate the hash and crack it offline,&quot; not &quot;replay the hash.&quot; The architectural counter-claim -- that *replaying* the hash from inside a Windows process bypasses every native-tool obstacle -- took a decade to land in the practitioner literature. The 2012 Duckwall + Campbell Black Hat USA paper named the lag in its title: &quot;Still Passing the Hash 15 Years Later.&quot; [@duckwall-campbell-bh2012]
&lt;p&gt;If the obstacle is &quot;built-in Windows tools ask for cleartext,&quot; the architectural answer is to put the substituted hash &lt;em&gt;inside&lt;/em&gt; the Windows process that those tools rely on. That insight took eleven years to operationalise. The person who operationalised it was Hernan Ochoa, in 2008.&lt;/p&gt;
&lt;h2&gt;3. From Patch to Toolkit: The Windows-Native Pivot&lt;/h2&gt;
&lt;p&gt;By 2008, Ashton&apos;s 1997 patch had been sitting on NTBugtraq for eleven years. Hernan Ochoa had a different idea: instead of patching the client, patch the &lt;em&gt;credential cache&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The artefact Ochoa shipped at CanSecWest 2008 and Black Hat USA 2008 was called the &lt;em&gt;Pass-the-Hash Toolkit&lt;/em&gt;, distributed through Core Security Technologies&apos; open-source projects page [@corelabs-pshtoolkit-wayback]. It contained two executables. &lt;code&gt;IAM.EXE&lt;/code&gt; opened the LSASS process with &lt;code&gt;PROCESS_VM_WRITE&lt;/code&gt;, located the cached credential block for the current interactive logon session, and overwrote the NT hash and username fields with attacker-supplied values. &lt;code&gt;PTH.EXE&lt;/code&gt; spawned a target process under a substituted hash.&lt;/p&gt;
&lt;p&gt;Once the substitution was in place, every native Windows SSO consumer -- &lt;code&gt;net.exe&lt;/code&gt;, &lt;code&gt;wmic&lt;/code&gt;, &lt;code&gt;mstsc&lt;/code&gt; once Restricted Admin RDP shipped years later, SMB, RPC, DCOM -- transparently picked up the attacker-supplied hash, because the OS handed them what it believed were the legitimate user&apos;s credentials.&lt;/p&gt;
&lt;p&gt;Wikipedia summarises the architectural pivot in one paragraph: &quot;It allowed the user name, domain name, and password hashes cached in memory by the Local Security Authority to be changed at runtime &lt;em&gt;after&lt;/em&gt; a user was authenticated -- this made it possible to &apos;pass the hash&apos; using standard Windows applications, and thereby to undermine fundamental authentication mechanisms built into the operating system.&quot; [@wikipedia-pass-the-hash] The eleven-year limitation was gone. Pass-the-Hash was now a Windows-native attack that worked against any tool that read its credentials from LSASS -- which in practice meant &lt;em&gt;every&lt;/em&gt; Windows tool.&lt;/p&gt;

The user-mode Windows process (`lsass.exe`) that handles interactive logon, owns the Security Reference Monitor&apos;s policy decisions, and -- relevant to this article -- caches the in-memory credential material that supports Single Sign-On for the duration of each logon session: NT hashes for NTLM, Kerberos TGTs and session keys, certificate handles, and (since Azure AD / Entra ID device join) Primary Refresh Token material in the CloudAP plug-in. Every credential-replay technique in this article reaches its target by reading LSASS in some form.
&lt;p&gt;The 2012 retrospective is where the security industry stopped pretending Pass-the-Hash was solved. Alva Duckwall and Christopher Campbell shipped a Black Hat USA 2012 paper titled, unambiguously, &quot;Still Passing the Hash 15 Years Later.&quot; [@duckwall-campbell-bh2012] The title is the load-bearing pull-quote: it named Ashton 1997 as the origin, Ochoa 2008 as the Windows-native pivot, and the industry&apos;s continued failure to ship a structural fix as the central fact. From this point onwards Microsoft itself acknowledged Pass-the-Hash as a structural property of NTLM rather than a fixable bug.&lt;/p&gt;
&lt;p&gt;Hernan Ochoa&apos;s Windows Credentials Editor (WCE), released a year after the Pass-the-Hash Toolkit, developed the same LSASS-injection primitive on a separate code base. Two independent implementations converging on the same memory-access pattern in the same window is the clearest indication that the architectural insight -- &quot;the credential is sitting in a process you can write to&quot; -- was overdetermined once anyone went looking for it.&lt;/p&gt;
&lt;p&gt;What did Ashton&apos;s 1997 patch leave on the table? The other long-term credentials that LSASS held. The NT hash was the first. There would be more.&lt;/p&gt;
&lt;p&gt;If you can read the NT hash from LSASS, you can read the Kerberos TGT from LSASS. The same memory-access primitive that animates &lt;code&gt;IAM.EXE&lt;/code&gt; is one commit away from animating &lt;code&gt;sekurlsa::tickets&lt;/code&gt;. That commit shipped in May 2011. Its author was a twenty-five-year-old French programmer named Benjamin Delpy.&lt;/p&gt;
&lt;h2&gt;4. Mimikatz and the Kerberos Turn&lt;/h2&gt;
&lt;p&gt;In May 2011, Benjamin Delpy posted his first public release of a program he had been writing as a side project to learn C. He was twenty-five, working as an IT manager at an institution he has never publicly named. Andy Greenberg&apos;s Wired profile records the date: &quot;He released it publicly in May 2011, but as a closed source program.&quot; [@wired-greenberg-mimikatz] Wikipedia corroborates: &quot;He released the first version of the software in May 2011 as closed source software.&quot; [@wikipedia-mimikatz] The program was called Mimikatz.&lt;/p&gt;
&lt;p&gt;What made Mimikatz architecturally different from Ochoa&apos;s toolkit was that it was &lt;em&gt;modular&lt;/em&gt;. The credential-extraction primitives lived in named command groups: &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; dumped NT hashes from LSASS; &lt;code&gt;sekurlsa::tickets&lt;/code&gt; dumped Kerberos tickets from LSASS; &lt;code&gt;kerberos::ptt&lt;/code&gt; injected a stolen ticket into the current Kerberos cache via the documented &lt;code&gt;LsaCallAuthenticationPackage&lt;/code&gt; API with the &lt;code&gt;KerbSubmitTicketMessage&lt;/code&gt; message [@ms-lsa-call-auth-package]; &lt;code&gt;lsadump::dcsync&lt;/code&gt; (added August 2015, in collaboration with Vincent Le Toux) impersonated a domain controller and asked another DC for the krbtgt hash via the IDL_DRSGetNCChanges replication RPC [@adsec-dcsync-p1729].&lt;/p&gt;
&lt;p&gt;Same LSASS, different artefact, different protocol surface. The architectural property section 2 named had two artefacts to work with on Windows: the NT hash, and the Kerberos TGT.&lt;/p&gt;
&lt;p&gt;This is &lt;strong&gt;Pass-the-Ticket&lt;/strong&gt; (Generation 2). The stolen TGT plus its session key authenticates the holder as the original principal for the ticket&apos;s lifetime, which on a default AD deployment is ten hours, renewable for seven days. Time complexity per replay: O(1). The TGT session key is the load-bearing piece -- without it, the ticket is opaque encrypted bytes that the holder cannot decrypt, sign, or present back to the KDC. Mimikatz&apos;s &lt;code&gt;sekurlsa::tickets /export&lt;/code&gt; writes the ticket as a &lt;code&gt;.kirbi&lt;/code&gt; file on disk; &lt;code&gt;kerberos::ptt &amp;lt;file&amp;gt;&lt;/code&gt; re-injects on any machine where the user has a Kerberos credentials cache.&lt;/p&gt;

The long-lived Kerberos credential issued by the KDC&apos;s Authentication Service (AS-REP) in response to a successful AS-REQ. The TGT is encrypted under the KDC&apos;s own krbtgt-account long-term key and contains a session key that the client uses to subsequently request service tickets from the Ticket Granting Service (TGS). Specification: RFC 4120, section 3 [@rfc-4120]. On a Windows Active Directory deployment the default TGT lifetime is 10 hours with renewal up to 7 days.

The technique of extracting a Kerberos TGT (and its session key) from one machine&apos;s LSASS-resident Kerberos cache and injecting it into another machine&apos;s cache, so that subsequent service-ticket requests authenticate as the ticket&apos;s original principal. Tool of record: Mimikatz `sekurlsa::tickets` + `kerberos::ptt`; equivalent functionality in Rubeus and Impacket.

sequenceDiagram
    participant Victim as Victim host
    participant Attacker as Attacker host
    participant KDC
    Note over Victim: User logged in, TGT cached in LSASS Kerberos package
    Attacker-&amp;gt;&amp;gt;Victim: mimikatz sekurlsa::tickets export
    Victim--&amp;gt;&amp;gt;Attacker: TGT.kirbi (ticket plus session key)
    Note over Attacker: mimikatz kerberos::ptt TGT.kirbi
    Attacker-&amp;gt;&amp;gt;KDC: TGS-REQ presenting injected TGT
    KDC--&amp;gt;&amp;gt;Attacker: TGS-REP service ticket
    Attacker-&amp;gt;&amp;gt;Attacker: Authenticate to any Kerberos service as the victim
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A common shorthand says that Microsoft&apos;s Credential Guard isolated NT hashes, so attackers shifted to TGTs. That arrow runs backwards in time. Pass-the-Ticket predates Credential Guard by years -- the Mimikatz Kerberos primitives developed between the May 2011 closed-source release and the April 6, 2014 open-source commit (the earliest verifiable source-level evidence for &lt;code&gt;sekurlsa::tickets&lt;/code&gt; and &lt;code&gt;kerberos::ptt&lt;/code&gt;), and were presented in detail at Black Hat USA 2014 by Duckwall and Delpy [@infocondb-bh2014-duckwall] [@duckwall-delpy-bh2014-wp]. Pass-the-Ticket exists because TGTs are also in LSASS, not as a defensive response. The shift to a new artefact happened because the &lt;em&gt;architectural property&lt;/em&gt; of credential extraction generalised, not because Credential Guard pushed attackers there.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The third generation followed shortly. &lt;strong&gt;Overpass-the-Hash&lt;/strong&gt; observes that for the RC4-HMAC Kerberos encryption type -- the Windows default from Windows 2000 through November 2022 -- the user&apos;s long-term Kerberos key is the unchanged NT hash.&lt;/p&gt;
&lt;p&gt;RFC 4757, authored by K. Jaganathan, L. Zhu, and J. Brezak of Microsoft and published as informational in December 2006, specifies the RC4-HMAC enctype&apos;s long-term key as the existing NT hash without modification [@rfc-4757]. An attacker who holds the NT hash can drive a legitimate Kerberos AS-REQ to the KDC, encrypt the timestamp pre-auth blob with the NT hash as the RC4-HMAC key, and receive a real TGT signed by the real krbtgt.&lt;/p&gt;
&lt;p&gt;The economic effect is large. Pass-the-Hash gets you NTLM-based services -- SMB, RPC, and any protocol over them. Overpass-the-Hash gets you the entire Kerberos surface: Kerberos-only services, services that require Kerberos for delegation, services with NTLM disabled at the GPO level. Same NT hash. Different downstream protocol. Strictly larger attack surface.&lt;/p&gt;

The technique of presenting a stolen NT hash to the KDC as the user&apos;s long-term RC4-HMAC Kerberos key (per RFC 4757 [@rfc-4757]), obtaining a real TGT signed by the real krbtgt, and operating as a real Kerberos client for the ticket&apos;s lifetime. Tool of record: Mimikatz `sekurlsa::pth /user: /domain: /ntlm: /run:` and Rubeus `asktgt /user: /rc4:`. Per Sean Metcalf&apos;s adsecurity.org reference, the technique is named &quot;over&quot; because the hash is promoted one notch up the protocol stack from NTLM into Kerberos [@adsec-mimikatz-p556] [@adsec-kerberos-p2293].

sequenceDiagram
    participant Attacker
    participant KDC
    participant Service as Kerberos service
    Note over Attacker: Holds NT hash for user (e.g. from sekurlsa::logonpasswords)
    Attacker-&amp;gt;&amp;gt;KDC: AS-REQ with PA-ENC-TIMESTAMP encrypted under RC4-HMAC(NT hash)
    KDC-&amp;gt;&amp;gt;KDC: Verify PA-ENC-TIMESTAMP decrypts cleanly
    KDC--&amp;gt;&amp;gt;Attacker: AS-REP with real TGT signed by krbtgt
    Attacker-&amp;gt;&amp;gt;KDC: TGS-REQ for Service
    KDC--&amp;gt;&amp;gt;Attacker: TGS-REP service ticket
    Attacker-&amp;gt;&amp;gt;Service: AP-REQ authenticate as user
    Service--&amp;gt;&amp;gt;Attacker: Access granted
&lt;p&gt;The naming has its own story. The Mimikatz capability is Delpy&apos;s; the term &quot;Overpass-the-Hash&quot; and the taxonomic framing that distinguishes it from straight Pass-the-Hash spread through the practitioner community via Sean Metcalf&apos;s adsecurity.org reference [@adsec-mimikatz-p556] and the Duckwall + Delpy Black Hat USA 2014 talk and whitepaper [@infocondb-bh2014-duckwall] [@duckwall-delpy-bh2014-wp]. The earliest archived snapshot of the adsecurity.org reference is October 1, 2014; the talk timestamp is August 7, 2014. The two sources are essentially contemporaneous, and Metcalf&apos;s later &quot;Red vs. Blue&quot; Black Hat USA 2015 whitepaper consolidates the practitioner taxonomy [@metcalf-bh2015-red-vs-blue].&lt;/p&gt;
&lt;p&gt;The &quot;Overpass&quot; coinage is a deliberate semantic argument that the technique is one notch &lt;em&gt;above&lt;/em&gt; Pass-the-Hash on the protocol stack: the NT hash, which began life as an NTLM response key, is being promoted into Kerberos as a long-term encryption key. The naming credit is socially distributed -- Metcalf, Delpy, Duckwall, and Mimikatz&apos;s own command group all carry traces of it -- so this article uses Metcalf&apos;s reference as the canonical practitioner explainer rather than as a single inventor citation.&lt;/p&gt;
&lt;p&gt;The DigiNotar incident in September 2011 is the first publicly attributed criminal use of Mimikatz, four months after Delpy&apos;s first public release. The Dutch certificate authority DigiNotar -- founded 1998, acquired by VASCO in January 2011, hacked in June 2011, declared bankrupt in September 2011 [@wikipedia-diginotar] -- was used to issue hundreds of fraudulent certificates that were then used in man-in-the-middle attacks on Iranian Gmail users [@wikipedia-diginotar] [@fox-it-operation-black-tulip].&lt;/p&gt;
&lt;p&gt;Greenberg&apos;s Wired profile records that Delpy was told by the breach investigators that Mimikatz had been used during the intrusion [@wired-greenberg-mimikatz]. The single-source attribution warrants a hedge -- Greenberg&apos;s source is Delpy himself, quoting investigators -- but the underlying breach timeline is solid.&lt;/p&gt;

The decision to open-source Mimikatz on April 6, 2014 is dated by the GitHub repository banner: `mimikatz 2.0 alpha (x86) release &quot;Kiwi en C&quot; (Apr  6 2014 22:02:03)` [@mimikatz-github]. The precipitating event, as Delpy told Wired, was a trip to Moscow: he returned to his hotel room to find a stranger at his laptop; a second man approached him in the lobby that evening and demanded source code on a USB stick. He decided defenders needed the source as much as the attackers already did, and pushed it to GitHub when he got home [@wired-greenberg-mimikatz].
&lt;p&gt;By 2014, the credential-replay family had three generations -- Pass-the-Hash, Pass-the-Ticket, Overpass-the-Hash -- and Microsoft&apos;s only documented response was a forty-page PDF. The next section is what that PDF said, and why documentation alone cannot end an attack class.&lt;/p&gt;
&lt;h2&gt;5. Documentation Is Not Defense&lt;/h2&gt;
&lt;p&gt;By December 2012, Microsoft had a problem. Duckwall and Campbell had just shipped a Black Hat USA paper titled &quot;Still Passing the Hash 15 Years Later&quot; [@duckwall-campbell-bh2012]. Mimikatz was eighteen months old. The institutional position that Pass-the-Hash was a &quot;post-compromise issue&quot; -- the line Microsoft had held since 1997 -- was no longer survivable in public.&lt;/p&gt;
&lt;p&gt;The institutional response came in two waves. &lt;em&gt;Mitigating Pass-the-Hash Attacks and Other Credential Theft&lt;/em&gt;, version 1, shipped in late 2012 (most practitioner secondaries place it in December 2012; no primary Microsoft URL with a verifiable v1 timestamp survives today).&lt;/p&gt;
&lt;p&gt;Version 2 followed in July 2014, extending the v1 playbook with the new defensive surfaces that shipped in Windows 8.1 and Windows Server 2012 R2: &lt;a href=&quot;https://paragmali.com/blog/who-is-allowed-to-log-in-where-the-kdc-side-answer-to-creden/&quot; rel=&quot;noopener&quot;&gt;Protected Users&lt;/a&gt; as a deployable security group, Restricted Admin RDP as a default-available feature, LSA Protection (RunAsPPL) as a registry-toggleable defense, and Authentication Policies and Silos as KDC-side restrictions [@ms-download-mitigating-pth-v2]. The two whitepapers are the closest thing the industry got to an institutional Microsoft acknowledgment that Pass-the-Hash was a load-bearing operational problem requiring a defensive playbook rather than a patch.&lt;/p&gt;
&lt;p&gt;What did the playbook recommend? Three orthogonal stopgaps, each with a published bypass.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Protected Users&lt;/strong&gt; (Windows Server 2012 R2). A security group whose membership bans, on the DC side, NTLM authentication, DES and RC4 Kerberos pre-authentication, and Kerberos unconstrained delegation; and, on the device side, NTLM caching of the user&apos;s plaintext credentials or NTOWF and Kerberos DES/RC4 long-term keys. Member TGTs are capped at 240 minutes (four hours) with no renewal [@ms-protected-users]. Documented bypasses: requires explicit opt-in per account, breaks any service that depended on unconstrained delegation, does not apply to computer accounts or service accounts by default, and has no effect on Kerberos AES-key extraction from LSASS (since AES keys are not banned; only RC4 is).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Restricted Admin RDP&lt;/strong&gt; (introduced in Windows 8.1 / Server 2012 R2 RTM, October 2013; backported to Windows 7 / Server 2008 R2 / Windows 8 / Server 2012 by KB2871997 on May 13, 2014 [@ms-kb2871997-may2014]). An opt-in RDP mode that authenticates to the target without sending credentials, so a compromised target cannot harvest the RDP user&apos;s hash from its own LSASS. Documented bypass: opt-in per session, applies only to RDP, leaves SMB, WMI, and RPC unprotected. And it &lt;em&gt;enables&lt;/em&gt; Pass-the-Hash for RDP -- the BloodHound &lt;code&gt;CanRDP&lt;/code&gt; edge documents the abuse path with the exact Mimikatz command for injecting a stolen NT hash into &lt;code&gt;mstsc.exe /restrictedadmin&lt;/code&gt; [@bloodhound-canrdp].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LSA Protection / RunAsPPL&lt;/strong&gt; (Windows 8.1). A registry toggle that marks LSASS as a &lt;a href=&quot;https://paragmali.com/blog/protected-process-light-when-the-administrator-isnt-enough/&quot; rel=&quot;noopener&quot;&gt;Protected Process Light&lt;/a&gt;, so non-PPL processes (including unsigned admin tools) cannot open it with &lt;code&gt;PROCESS_VM_READ&lt;/code&gt;. Documented bypass: any signed kernel driver -- including loadable third-party drivers -- can still read PPL memory, and an attacker with local admin can load such a driver. The itm4n analysis includes the verbatim Mimikatz output where &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; returns access-denied against a PPL-marked LSASS, and shows that an attacker who loads a signed driver via the BYOVD pattern (&quot;bring your own vulnerable driver&quot;) or escalates to kernel mode bypasses the marking. itm4n&apos;s framing -- &quot;Credential Guard and LSA Protection are actually complementary&quot; [@itm4n-lsass-runasppl] -- is also the prediction: PPL is part of the answer, but only when paired with the architectural pivot still to come.&lt;/p&gt;

A Windows Server 2012 R2 security group whose membership applies a set of restrictions, enforced jointly by the device and the domain controller, that block the most commonly extracted long-term credential material: no NTLM, no Kerberos RC4 or DES pre-auth, no unconstrained delegation, no NT-hash caching, and a 240-minute TGT lifetime with no renewal [@ms-protected-users].
&lt;p&gt;The structural point is this. Documentation tells administrators &lt;em&gt;what to do&lt;/em&gt;. It does not prevent the underlying LSASS-resident credential extraction. Every defense documented in v1 and v2 of the Mitigating-PtH whitepapers is bypassable, with a known and published technique, on any system where the attacker already has local administrator -- and local administrator is exactly what Pass-the-Hash exploitation &lt;em&gt;already implies&lt;/em&gt;. The defender&apos;s win condition is to keep the attacker from ever getting to local admin in the first place; once they have it, every documented mitigation is a speed bump rather than a wall.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 2012-2014 era&apos;s load-bearing failure mode was assuming that telling administrators where credentials &lt;em&gt;should&lt;/em&gt; live would prevent extraction from where they &lt;em&gt;do&lt;/em&gt; live. Protected Users, Restricted Admin RDP, RunAsPPL, and Authentication Silos are all useful, and stacked together they raise the cost of post-admin exploitation. None of them moves the credential out of the address space the attacker can read.&lt;/p&gt;
&lt;/blockquote&gt;

A common secondary characterisation cites a &quot;v3 2017&quot; of the whitepaper alongside v1 and v2. That document does not exist in Microsoft Download Center ID 36036; the page lists Version 2.0; the 2023 Wayback snapshot of the same Download Center page records Date Published 7/7/2014, while the live page now shows a 2024 republication date for the same Version 2.0 PDF without a version bump [@ms-download-mitigating-pth-v2]. The Download Center page carries v2 metadata only -- v1&apos;s late-2012 date is sourced through contemporary practitioner literature rather than a primary Microsoft timestamp. After 2014 the post-v2 institutional documentation moves to the Microsoft Learn Credential Guard page rather than to a third whitepaper revision -- a structural choice, because by 2015 the architectural answer has shifted from prose to code.
&lt;p&gt;By mid-2014 Microsoft&apos;s institutional position was that the protocol-level fix was unavailable and the architectural answer would need to &lt;em&gt;relocate the credentials&lt;/em&gt;. If credentials cannot stay in LSASS where every admin process can read them, the credentials have to be moved to a place admin processes cannot read. That insight produces Credential Guard.&lt;/p&gt;
&lt;h2&gt;6. Credential Guard and the Architectural Pivot&lt;/h2&gt;
&lt;p&gt;On July 29, 2015, Microsoft shipped Windows 10 Enterprise [@ms-lifecycle-w10-enterprise]. Hidden in the RTM build was the first defense in the credential-replay lineage that wasn&apos;t documentation: hardware-rooted isolation. They called it Credential Guard.&lt;/p&gt;
&lt;p&gt;The architecture is worth unpacking carefully, because every later generation of the family is best read as &quot;what does this attack do to the assumptions Credential Guard makes?&quot;&lt;/p&gt;
&lt;p&gt;Credential Guard runs on top of Virtualization-Based Security. The Windows hypervisor partitions user mode into two virtual trust levels. VTL0 is the normal user partition: normal user-mode processes, including the normal LSASS, and the normal kernel. VTL1 is the isolated user partition: a small set of &lt;em&gt;trustlets&lt;/em&gt;, signed user-mode processes the hypervisor protects from VTL0 inspection. Credential Guard&apos;s trustlet is LSAISO (&quot;LSA Isolated&quot;), a stripped-down clone of the LSA credential cache holding the material Microsoft wants out of VTL0. Hypervisor-enforced Code Integrity (HVCI) below enforces W^X on the VTL0 kernel, blocking kernel-mode bypasses that would otherwise read VTL1 memory directly.&lt;/p&gt;

The Windows architecture that runs a Type-1 hypervisor below the normal Windows kernel and partitions user mode into VTL0 (the normal partition) and VTL1 (the isolated partition). VTL1 hosts trustlets that the hypervisor protects from VTL0 inspection, even from kernel-mode VTL0 code. VBS is the substrate for Credential Guard, HVCI, the System Guard secure-launch chain, and the secure kernel.

The Windows feature that relocates NT hashes, Kerberos TGT session keys, and &quot;credentials stored by applications as domain credentials&quot; from the in-VTL0 LSASS to the in-VTL1 LSAISO trustlet, so that the credential cache is unreadable from any VTL0 process or driver. Shipped in Windows 10 RTM (July 2015); default-enabled on hardware-eligible domain-joined non-DC systems in Windows 11 22H2 (September 2022) [@ms-learn-credential-guard].

The isolated-user-mode LSA process (`lsaiso.exe`) that holds Credential Guard&apos;s protected credential material. Runs in VTL1, unreadable from VTL0 kernel or user processes. Communicates with the VTL0 LSASS through a small RPC surface for authorised authentication operations only.
&lt;p&gt;What does Credential Guard isolate? The Microsoft Learn page is unambiguous: &quot;Credential Guard prevents credential theft attacks by protecting NTLM password hashes, Kerberos Ticket Granting Tickets (TGTs), and credentials stored by applications as domain credentials.&quot; [@ms-learn-credential-guard] Those three categories are also the three categories the previous three generations of the family targeted. Pass-the-Hash hits NTLM password hashes. Pass-the-Ticket hits Kerberos TGTs. Overpass-the-Hash hits NTLM password hashes promoted into Kerberos. Credential Guard moves all three out of VTL0 LSASS into VTL1 LSAISO. On a hardware-eligible domain-joined Windows 10/11 system with Credential Guard enabled, all three attacks return empty buffers.&lt;/p&gt;
&lt;p&gt;The institutional importance of the change is that under Microsoft&apos;s own &lt;em&gt;Windows Security Servicing Criteria&lt;/em&gt;, Credential Guard is a &lt;em&gt;security boundary&lt;/em&gt; -- which means a bypass is a CVE-class vulnerability rather than a documentation gap.&lt;/p&gt;
&lt;p&gt;The criteria&apos;s load-bearing definitions: &quot;A security boundary provides a logical separation between the code and data of security domains with different levels of trust&quot; and &quot;Does the vulnerability violate the goal or intent of a security boundary or a security feature?&quot; [@msrc-windows-servicing-criteria] Pre-2015 Pass-the-Hash defenses were documentation; Credential Guard is the first defense the criteria treats as CVE-class under the boundary &quot;admin -&amp;gt; VBS (LSAISO trustlet).&quot;&lt;/p&gt;

flowchart TD
    subgraph VTL0[VTL0 normal partition]
        A[User processes]
        B[LSASS]
        K[VTL0 kernel]
    end
    subgraph VTL1[VTL1 isolated partition]
        L[LSAISO trustlet]
        SK[Secure kernel]
    end
    H[Hypervisor]
    A --&amp;gt; B
    K --&amp;gt; B
    B -- authorised RPC only --&amp;gt; L
    H --&amp;gt; VTL0
    H --&amp;gt; VTL1
    SK --&amp;gt; L
    K -. blocked by HVCI .-&amp;gt; L
&lt;p&gt;What does Credential Guard &lt;em&gt;not&lt;/em&gt; isolate? This is the load-bearing question for the rest of the article. The same Microsoft Learn page enumerates four caveats, each verbatim.&lt;/p&gt;
&lt;p&gt;First, the Active Directory database and the SAM. &quot;Credential Guard doesn&apos;t provide protections for the Active Directory database or the Security Accounts Manager (SAM).&quot; [@ms-learn-credential-guard] This is the &lt;a href=&quot;https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/&quot; rel=&quot;noopener&quot;&gt;DCSync&lt;/a&gt; gap: an attacker with the right replication privileges can ask a DC to hand over every hash in the directory, and Credential Guard cannot intervene because the data is being released through a legitimate, authorised API rather than being read from LSASS.&lt;/p&gt;
&lt;p&gt;Second, domain controllers. &quot;Enabling Credential Guard on domain controllers isn&apos;t recommended. Credential Guard doesn&apos;t provide any added security to domain controllers.&quot; [@ms-learn-credential-guard] The KDC must read the krbtgt account&apos;s long-term key in cleartext to issue tickets; the architectural exception is intrinsic to Kerberos rather than a Microsoft oversight.&lt;/p&gt;
&lt;p&gt;Third, application credentials outside the &quot;domain credentials&quot; scope. Certificate private keys held by CryptoAPI key containers, third-party authentication package secrets, and -- the one this article eventually argues is the most consequential -- the Primary Refresh Token material held by the CloudAP authentication plug-in, are all out of scope by construction.&lt;/p&gt;
&lt;p&gt;Fourth, and most importantly, the institutional acknowledgment of the supersession pattern. Microsoft Learn reproduces it verbatim on the same page, the prophecy the rest of this article spends its time documenting being fulfilled:&lt;/p&gt;

While Credential Guard is a powerful mitigation, persistent threat attacks will likely shift to new attack techniques, and you should also incorporate other security strategies and architectures. -- Microsoft Learn, *Credential Guard overview* [@ms-learn-credential-guard]
&lt;p&gt;That sentence, written about the 2015 Credential Guard architecture, accurately predicts the 2021-2022 shift to Pass-the-Certificate and the 2020-present shift to Pass-the-PRT. It is Microsoft&apos;s own structural prediction that the family will continue to evolve to the next artefact Credential Guard&apos;s verbatim scope does not cover. The rest of this article reads as the unfolding of that prediction.&lt;/p&gt;

The Kerberos KDC must read the krbtgt account&apos;s long-term key to encrypt the TGT issued in every AS-REP. That key has to be available to the LSA process in cleartext, on every DC, on every ticket issuance, by protocol. Putting krbtgt behind LSAISO would mean issuing every TGT through an inter-trust-level RPC call -- a non-trivial performance penalty on every authentication in an Active Directory forest -- and would not actually close the architectural gap, because the trustlet itself would still need to do the cleartext work that LSASS does today. The exception is honest about an architectural reality rather than concealing it.
&lt;p&gt;PPL and Credential Guard are &lt;em&gt;complementary&lt;/em&gt;, not alternatives. itm4n&apos;s analysis [@itm4n-lsass-runasppl] makes the case carefully: RunAsPPL raises the bar from &quot;any admin process can read LSASS&quot; to &quot;any signed driver can read LSASS,&quot; and Credential Guard closes the signed-driver bypass with hardware-rooted hypervisor isolation. They stack. The 2026 best-practice Windows endpoint has both turned on.&lt;/p&gt;
&lt;p&gt;The default-enablement window shows how long this took to land. Credential Guard shipped enabled-by-policy in Windows 10 RTM in 2015, but did not become &lt;em&gt;default-enabled on hardware-eligible domain-joined non-DC systems&lt;/em&gt; until Windows 11 22H2 in September 2022 [@ms-learn-credential-guard]. Seven years of uneven deployment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Four residuals from the Microsoft Learn page: the Active Directory database and the SAM are out of scope; domain controllers are out of scope by recommendation; application credentials outside the &quot;domain credentials&quot; category (certificates, CloudAP material, third-party authentication packages) are out of scope by construction; and persistent threats are &lt;em&gt;expected&lt;/em&gt; to shift to new attack techniques. Each residual maps to a later generation of this article: AD database -&amp;gt; DCSync; certificates -&amp;gt; Pass-the-Certificate; CloudAP -&amp;gt; Pass-the-PRT.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Each new credential type needs its own isolation boundary. Credential Guard isolates NT hashes and TGT session keys. It does not isolate certificate private keys, because in 2015 nobody was replaying certificates at scale. And it does not isolate the Primary Refresh Token, because in 2015 the Primary Refresh Token did not yet exist.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Each new credential type needs its own isolation boundary. The pattern is reusable but does not transfer automatically -- and the gap between &quot;what fits in the boundary&quot; and &quot;what credentials Windows actually uses&quot; is exactly the territory where the next attack generation grows.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;7. Pass-the-Certificate: The Predictable Response&lt;/h2&gt;
&lt;p&gt;If the NT hash is isolated and RC4-HMAC is banned, what is the next long-term credential Windows accepts? The answer was hiding in plain sight: every Active-Directory-integrated enterprise had been running Microsoft&apos;s PKI since 2008, and almost every PKI deployment had at least one template-level catastrophe.&lt;/p&gt;
&lt;p&gt;On June 17, 2021, Will Schroeder and Lee Christensen posted &quot;Certified Pre-Owned&quot; on Medium, with the accompanying 143-page whitepaper [@specterops-certified-pre-owned] [@specterops-certified-pre-owned-pdf]. The post named ESC1 through ESC8 in a single document, with paired DETECT and PREVENT recommendations, and shipped three pieces of tooling at the same Black Hat USA 2021 cycle: Certify (offensive enrollment), ForgeCert (golden-certificate forging using a stolen CA private key), and PSPKIAudit (defensive enumeration). The Medium post&apos;s tone was unsubtle:&lt;/p&gt;

Of note, nearly every environment with AD CS that we&apos;ve examined for domain escalation misconfigurations has been vulnerable. It&apos;s hard for us to overstate what a big deal these issues are. -- Will Schroeder and Lee Christensen, *Certified Pre-Owned* [@specterops-certified-pre-owned]
&lt;p&gt;The &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;ESC catalog&lt;/a&gt; organises certificate misconfigurations by the abuse primitive they enable. ESC1 is the canonical example: a published certificate template that allows the enrollee to supply the Subject Alternative Name, contains a client-authentication Extended Key Usage, has permissive enrollment rights, and has no effective approval gates.&lt;/p&gt;
&lt;p&gt;An attacker who can enroll for such a template requests a certificate naming a victim principal -- say, the domain administrator -- in the SAN. The certificate&apos;s private key is now the attacker&apos;s. PKINIT-authenticate to the KDC with that certificate, and the KDC issues a TGT for the named principal. Domain escalation, in three commands.&lt;/p&gt;

Microsoft&apos;s enterprise PKI. Issues X.509 certificates from administrator-defined templates that pin a certificate&apos;s permitted uses (Extended Key Usages), its enrollment authorisation rules, its subject and SAN generation policy, and its revocation behaviour. Ships as a Windows Server role; deployed in essentially every Active-Directory-integrated enterprise.

Kerberos pre-authentication using a certificate&apos;s private key in place of a long-term symmetric key. Specified by RFC 4556 (L. Zhu and B. Tung, Microsoft and Aerospace, June 2006) [@rfc-4556]. The certificate&apos;s UPN SAN (or its dNSHostName for computer accounts) maps the certificate to the principal whose TGT the KDC will issue. PKINIT is the protocol surface most commonly exercised by Pass-the-Certificate against domain controllers that support certificate-based authentication.

The Windows TLS implementation. Supports TLS client-certificate authentication, which authenticated LDAPS uses. When a domain controller does not support PKINIT (Schroeder + Christensen documented this case in the original catalog; AlmondOffSec built tooling for it), an attacker can authenticate to LDAPS over Schannel with a stolen client certificate and perform high-privilege LDAP operations without traversing the KDC.

The technique of authenticating to Active Directory with a stolen X.509 certificate&apos;s private key, via PKINIT to the KDC or via Schannel client-certificate authentication to LDAPS. Named in this form by Yannick Méheut&apos;s PassTheCert tool and blog post (May 2022) [@almondoffsec-passthecert-github] [@almondoffsec-passthecert-blog], though the technique class was catalogued by Schroeder and Christensen eleven months earlier [@specterops-certified-pre-owned]. Tool of record: Certify (C#), Certipy (Python, ESC1-ESC16 [@certipy-wiki-privesc]), and Rubeus PKINIT mode.

sequenceDiagram
    participant Atk as Attacker (user)
    participant CA as Enterprise CA
    participant KDC
    Atk-&amp;gt;&amp;gt;CA: Enrol for template ESC1, SAN field set to Domain Administrator
    CA--&amp;gt;&amp;gt;Atk: X.509 certificate plus private key
    Note over Atk: Now holds a certificate naming the victim principal
    Atk-&amp;gt;&amp;gt;KDC: AS-REQ with PKINIT pre-auth using the stolen private key
    KDC-&amp;gt;&amp;gt;KDC: Validate certificate, map SAN to victim principal
    KDC--&amp;gt;&amp;gt;Atk: AS-REP with TGT for victim principal
    Atk-&amp;gt;&amp;gt;KDC: TGS-REQ for any service
    KDC--&amp;gt;&amp;gt;Atk: TGS-REP service ticket
&lt;p&gt;The CVE-class case lands on May 10, 2022. Oliver Lyak of IFCR discloses Certifried, CVE-2022-26923, an Active Directory Domain Services elevation-of-privilege vulnerability in which the combination of three Microsoft defaults -- &lt;code&gt;ms-DS-MachineAccountQuota = 10&lt;/code&gt; (any authenticated user can add up to 10 computer accounts to the domain), the default Machine template (which a computer account can enroll for), and the KDC&apos;s permissive &lt;code&gt;dNSHostName&lt;/code&gt;-to-SAN binding logic -- lets any authenticated user obtain a certificate for any computer account in the forest, including domain controllers.&lt;/p&gt;
&lt;p&gt;PKINIT-authenticate as a domain controller, and the KDC issues you a TGT for the DC; from there, DCSync extracts the krbtgt key and the domain is yours. Domain escalation from any authenticated user, with the only required misconfiguration being &lt;em&gt;Microsoft&apos;s defaults&lt;/em&gt; [@nvd-cve-2022-26923] [@semperis-cve-2022-26923].&lt;/p&gt;
&lt;p&gt;The defensive response shipped the same day. Microsoft published KB5014754 on May 10, 2022 -- coordinated disclosure, with the patch shipping in the same window as the CVE -- introducing a new X.509 extension &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt; (OID &lt;code&gt;1.3.6.1.4.1.311.25.2&lt;/code&gt;) that carries the requesting principal&apos;s SID at certificate issuance.&lt;/p&gt;
&lt;p&gt;The KDC&apos;s new strong-mapping logic refuses certificates that fail one of four conditions: the SID extension is present and matches; an issuer-serial mapping is present; a Subject Key Identifier mapping is present; or a SHA1-public-key mapping is present. The KB&apos;s load-bearing sentence: &quot;In Full Enforcement mode, if a certificate fails the strong (secure) mapping criteria (see Certificate mappings), authentication will be denied.&quot; [@ms-kb5014754]&lt;/p&gt;
&lt;p&gt;The KB5014754 change-log preserves a forensic artefact of the coordinated-disclosure timeline that is easy to miss. The current change-log row reads, verbatim: &quot;9/10/2025 - Corrected the Enforcement mode date from September 10, 2025, to September 9, 2025.&quot; [@ms-kb5014754] An off-by-one date correction, captured in the public KB. The kind of detail that only shows up when a small team has had to ship a date repeatedly against a multi-year audit-to-enforcement schedule.&lt;/p&gt;
&lt;p&gt;The enforcement timeline tells you how long even a CVE-class fix took to drive through deployment. Audit mode (May 10, 2022). Enforcement mode with a registry escape that admins could use to revert to compatibility (February 11, 2025). Final cutover with no escape (September 9, 2025) [@ms-kb5014754]. Three years and four months between the patch and the day Microsoft stopped accepting non-strong certificate mappings. Faster than the Credential Guard default-enablement window, but still measured in years.&lt;/p&gt;
&lt;p&gt;The naming history deserves a disambiguation. The &lt;em&gt;catalog&lt;/em&gt; -- ESC1 through ESC8, the full taxonomy of AD CS misconfigurations -- is Schroeder and Christensen, June 2021 [@specterops-certified-pre-owned]. The &lt;em&gt;wire-level technique name&lt;/em&gt; &quot;Pass-the-Certificate&quot; is popularised by AlmondOffSec&apos;s PassTheCert PoC (Yannick Méheut, May 4, 2022), which targets LDAP/S via Schannel client-cert authentication when PKINIT is unavailable, as a fallback path for environments where domain controllers do not support certificate-based Kerberos pre-authentication [@almondoffsec-passthecert-github] [@almondoffsec-passthecert-blog]. The blog post documents the &lt;code&gt;KDC_ERR_PADATA_TYPE_NOSUPP&lt;/code&gt; error path that diverts the PKINIT-blocked attacker into Schannel.&lt;/p&gt;
&lt;p&gt;The AlmondOffSec blog post acknowledges the social attribution of the term: &quot;Note for Googlers: this tool extends the notion of Pass the Certificate, thus dubbed by @_nwodtuhs in his Twitter thread on AD CS and PKINIT.&quot; [@almondoffsec-passthecert-blog] The technique name is socially attributed; the catalog framing is editorial.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A common shorthand says that KB5014754 bound NTOWFs to Kerberos, and that this is what forced attackers to shift to certificates. That arrow runs backwards in time. KB5014754 is the &lt;em&gt;response&lt;/em&gt; to Certifried, not the cause of Pass-the-Certificate. The technique class was catalogued by Schroeder and Christensen in June 2021, eleven months before KB5014754 shipped, and the PassTheCert tool that gave the technique its wire-level name appeared six days before Certifried&apos;s disclosure. The shift to certificates happened because certificates were the next long-term credential type Credential Guard did not isolate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What does KB5014754 actually close? Three specific CVEs in the Certifried family: CVE-2022-26923 (the original SID-spoof Certifried disclosure), CVE-2022-26931 (UPN / sAMAccountName collision spoof), and CVE-2022-34691 (the certificate-pre-dating-account-creation case) [@ms-kb5014754]. What does it &lt;em&gt;not&lt;/em&gt; close? The broader ESC2 through ESC8 catalog, which is administrative hardening rather than CVE-class control. And it does not close ESC9 through ESC16, which were enumerated &lt;em&gt;after&lt;/em&gt; KB5014754 shipped and include cases like the &lt;code&gt;CT_FLAG_NO_SECURITY_EXTENSION&lt;/code&gt; template flag that &lt;em&gt;exempts&lt;/em&gt; a template from the very SID extension the patch introduced [@specterops-certs-patches-2022] [@certipy-wiki-privesc].&lt;/p&gt;
&lt;p&gt;The current state of the catalog: as of the 2025 Certipy 5.x documentation, ESC1 through ESC16 is the practitioner enumeration, with each technique characterised by a template-level, ACL-level, CA-administrator-level, NTLM-relay-level, SID-extension-level, or mapping-level abuse primitive [@certipy-wiki-privesc]. Microsoft Defender for Identity&apos;s certificates posture assessment tracks nine distinct ESC numbers as of the 2025 documentation -- ten posture assessments, because ESC4 owner and ESC4 ACL are tracked as separate sub-cases (ESC1, ESC2, ESC3, ESC4 owner, ESC4 ACL, ESC6 preview, ESC7, ESC8, ESC11, ESC15) [@ms-defender-id-certs]. Same pattern as Pass-the-Hash in 2012-2014: documentation tells administrators what to do; the structural exposure is downstream of how each enterprise built its templates years earlier.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ESC ID&lt;/th&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Closed by KB5014754&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ESC1&lt;/td&gt;
&lt;td&gt;Template -- enrollee supplies SAN, client-auth EKU, permissive enrollment&lt;/td&gt;
&lt;td&gt;Partial: SID extension binds requester at issuance; ESC1 still works if the SID extension is absent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC2&lt;/td&gt;
&lt;td&gt;Template -- enrollee supplies SAN, Any-Purpose or no EKU&lt;/td&gt;
&lt;td&gt;No -- administrative hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC3&lt;/td&gt;
&lt;td&gt;Template -- Certificate Request Agent enrollment-agent abuse&lt;/td&gt;
&lt;td&gt;No -- administrative hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC4&lt;/td&gt;
&lt;td&gt;ACL -- writeable template configuration&lt;/td&gt;
&lt;td&gt;No -- administrative hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC6&lt;/td&gt;
&lt;td&gt;CA -- &lt;code&gt;EDITF_ATTRIBUTESUBJECTALTNAME2&lt;/code&gt; flag set on the CA&lt;/td&gt;
&lt;td&gt;No -- CA-level hardening (was MS22-23, separately patched)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC8&lt;/td&gt;
&lt;td&gt;NTLM relay -- HTTP enrolment endpoints reachable from low-privilege contexts&lt;/td&gt;
&lt;td&gt;No -- relay-defence hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC9&lt;/td&gt;
&lt;td&gt;Template -- &lt;code&gt;CT_FLAG_NO_SECURITY_EXTENSION&lt;/code&gt; exempts template from the SID extension&lt;/td&gt;
&lt;td&gt;No -- by design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC11&lt;/td&gt;
&lt;td&gt;NTLM relay -- ICPR RPC endpoint without sign / seal&lt;/td&gt;
&lt;td&gt;No -- relay-defence hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC16&lt;/td&gt;
&lt;td&gt;CA -- security-extension disabled at the CA level&lt;/td&gt;
&lt;td&gt;No -- CA-level hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Table 1. A representative slice of the ESC1-ESC16 catalog showing what KB5014754 closes and what remains administrative hardening [@specterops-certify-wiki] [@certipy-wiki-privesc] [@specterops-certs-patches-2022].&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;KB5014754 is a CVE-class fix for one sub-case. The broader ADCS catalog is administrative hardening. And the &lt;em&gt;next&lt;/em&gt; credential type -- the one that defeats Credential Guard, Protected Users, and KB5014754 simultaneously -- was already shipping in commodity Mimikatz code by August 2020.&lt;/p&gt;
&lt;h2&gt;8. Pass-the-PRT: The CloudAP Frontier&lt;/h2&gt;
&lt;p&gt;By August 2020, Microsoft had two architectural defenses against credential replay that the security industry actually trusted: Credential Guard for local Active Directory credentials, and (eighteen months later) KB5014754 for the certificate-replay class. Then a Dutch security researcher named Dirk-jan Mollema published a 21-minute read that broke both, in the same paragraph, by stealing a different credential type.&lt;/p&gt;
&lt;p&gt;The credential is the &lt;a href=&quot;https://paragmali.com/blog/inside-the-primary-refresh-token-the-cryptographic-seam-betw/&quot; rel=&quot;noopener&quot;&gt;Primary Refresh Token&lt;/a&gt;. The two foundational write-ups are Mollema&apos;s &quot;Abusing Azure AD SSO with the Primary Refresh Token&quot; [@mollema-prt-abusing] and its follow-on &quot;Digging further into the Primary Refresh Token&quot; [@mollema-prt-digging], both posted in August 2020. The second post is the single most-cited primary source in the fifth generation of the family. Read it once and you understand why Pass-the-PRT is structurally different from everything that came before.&lt;/p&gt;
&lt;p&gt;A PRT is a JSON Web Token refresh token issued by Microsoft Entra ID (formerly Azure AD) to Entra-joined or Hybrid-joined Windows devices, paired with a session key (HMAC-SHA256 secret) and bound to a device key registered at device join.&lt;/p&gt;
&lt;p&gt;The Microsoft Entra documentation describes the artefact precisely: &quot;A Primary Refresh Token (PRT) is a key artifact of Microsoft Entra authentication ... Once issued, a PRT is valid for 90 days and is continuously renewed as long as the user actively uses the device.&quot; [@ms-entra-concept-prt] On Windows the PRT is renewed every four hours during sign-in. The device-key registration binds the PRT to the device that owns it -- and is what an attacker has to work around to use a stolen PRT on a different device.&lt;/p&gt;

The Microsoft Entra-issued long-lived refresh token for SSO on Entra-joined or Hybrid-joined Windows devices. Carries a session key (HMAC-SHA256) used to sign per-request `x-ms-RefreshTokenCredential` cookies, and binds to a device transport key registered at device join. Default lifetime is 90 days with sliding renewal as long as the user actively uses the device; an inactivity timeout governs when an idle PRT must be re-acquired [@ms-entra-concept-prt]. The PRT is the load-bearing artefact for Single Sign-On to every Entra-integrated resource the device&apos;s user can reach.
&lt;p&gt;The PRT default lifetime is 90 days per the Microsoft Entra documentation, with renewal every four hours during Windows sign-in [@ms-entra-concept-prt]. The 14-day figure that sometimes appears in secondary references is the inactivity timeout on certain device states, not the PRT lifetime itself; this article uses the Microsoft Entra documentation&apos;s value to avoid the conflation.&lt;/p&gt;
&lt;p&gt;Where the PRT &lt;em&gt;lives&lt;/em&gt; is what makes the rest of the architecture work -- and what makes it vulnerable. The PRT is &lt;em&gt;hybrid&lt;/em&gt;: issued and revoked cloud-side by Entra ID, stored and used client-side via the &lt;strong&gt;CloudAP&lt;/strong&gt; authentication plug-in, which is loaded into LSASS like any other Windows authentication package.&lt;/p&gt;
&lt;p&gt;The load-bearing structural fact is that CloudAP is &lt;em&gt;in LSASS&lt;/em&gt;, not behind the LSAISO trustlet. Credential Guard&apos;s classical isolation does not extend to the CloudAP plug-in&apos;s working memory, because Credential Guard&apos;s scope is the three credential categories its design predates -- NT hashes, Kerberos TGTs, and &quot;domain credentials&quot; -- and the PRT is none of those [@mollema-prt-abusing].&lt;/p&gt;

The Windows authentication package (`cloudap.dll`, loaded into LSASS) that handles authentication against Microsoft Entra ID for Entra-joined and Hybrid-joined devices. Holds the device&apos;s Primary Refresh Token, its session key, and the derived material used to sign per-request PRT cookies. Sits inside LSASS in VTL0, *not* inside the LSAISO trustlet in VTL1; Credential Guard does not currently extend its isolation to CloudAP&apos;s working memory.
&lt;p&gt;The mechanism, as Mollema and Delpy developed it through the second half of 2020, runs as follows. Mimikatz &lt;code&gt;dpapi::cloudapkd /unprotect&lt;/code&gt; extracts the PRT (the encrypted-by-Entra refresh-token blob) and the session key from CloudAP&apos;s working memory.&lt;/p&gt;
&lt;p&gt;The attacker constructs an &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; JWT carrying the PRT in the &lt;code&gt;refresh_token&lt;/code&gt; claim, &lt;code&gt;is_primary: true&lt;/code&gt;, and a &lt;code&gt;request_nonce&lt;/code&gt; obtained by an unauthenticated POST against the Entra ID v1 token endpoint at &lt;code&gt;https://login.microsoftonline.com/common/oauth2/token&lt;/code&gt; with form-encoded body &lt;code&gt;grant_type=srv_challenge&lt;/code&gt; (the server-challenge nonce pattern used by the ROADtools &lt;code&gt;roadtx prt&lt;/code&gt; reference implementation; the response is a JSON object with a &lt;code&gt;Nonce&lt;/code&gt; field). The signature is HMAC-SHA256 over the JWT under the session key. The completed cookie is presented to &lt;code&gt;login.microsoftonline.com&lt;/code&gt; from any machine, and Entra ID returns access and refresh tokens for any resource the original user can reach. Mollema&apos;s second post describes the collaboration that built the tooling:&lt;/p&gt;

Around the same time Benjamin Delpy took up my &apos;challenge&apos; of recovering PRT data from `lsass` with mimikatz. We combined forces and ended up with tooling that is not only able to extract the PRT and associated cryptographic keys (such as the session key) from memory, but can also use these keys to create new SSO cookies or modify existing ones. -- Dirk-jan Mollema, *Digging further into the Primary Refresh Token* [@mollema-prt-digging]
&lt;p&gt;The operational tooling closed quickly. Mollema&apos;s &lt;code&gt;roadtx prt&lt;/code&gt; (part of ROADtools [@roadtools-github]) automates the full chain end-to-end -- extract the material, mint the cookie, complete the OAuth dance, hand the attacker an access token. The Mimikatz &lt;code&gt;dpapi::cloudapkd&lt;/code&gt; command landed in the open-source repository the same window. Pass-the-PRT moved from research artefact to commodity tooling in months, not years.&lt;/p&gt;

sequenceDiagram
    participant Victim as Victim device (Entra-joined)
    participant Attacker as Attacker device
    participant Entra as login.microsoftonline.com
    Note over Victim: PRT plus session key held by CloudAP in LSASS
    Attacker-&amp;gt;&amp;gt;Victim: mimikatz dpapi::cloudapkd /unprotect
    Victim--&amp;gt;&amp;gt;Attacker: PRT (encrypted blob) plus session key
    Attacker-&amp;gt;&amp;gt;Entra: POST /common/oauth2/token grant_type=srv_challenge (unauthenticated)
    Entra--&amp;gt;&amp;gt;Attacker: request_nonce
    Note over Attacker: Build x-ms-RefreshTokenCredential JWT
    Note over Attacker: Sign HMAC-SHA256 with extracted session key
    Attacker-&amp;gt;&amp;gt;Entra: POST /token with PRT cookie
    Entra--&amp;gt;&amp;gt;Attacker: Access and refresh tokens
    Attacker-&amp;gt;&amp;gt;Attacker: Authenticate to any Entra resource as victim user
&lt;p&gt;Now the analytical core. Pass-the-PRT defeats three Microsoft defenses &lt;em&gt;simultaneously&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;First, &lt;strong&gt;Credential Guard&lt;/strong&gt; is out of scope. The CloudAP material is not an NT hash, not a Kerberos TGT, and not &quot;credentials stored by applications as domain credentials&quot; in the verbatim sense the Credential Guard documentation uses. Credential Guard&apos;s VBS-based isolation does not extend to CloudAP. The defense was designed in 2015 against the three credential types the family had then; the PRT is a credential type the family had not yet evolved into [@ms-learn-credential-guard].&lt;/p&gt;
&lt;p&gt;Second, &lt;strong&gt;KB5014754&lt;/strong&gt; is out of scope. The PRT cookie does not traverse the KDC&apos;s certificate-mapping logic at all; it is a JWT signed by an HMAC and authenticated at the Entra ID token endpoint. The strong certificate mapping that Microsoft drove through five years of audit-to-enforcement timeline has no relevance to a credential that never touches the KDC [@ms-kb5014754].&lt;/p&gt;
&lt;p&gt;Third, &lt;strong&gt;Protected Users&lt;/strong&gt; is out of scope. Protected Users is an Active-Directory-only construct, enforced on Windows Server domain controllers and on AD-joined member devices. Entra ID is a separate identity provider with separate enforcement; the 240-minute TGT cap, the NTLM ban, and the RC4 ban that Protected Users enforces simply do not apply [@ms-protected-users].&lt;/p&gt;
&lt;p&gt;The TPM-sealing finding is where the architectural pattern becomes most precise. Microsoft began sealing the PRT session key to a &lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;TPM-bound key&lt;/a&gt; on TPM-2.0-eligible hardware -- a defense that, in principle, makes the raw session key cryptographically non-exportable. Mollema&apos;s finding in the August 2020 second post is that the seal does not close the attack, because CloudAP holds &lt;em&gt;derived&lt;/em&gt; PRT-cookie-signing material in its own working memory in LSASS, and the attacker only needs the derived material:&lt;/p&gt;

despite the session key of the PRT is stored in the TPM whenever possible, this doesn&apos;t prevent us from extracting the PRT and the required information to create SSO cookies. The result of this is that regardless of whether the PRT is protected by the TPM or not, with Administrator access it is possible to extract the PRT from LSASS and use the PRT on a different device than it was issued to. -- Dirk-jan Mollema, *Digging further into the Primary Refresh Token* [@mollema-prt-digging]
&lt;p&gt;The structural reason the standard hardware-rooted defense pattern does not transfer: the attacker does not need the raw session key out of the TPM. They need only the in-memory derived material CloudAP itself uses to sign the cookies, and that derived material lives in the same address space Credential Guard does not isolate.&lt;/p&gt;
&lt;p&gt;The TPM seals the key. CloudAP uses the key. Whatever CloudAP can read, an attacker with administrator and a memory-access primitive can also read. The defense pattern that worked for NT hashes (move them out of the address space) has not been applied to CloudAP -- and until it is, the TPM seal is a speed bump rather than a wall.&lt;/p&gt;
&lt;p&gt;{`
// Pedagogical demonstration of the JWT structure used in Pass-the-PRT
// cookie minting. Uses placeholder values throughout; no real PRT material.&lt;/p&gt;
&lt;p&gt;const base64url = (buf) =&amp;gt; Buffer.from(buf).toString(&apos;base64&apos;)
  .replace(/=+$/, &apos;&apos;).replace(/\+/g, &apos;-&apos;).replace(/\//g, &apos;_&apos;);&lt;/p&gt;
&lt;p&gt;const header = { alg: &apos;HS256&apos;, ctx: &apos;AAAAAAAA&apos; };
const payload = {
  // The PRT itself, an opaque refresh-token string Entra issued to the
  // device. In a real attack this comes from mimikatz dpapi::cloudapkd.
  refresh_token: &apos;AQABAAAAAAA...redacted...&apos;,
  // Marks this cookie as a primary refresh token cookie.
  is_primary: &apos;true&apos;,
  // Fresh nonce from an unauthenticated POST against the v1 token endpoint
  // at login.microsoftonline.com/common/oauth2/token with form body
  // grant_type=srv_challenge (returns JSON with Nonce field; the canonical
  // server-challenge pattern used by ROADtools roadtx prt).
  request_nonce: &apos;AwABAAEAAAAC...&apos;,
  iat: Math.floor(Date.now() / 1000),
};&lt;/p&gt;
&lt;p&gt;// HMAC-SHA256 over the JWT under the session key recovered from CloudAP.
// Placeholder key for demonstration only.
const sessionKey = Buffer.alloc(32); // 32 bytes of zeros (fake)
const crypto = require(&apos;crypto&apos;);&lt;/p&gt;
&lt;p&gt;const h = base64url(JSON.stringify(header));
const p = base64url(JSON.stringify(payload));
const sig = base64url(
  crypto.createHmac(&apos;sha256&apos;, sessionKey).update(h + &apos;.&apos; + p).digest()
);&lt;/p&gt;
&lt;p&gt;console.log(&apos;Header segment:    &apos; + h);
console.log(&apos;Payload segment:   &apos; + p);
console.log(&apos;Signature segment: &apos; + sig);
console.log();
console.log(&apos;Full PRT cookie: &apos; + h + &apos;.&apos; + p + &apos;.&apos; + sig);
// In a real attack the attacker would now POST this as the
// x-ms-RefreshTokenCredential cookie to login.microsoftonline.com.
`}&lt;/p&gt;
&lt;p&gt;The current partial mitigations are worth enumerating, because none of them closes the gap.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Token Protection&lt;/strong&gt; (a &lt;a href=&quot;https://paragmali.com/blog/who-decided-this-token-is-good-a-field-guide-to-conditional-/&quot; rel=&quot;noopener&quot;&gt;Conditional Access&lt;/a&gt; session control) attempts to ensure that only device-bound sign-in session tokens are accepted at the Entra ID token endpoint for protected resources. The Microsoft Learn page is explicit about both the design intent and the deployment limits: &quot;Token Protection is a Conditional Access session control that attempts to reduce token replay attacks by ensuring only device bound sign-in session tokens, like Primary Refresh Tokens (PRTs), are accepted by Microsoft Entra ID when applications request access to protected resources.&quot; [@ms-entra-token-protection] As of the current documentation the &lt;em&gt;supported resources&lt;/em&gt; are five named applications: Exchange Online, SharePoint Online, Microsoft Teams, Azure Virtual Desktop, and Windows 365. Browser applications are out of scope; &quot;Token Protection currently supports native applications only. Browser-based applications are not supported.&quot; [@ms-entra-token-protection] Most Entra-integrated SaaS is unbound.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Continuous Access Evaluation&lt;/strong&gt; (CAE) shortens the window during which a stolen PRT is operationally usable, by allowing the token endpoint to revoke tokens within minutes of a triggering signal (password change, risk-based detection, conditional-access policy update) [@ms-entra-cae]. CAE is evaluation-time, not isolation. It shortens the window between extraction and detection-driven revocation; it does not prevent extraction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hybrid-joined PRT renewal binding&lt;/strong&gt; partially closes the cross-tenant case for hybrid Azure AD Join configurations, but does not address the same-tenant Pass-the-PRT case that Mollema&apos;s original 2020 posts described [@ms-entra-hybrid-join-plan].&lt;/p&gt;
&lt;p&gt;The institutional acknowledgment of the supersession pattern is the verbatim Microsoft Learn sentence already quoted in section 6 [@ms-learn-credential-guard]: written about the 2015 Credential Guard architecture, it accurately predicts the 2020 Pass-the-PRT shift. The credential-replay family has reached the point where &lt;em&gt;every Microsoft defense&lt;/em&gt; in the on-prem stack runs in parallel against an attack the on-prem stack cannot reach.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Pass-the-PRT defeats Credential Guard, KB5014754, and Protected Users simultaneously because each defense was designed around a different long-term artefact, and the PRT is none of them. The architectural property -- a long-term authentication artefact reachable from the using process is replayable -- is unchanged. The artefact moved.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Six years after Mollema&apos;s disclosure, the TPM-resilience finding still holds. The CloudAP plug-in is still in LSASS. Credential Guard still does not extend its boundary. Pass-the-PRT remains the operational frontier in 2026.&lt;/p&gt;
&lt;h2&gt;9. The 5x5 Matrix and the Irregular Cadence&lt;/h2&gt;
&lt;p&gt;Five generations of attack. Five generations of defense. They map onto each other unevenly; the gaps are not five years.&lt;/p&gt;
&lt;p&gt;The matrix below consolidates the lineage at a glance. Rows are the attack generations (in the order they entered the practitioner literature). Columns are the defense generations (in the order they shipped). Each cell records whether that defense closes that attack on a fully-deployed hardware-eligible 2026 Windows 11 endpoint with the control turned on. &quot;Closed&quot; means the attack returns empty buffers or fails authentication; &quot;Partial&quot; means the defense increases attacker cost or closes one sub-case; &quot;Open&quot; means the defense&apos;s design scope does not include that attack.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attack \ Defense&lt;/th&gt;
&lt;th&gt;Mitigating-PtH whitepapers (2012/2014)&lt;/th&gt;
&lt;th&gt;Protected Users + RunAsPPL + Restricted Admin (2013-2014)&lt;/th&gt;
&lt;th&gt;Credential Guard / LSAISO (2015)&lt;/th&gt;
&lt;th&gt;KB5014754 strong mapping (2022)&lt;/th&gt;
&lt;th&gt;Token Protection + CAE (2023-2025)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Pass-the-Hash (Ashton 1997, Ochoa 2008)&lt;/td&gt;
&lt;td&gt;Open (documentation)&lt;/td&gt;
&lt;td&gt;Partial (Protected Users members)&lt;/td&gt;
&lt;td&gt;Closed (on enabled endpoints)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass-the-Ticket (Delpy 2011, Duckwall+Delpy 2014)&lt;/td&gt;
&lt;td&gt;Open (documentation)&lt;/td&gt;
&lt;td&gt;Partial (4-hour TGT cap for Protected Users)&lt;/td&gt;
&lt;td&gt;Closed (TGT session key in LSAISO)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overpass-the-Hash (Delpy / Metcalf 2014)&lt;/td&gt;
&lt;td&gt;Open (documentation)&lt;/td&gt;
&lt;td&gt;Partial (RC4 banned for Protected Users)&lt;/td&gt;
&lt;td&gt;Closed (NT hash in LSAISO)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass-the-Certificate (Schroeder + Christensen 2021, Méheut 2022)&lt;/td&gt;
&lt;td&gt;Open (documentation)&lt;/td&gt;
&lt;td&gt;Open (cert keys outside scope)&lt;/td&gt;
&lt;td&gt;Open (cert keys outside scope)&lt;/td&gt;
&lt;td&gt;Partial (closes Certifried sub-case; ESC2-ESC16 remain)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass-the-PRT (Mollema + Delpy 2020)&lt;/td&gt;
&lt;td&gt;Open (Entra ID is separate IDP)&lt;/td&gt;
&lt;td&gt;Open (Entra ID is separate IDP)&lt;/td&gt;
&lt;td&gt;Open (CloudAP not in LSAISO)&lt;/td&gt;
&lt;td&gt;Open (not in scope)&lt;/td&gt;
&lt;td&gt;Partial (5 named resources; browser apps out of scope)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Table 2. The 5x5 attack/defense matrix. The union of every cell in the rightmost column of &quot;Closed&quot; entries is the set of attacks Microsoft&apos;s published 2026 defenses close on hardware-eligible non-DC endpoints with every control turned on; that set is precisely the first three rows.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The matrix makes the structure visible. No single defense closes all attacks, and no single attack is closed by all defenses. The union of every defense closes Pass-the-Hash, Pass-the-Ticket, and Overpass-the-Hash on hardware-eligible non-DC Windows 10/11 systems with all controls enabled. It partially closes Pass-the-Certificate (for the Certifried sub-case) and partially closes Pass-the-PRT (for five named resources). Both of the most recent generations remain operationally open against any deployment that does not run those specific controls -- which is most deployments.&lt;/p&gt;
&lt;p&gt;The cadence is just as uneven as the matrix. The original input that prompted this article claimed &quot;every Windows defense against credential replay buys about five years before the attack class evolves to the next credential type.&quot; Memorable. Also wrong. The actual timeline produces gaps from eleven months to eleven years, with one negative interval:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1997 -&amp;gt; 2008&lt;/strong&gt; (eleven years) for the Samba-patch -&amp;gt; Windows-native pivot. Pass-the-Hash existed for over a decade as a Unix-side novelty before Ochoa&apos;s LSASS-injection insight made it Windows-native.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2008 -&amp;gt; 2011&lt;/strong&gt; (three years) for the Mimikatz Pass-the-Ticket extension. The same memory-access primitive that animated &lt;code&gt;IAM.EXE&lt;/code&gt; was retargeted at a different artefact.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2012/2014 -&amp;gt; 2015&lt;/strong&gt; (one to three years) for the Mitigating-PtH whitepapers -&amp;gt; Credential Guard pivot. Documentation took a year and a half to ship; the architectural counter took another.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2021 -&amp;gt; 2022&lt;/strong&gt; (eleven months) for the AD CS catalog -&amp;gt; KB5014754 response. Coordinated disclosure compressed this gap; Certifried&apos;s CVE-class status forced a CVE-class response.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2020 -&amp;gt; 2025+&lt;/strong&gt; (open-ended) for Pass-the-PRT with no Credential-Guard-equivalent shipped. As of the Windows 11 25H2 cycle there is no public roadmap for VBS-class isolation of CloudAP material.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most striking gap is the 2020/2021 &lt;em&gt;negative&lt;/em&gt; interval. Pass-the-PRT (Mollema, August 2020) and the AD CS catalog (Schroeder + Christensen, June 2021) are siblings rather than sequential; Pass-the-PRT predates Pass-the-Certificate as a &lt;em&gt;named technique&lt;/em&gt; by ten months, even though the article treats them as Generation 4 and Generation 5 in narrative order. The Generation N -&amp;gt; N+1 framing is &lt;em&gt;taxonomic&lt;/em&gt;, not strictly chronological. The reader needs this distinction to read the lineage accurately: the attack class evolves along the architectural property, not along the calendar.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &quot;every Windows defense buys five years&quot; framing is what you see if you select the cleanest pairings (Mitigating-PtH 2012/2014 to Credential Guard 2015 plus an artificial 2020-targeted &quot;next attack&quot;). When you look at the actual intervals, you see eleven years (1997-2008), three years (2008-2011), eleven months (2021-2022), and an open-ended interval (2020 onwards). The pattern is the architectural property persisting across artefact changes, not a calendar drumbeat.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The storage-class progression is the cleanest way to see the property hold across the lineage. Each row names the long-term artefact, where it lives, and which defense moved or shielded that storage class.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Long-term artefact&lt;/th&gt;
&lt;th&gt;Storage location&lt;/th&gt;
&lt;th&gt;Defense that isolated it&lt;/th&gt;
&lt;th&gt;Status 2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1A (1997 Samba)&lt;/td&gt;
&lt;td&gt;NT hash (and LM hash)&lt;/td&gt;
&lt;td&gt;Local SAM file on disk&lt;/td&gt;
&lt;td&gt;&quot;Do not store LAN Manager hash&quot; policy (Vista default-on); SAM hash extraction still works&lt;/td&gt;
&lt;td&gt;LM hash retired; NT hash extraction still works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1B (2008 Windows-native)&lt;/td&gt;
&lt;td&gt;NT hash&lt;/td&gt;
&lt;td&gt;LSASS credential cache&lt;/td&gt;
&lt;td&gt;Credential Guard relocates to LSAISO&lt;/td&gt;
&lt;td&gt;Closed on Credential-Guard-enabled endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 (2011 Mimikatz)&lt;/td&gt;
&lt;td&gt;Kerberos TGT plus session key&lt;/td&gt;
&lt;td&gt;LSASS Kerberos package&lt;/td&gt;
&lt;td&gt;Credential Guard relocates to LSAISO&lt;/td&gt;
&lt;td&gt;Closed on Credential-Guard-enabled endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3 (2014)&lt;/td&gt;
&lt;td&gt;NT hash promoted to RC4-HMAC Kerberos key&lt;/td&gt;
&lt;td&gt;LSASS, same buffer as Pass-the-Hash&lt;/td&gt;
&lt;td&gt;Credential Guard relocates to LSAISO; KB5021131 makes AES the default&lt;/td&gt;
&lt;td&gt;Closed on Credential-Guard-enabled endpoints; RC4 deprecated in favour of AES [@ms-kb5021131]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 (2021 AD CS catalog)&lt;/td&gt;
&lt;td&gt;X.509 certificate private key&lt;/td&gt;
&lt;td&gt;CryptoAPI key container, TPM, or smart card&lt;/td&gt;
&lt;td&gt;TPM-resident or VSC-resident keys are cryptographically non-exportable; KB5014754 binds certificates to SIDs at issuance&lt;/td&gt;
&lt;td&gt;Partial; ESC2-ESC16 misconfigurations remain administrative hardening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5 (2020 Pass-the-PRT)&lt;/td&gt;
&lt;td&gt;PRT session key plus derived signing material&lt;/td&gt;
&lt;td&gt;CloudAP plug-in in LSASS (session key optionally TPM-sealed)&lt;/td&gt;
&lt;td&gt;None deployed; Token Protection partially shields five resources&lt;/td&gt;
&lt;td&gt;Open&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Table 3. Storage-class progression. Each attack generation targets the next long-term artefact whose storage location is not isolated by the previous generation&apos;s defense.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The matrix and the storage-class table jointly produce the structural prediction: each generation shifts to the next available long-term artefact whose storage class the latest defense does not isolate. The graph-based formalisation of these storage-class transitions is the BloodHound edge catalog -- the &lt;code&gt;HasSession&lt;/code&gt;, &lt;code&gt;AdminTo&lt;/code&gt;, and &lt;code&gt;CanRDP&lt;/code&gt; family that operationalises &quot;which principal can reach which credential from where&quot; as a queryable property of an enterprise&apos;s directory [@bloodhound-edges]. The pattern predicts a Generation 6 outside whatever isolation scope arrives next.&lt;/p&gt;
&lt;p&gt;The most credible candidate today is &lt;strong&gt;Pass-the-DeviceKey&lt;/strong&gt;: extraction or abuse of the device transport key the PRT binds to, or of the CloudAP-derived material the cookie-signing process produces from it [@mollema-prt-phishing]. Mollema&apos;s 2023-2025 continuation work documents the underlying device-transport-key primitives in detail; the September 2025 Actor-tokens disclosure shows that cross-tenant abuse of related Entra-side material is also operational in the wild [@mollema-actor-tokens] [@mollema-federated-credentials].&lt;/p&gt;

flowchart TD
    A1[Pass-the-Hash 1A Samba&lt;br /&gt;Ashton 1997]
    A2[Pass-the-Hash 1B Windows-native&lt;br /&gt;Ochoa 2008]
    A3[Pass-the-Ticket&lt;br /&gt;Delpy 2011]
    A4[Overpass-the-Hash&lt;br /&gt;Delpy / Metcalf 2014]
    A5[Pass-the-Certificate&lt;br /&gt;Schroeder + Christensen 2021]
    A6[Pass-the-PRT&lt;br /&gt;Mollema + Delpy 2020]
    A7[Pass-the-DeviceKey forecast]
    D1[Mitigating-PtH whitepapers&lt;br /&gt;v1 2012, v2 2014]
    D2[Protected Users + RunAsPPL + Restricted Admin&lt;br /&gt;2013-2014]
    D3[Credential Guard / LSAISO&lt;br /&gt;2015, default 2022]
    D4[KB5014754 strong mapping&lt;br /&gt;2022, enforced 2025]
    D5[Token Protection + CAE&lt;br /&gt;2023-2025]
    D6[CloudAP isolation forecast]
    A1 --&amp;gt; A2
    A2 --&amp;gt; A3
    A3 --&amp;gt; A4
    A4 --&amp;gt; A5
    A4 --&amp;gt; A6
    A6 --&amp;gt; A7
    D1 --&amp;gt; D2
    D2 --&amp;gt; D3
    D3 --&amp;gt; D4
    D4 --&amp;gt; D5
    D5 -.- D6
    A2 -.- D1
    A2 -.- D2
    A3 -.- D3
    A4 -.- D3
    A5 -.- D4
    A6 -.- D5
    A7 -.- D6
&lt;p&gt;If the pattern holds, Generation 6 is already in research literature. Mollema&apos;s 2023-2025 continuation work [@mollema-prt-phishing] [@mollema-federated-credentials] [@mollema-actor-tokens] documents the device-transport-key extraction primitives. The only things missing are the name and the commodity tool. The historical pattern says we probably get both before VBS-class CloudAP isolation ships.&lt;/p&gt;
&lt;h2&gt;10. Open Problems and the 2026-2030 Forecast&lt;/h2&gt;
&lt;p&gt;The credential-replay family has six load-bearing open problems in 2026. Each is structural rather than mathematical; the cryptographic primitives that would close them already exist.&lt;/p&gt;
&lt;p&gt;The architectural lower bound -- the only configuration that closes the family in principle -- is the union of three things.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Universal hardware-rooted non-extractable keys&lt;/strong&gt;: every long-term authentication artefact lives in a TPM, secure enclave, FIDO2 authenticator, or smart card, with key attestation, and is never released to software memory. &lt;strong&gt;Universal protocol-layer token binding&lt;/strong&gt;: every issued token (Kerberos service ticket, OAuth refresh token, OIDC ID token, SAML assertion) is cryptographically bound to the device that requested it, and a verifier rejects any presentation from a non-bound device. &lt;strong&gt;Universal continuous evaluation&lt;/strong&gt;: every protected resource queries the issuer in near-real-time and revokes within minutes of a triggering signal. Each component is deployed &lt;em&gt;somewhere&lt;/em&gt;; none is deployed &lt;em&gt;everywhere&lt;/em&gt;; no single vendor controls all three layers.&lt;/p&gt;
&lt;p&gt;The five concrete open problems flow from the lower bound.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The CloudAP isolation problem.&lt;/strong&gt; When does Microsoft extend VBS-class isolation to the CloudAP plug-in&apos;s working memory in LSASS? No public roadmap as of 2026. Until it ships, Pass-the-PRT remains operationally open against every Entra-joined Windows endpoint.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The token-binding adoption problem.&lt;/strong&gt; Token Protection&apos;s verbatim 2026 scope is the five named resources enumerated in section 8 [@ms-entra-token-protection], which covers approximately five percent of typical Entra-integrated SaaS surface area; every other Entra-integrated resource accepts unbound tokens. The OAuth working group&apos;s RFC 9449 (DPoP, September 2023) standardises proof-of-possession at the OAuth layer [@rfc-9449], but adoption across SaaS providers and enterprise applications is uneven.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Pass-the-DeviceKey forecast.&lt;/strong&gt; Mollema&apos;s 2023-2025 continuation work exercises device-transport-key extraction primitives, federated-credential persistence on Entra applications, and cross-tenant Actor-token abuse [@mollema-prt-phishing] [@mollema-federated-credentials] [@mollema-actor-tokens]. The pattern of every previous generation predicts that whichever of these primitives commoditises first will be the next named &quot;Pass-the-X&quot; technique.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The ESC9-ESC16 hardening problem.&lt;/strong&gt; The AD CS catalog has grown from 8 entries (June 2021) to 16 (current Certipy and Certify wikis [@certipy-wiki-privesc] [@specterops-certify-wiki]); most additions are misconfiguration-class rather than CVE-class. ESC9 specifically describes the &lt;code&gt;CT_FLAG_NO_SECURITY_EXTENSION&lt;/code&gt; template flag that &lt;em&gt;exempts&lt;/em&gt; a template from the very SID extension KB5014754 introduced -- so administrators who turn that flag on for legacy compatibility reasons silently re-enable the Certifried-class abuse path on those templates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hardware-backed identity ubiquity.&lt;/strong&gt; When does the union of Pluton + FIDO2 + virtual smart cards + TPM key attestation eliminate the long-term software-extractable artefact class? Human interactive sign-in to Entra ID can already be fully passwordless on supported hardware. The long tail of service accounts, scheduled tasks, on-prem AD workflows, and legacy applications resists migration; the migration is a years-long enterprise project, not a feature flag.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The non-Microsoft sibling lineages.&lt;/strong&gt; The credential-replay family is not Windows-specific. Okta session-cookie theft, Google IDP refresh-token reuse, Apple ASWebAuthSession token replay, and AWS STS session-token theft all face the same architectural property. An enterprise running Microsoft plus Okta plus Google inherits the union of every vendor&apos;s residual replay surface. The family generalises beyond Microsoft because the architectural property generalises beyond Microsoft.&lt;/p&gt;

Okta&apos;s `sessionToken` and OAuth `refresh_token` artefacts live on the device that requested them, and have been used in commodity offensive tooling since at least 2022. Google&apos;s IDP refresh tokens face the same exposure surface on managed Chromebooks. Apple&apos;s ASWebAuthSession tokens are device-bound at the platform level, which closes the cross-device replay case but not the same-device extraction case. AWS STS session tokens are not device-bound at all. The credential-replay family is a property of long-term software-extractable authentication artefacts in general; this article is Windows-specific only because Windows has the longest documented lineage.
&lt;p&gt;The institutional position is that the protocol-level fix is unavailable -- Microsoft&apos;s framing of Pass-the-Hash as a structural property of NTLM generalises directly to every later generation. A universal fix would require replacing every long-term software-extractable artefact globally with hardware-bound primitives, with mandatory token binding at every issuer and every resource server, with continuous evaluation everywhere. Each step is incrementally closable; the union has not yet closed for any deployment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Universal hardware-rooted non-extractable keys, universal protocol-layer token binding, universal continuous evaluation. Each component is deployed somewhere; none is deployed everywhere. No single vendor controls all three layers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The architectural property the family shares has held for twenty-nine years; the defensive lineage will not close it without making &lt;em&gt;every&lt;/em&gt; long-term artefact live in hardware-rooted isolation that exceeds the host&apos;s privilege. Whether that happens in the next five years, the next ten, or the next twenty-five, is the open question the next chapter of this lineage will answer.&lt;/p&gt;
&lt;h2&gt;11. The 2026 Defender Playbook&lt;/h2&gt;
&lt;p&gt;Architectural humility does not mean defensive passivity. The 2026 estate is defensible against generations 1 through 3 and partially against generation 4; the playbook is to deploy every available control while reading Mollema&apos;s 2025 posts to know what&apos;s coming for generation 5 and beyond.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Credential Guard everywhere it can run.&lt;/strong&gt; Hardware-eligible non-DC Windows 10/11 endpoints, with the four-residual disclosure (AD database, DCs, certificate keys, CloudAP) documented for the SOC so that detection engineering does not assume Credential Guard covers categories it explicitly excludes [@ms-learn-credential-guard].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LSA Protection (RunAsPPL), UEFI-anchored&lt;/strong&gt; stacked underneath, per itm4n&apos;s &quot;complementary&quot; framing [@itm4n-lsass-runasppl]. The UEFI-anchored variant resists the registry-based bypass that a kernel-mode attacker can otherwise apply at boot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication Silos and Protected Users for Tier-0 accounts.&lt;/strong&gt; Expect to encounter unconstrained-delegation breakage on legacy services and budget remediation; the 240-minute TGT cap is the lever that prevents long-lived Tier-0 ticket reuse [@ms-protected-users].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;KB5014754 strong-mapping enforcement&lt;/strong&gt; -- fully on by the September 9, 2025 cutover -- plus an annual certificate-template audit cycle against the ESC1-ESC16 catalog using Certipy or PSPKIAudit [@ms-kb5014754] [@certipy-wiki-privesc]. The audit is the load-bearing control because the strong-mapping fix only closes Certifried-class abuses; the template misconfigurations Schroeder and Christensen catalogued are still administrative responsibility.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Conditional Access with Token Protection where supported&lt;/strong&gt; -- the five resources Microsoft Learn enumerates [@ms-entra-token-protection]. Device-bound sign-ins for privileged accounts; FIDO2 for human interactive sign-in. Know that the long tail of Entra-integrated SaaS does not enforce binding, and that a stolen PRT used against an unbound resource will still authenticate.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PRT-extraction telemetry.&lt;/strong&gt; Detect CloudAP-plug-in token access from non-CloudAP processes; tie to Endpoint DLP; alert on out-of-band access to &lt;code&gt;cloudap.dll&lt;/code&gt;-owned regions of LSASS memory. Mollema&apos;s &lt;code&gt;roadtx&lt;/code&gt; and BARK produce signal patterns worth modelling.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mental model: assume the PRT is the next NT hash.&lt;/strong&gt; Architect today as if Credential Guard for CloudAP shipped tomorrow -- which means TPM-attested device joins as standard, FIDO2 for every human sign-in, hardware-backed identity for service accounts wherever the vendor supports it, and conditional access policies that treat unmanaged or non-attested devices as untrusted by default.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

Open PowerShell as administrator and run:&lt;p&gt;&lt;code&gt;Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard | Format-List&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The result of interest is &lt;code&gt;SecurityServicesRunning&lt;/code&gt;. A value of &lt;code&gt;1&lt;/code&gt; in that list means Credential Guard is actively running (per the Win32_DeviceGuard documentation: &lt;code&gt;1 = Credential Guard&lt;/code&gt;, &lt;code&gt;2 = HVCI&lt;/code&gt;, &lt;code&gt;3 = System Guard secure launch&lt;/code&gt;, etc.). &lt;code&gt;SecurityServicesConfigured&lt;/code&gt; tells you what the policy intends; &lt;code&gt;SecurityServicesRunning&lt;/code&gt; tells you what the hypervisor is actually enforcing right now. The two values disagree more often than you would expect, usually because the hardware did not meet a prerequisite at boot.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The minimum-viable layer: Credential Guard on every hardware-eligible non-DC endpoint, KB5014754 enforcement-mode certificate strong mapping with an annual ESC catalog audit, and PRT-extraction telemetry tied to a real detection workflow. The first two are commodity Microsoft features that close real attack classes today; the third is the only meaningful signal you can get on the attack class that none of the published defenses currently closes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;None of this closes Pass-the-PRT. All of it shortens the dwell time.&lt;/p&gt;
&lt;h2&gt;12. Frequently Asked Questions&lt;/h2&gt;


No. The Primary Refresh Token sits in the CloudAP plug-in, which is outside Credential Guard&apos;s verbatim three-credential scope -- see section 6 (&quot;What does Credential Guard isolate?&quot;) and section 8 (&quot;Pass-the-PRT defeats three Microsoft defenses simultaneously&quot;) for the full mechanism.

No. The 1997 Ashton patch and the 2008 Ochoa Windows-native pivot are both pre-Mimikatz; see section 1 and section 3 for the full origin story. Mimikatz is the dominant *tool* (May 2011 first release) but it is not the *origin* of Pass-the-Hash.

No. The PRT is *hybrid* -- issued and revoked cloud-side by Entra ID, but stored and used client-side via the CloudAP plug-in inside LSASS. See section 8 (&quot;Where the PRT *lives*&quot;) for why this hybrid architecture is what makes Pass-the-PRT operationally tractable today.

No. It closed the three Certifried-class CVEs (CVE-2022-26923, CVE-2022-26931, CVE-2022-34691) but not the broader ESC2 through ESC16 catalog. See section 7 (&quot;What does KB5014754 actually close?&quot;) and Table 1 for the per-template breakdown.

For human interactive sign-in to Entra ID, mostly, if the entire enterprise migrates -- the FIDO2 authenticator holds a non-extractable private key in hardware, and the resulting authentication is bound to that key. For service accounts, scheduled tasks, on-prem Kerberos workflows, hybrid identity scenarios, and the long tail of legacy applications, no -- those paths still rely on long-term software-extractable artefacts (passwords, hashes, keys) by construction. The architectural counter is universal hardware-rooted non-extractable keys plus universal token binding plus universal continuous evaluation; the operational reality is partial coverage.

No public v3. See section 5 (&quot;The Mitigating-PtH v3 that never shipped&quot;) for the source-by-source disambiguation against Microsoft Download Center ID 36036.

&lt;h2&gt;13. The Pattern That Outlived Six Defenses&lt;/h2&gt;
&lt;p&gt;The 1997 patch and the 2026 attack are the same attack because the architectural property the family shares is unchanged. The artefact moved; the property did not.&lt;/p&gt;
&lt;p&gt;A long-term authentication artefact reachable by the using process is replayable. The NT hash sat in LSASS on Windows NT 4.0 and replayed against SMB. The Kerberos TGT sat in LSASS on Windows Server 2003 and replayed against Kerberos services. The NT hash sat in LSASS on Windows Server 2008 and replayed against the KDC&apos;s RC4-HMAC authentication path as a real Kerberos client.&lt;/p&gt;
&lt;p&gt;The X.509 certificate private key sat in a CryptoAPI key container on Windows Server 2012 R2 and replayed against PKINIT-supporting domain controllers as the principal in the SAN. The Primary Refresh Token sits in the CloudAP plug-in inside LSASS on Windows 11 23H2 today, and replays against Entra ID as the device&apos;s user from any machine that holds the extracted session key.&lt;/p&gt;
&lt;p&gt;Each defense relocated the artefact to a harder-to-reach storage class. The &quot;Do not store LAN Manager hash&quot; policy retired LM. RunAsPPL marked LSASS as a Protected Process Light. Credential Guard moved NT hashes and TGT session keys out of LSASS in VTL0 into the LSAISO trustlet in VTL1. KB5014754 bound certificates to SIDs at issuance, so that a certificate without the SID extension fails strong mapping at the KDC. Token Protection bound PRTs to devices, so that a stolen PRT used against a supported resource from a non-bound device fails.&lt;/p&gt;
&lt;p&gt;Each defense was real. Each closed a generation. The family did not close.&lt;/p&gt;
&lt;p&gt;The reason the family does not close is structural. Every generation finds the next long-term artefact whose storage class the latest defense did not isolate. Pass-the-Hash worked because the NT hash was reachable. Pass-the-Ticket worked because the TGT was reachable. Overpass-the-Hash worked because the NT hash was reachable &lt;em&gt;and&lt;/em&gt; the KDC accepted RC4-HMAC. Pass-the-Certificate worked because certificate templates were misconfigured and the SID extension did not exist. Pass-the-PRT works because CloudAP is in LSASS in VTL0 and Token Protection covers five resources.&lt;/p&gt;
&lt;p&gt;The architectural lower bound -- universal hardware-rooted non-extractable keys plus universal token binding plus universal continuous evaluation -- is the only configuration that closes the family, and it is not deployed anywhere as a complete stack.&lt;/p&gt;
&lt;p&gt;The playbook in the previous section is what to do today. The forecast in section 10 is what to architect for next. The closing observation is the one this article exists to register: when you read about the next named &quot;Pass-the-X&quot; technique, you already know what it will look like. A long-term authentication artefact, reachable from the process that holds it, replayed from a different machine, defeating the latest defense because that defense was designed for a different artefact.&lt;/p&gt;
&lt;p&gt;Generation 6 is already in research literature. The only thing missing is the name.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;pass-the-hash-to-pass-the-prt&quot; keyTerms={[
  { term: &quot;NT hash&quot;, definition: &quot;16-byte MD4 of the user&apos;s password as UTF-16 little-endian; the long-term Windows authentication secret since the early NT releases, unsalted by design.&quot; },
  { term: &quot;NTLM challenge-response&quot;, definition: &quot;Family of Windows authentication protocols (NTLMv1 and NTLMv2) in which the server sends a random challenge and the client returns a keyed cryptographic response computed under a key derived from the user&apos;s password; the password is never transmitted.&quot; },
  { term: &quot;Pass-the-Hash&quot;, definition: &quot;Authenticating with a stolen NT hash by feeding it directly to the protocol&apos;s response-construction function instead of typing a password; Paul Ashton, NTBugtraq, April 1997.&quot; },
  { term: &quot;LSASS&quot;, definition: &quot;Local Security Authority Subsystem Service; the user-mode Windows process that caches in-memory credential material (hashes, tickets, certificate handles, PRT material) for the duration of each logon session.&quot; },
  { term: &quot;Kerberos TGT&quot;, definition: &quot;Ticket Granting Ticket: the long-lived Kerberos credential issued by the KDC&apos;s Authentication Service, encrypted under the krbtgt long-term key, carrying a session key for subsequent service-ticket requests.&quot; },
  { term: &quot;Pass-the-Ticket&quot;, definition: &quot;Extracting a Kerberos TGT (and its session key) from one machine&apos;s LSASS-resident Kerberos cache and injecting it into another machine&apos;s cache.&quot; },
  { term: &quot;Overpass-the-Hash&quot;, definition: &quot;Presenting a stolen NT hash to the KDC as the user&apos;s long-term RC4-HMAC Kerberos key (per RFC 4757) to obtain a real TGT signed by the real krbtgt.&quot; },
  { term: &quot;Credential Guard&quot;, definition: &quot;Windows feature that relocates NT hashes, Kerberos TGT session keys, and &apos;credentials stored by applications as domain credentials&apos; from LSASS in VTL0 to the LSAISO trustlet in VTL1, isolated by the Windows hypervisor.&quot; },
  { term: &quot;LSAISO trustlet&quot;, definition: &quot;The isolated-user-mode LSA process (lsaiso.exe) that holds Credential Guard&apos;s protected credential material in VTL1; unreadable from any VTL0 process or driver.&quot; },
  { term: &quot;PKINIT&quot;, definition: &quot;Kerberos pre-authentication using a certificate&apos;s private key in place of a long-term symmetric key (RFC 4556); the SAN of the certificate maps to the principal whose TGT the KDC will issue.&quot; },
  { term: &quot;Pass-the-Certificate&quot;, definition: &quot;Authenticating to Active Directory with a stolen X.509 certificate&apos;s private key via PKINIT to the KDC or Schannel client-cert authentication to LDAPS.&quot; },
  { term: &quot;szOID_NTDS_CA_SECURITY_EXT&quot;, definition: &quot;X.509 extension introduced by KB5014754 (OID 1.3.6.1.4.1.311.25.2) that carries the requesting principal&apos;s SID at certificate issuance; the basis of KDC strong certificate mapping.&quot; },
  { term: &quot;Primary Refresh Token (PRT)&quot;, definition: &quot;Microsoft Entra-issued long-lived refresh token for SSO on Entra-joined or Hybrid-joined Windows devices; carries a session key (HMAC-SHA256) and binds to a device transport key; default 90-day lifetime with sliding renewal.&quot; },
  { term: &quot;CloudAP&quot;, definition: &quot;Cloud Authentication Provider; the Windows authentication package (cloudap.dll) loaded into LSASS that holds Microsoft Entra credential material including the PRT; not currently inside Credential Guard&apos;s isolation scope.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>active-directory</category><category>kerberos</category><category>credential-theft</category><category>credential-guard</category><category>entra-id</category><category>pass-the-hash</category><category>pass-the-prt</category><category>windows-security</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Microsoft Defender for Identity: The Defensive AD Stack That Sees What BloodHound Maps</title><link>https://paragmali.com/blog/microsoft-defender-for-identity-the-defensive-ad-stack-that-/</link><guid isPermaLink="true">https://paragmali.com/blog/microsoft-defender-for-identity-the-defensive-ad-stack-that-/</guid><description>A field guide to Microsoft Defender for Identity, the on-DC sensor and cloud analytics engine descended from Aorato, that fires named alerts on almost every offensive AD primitive in the corpus -- and the five structural blind spots it cannot close.</description><pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Microsoft Defender for Identity (MDI) is the cloud-backed, on-DC defensive sensor that watches for almost every offensive Active Directory primitive in the SpecterOps / Mimikatz / Certipy corpus** -- DCSync, DCShadow, Golden / Silver / Diamond ticket forgery, Kerberoasting, AS-REP roasting, NTLM relay, and AD CS abuse -- by parsing Kerberos, NTLM, LDAP, and DRSUAPI on the wire and running per-principal behavioural baselines in a multi-tenant cloud backend. The product began as the Israeli startup Aorato (acquired by Microsoft in November 2014), shipped on-prem as Microsoft ATA in 2015, moved to the cloud as Azure ATP in 2018, was renamed to MDI in 2020, folded into Microsoft Defender XDR at Ignite 2023, and reached its current MDE-integrated v3.x sensor in October 2025. The alert catalogue maps cleanly onto MITRE ATT&amp;amp;CK, and the residual blind spots are knowable: the Credential Guard wall, the Sapphire Ticket&apos;s cryptographic indistinguishability, the encrypted-channel DCSync class, the cross-forest under-instrumentation tail, and legitimate-principal compromise. The operator question in 2026 is not whether MDI detects the attack, but whether the sensor is deployed, the alert was triaged inside the batched-emission window, and the residuals are covered by KQL, Sigma rules, or out-of-band controls.
&lt;h2&gt;1. A Friday Afternoon at the Domain Controller&lt;/h2&gt;
&lt;p&gt;Friday, 14:33. A red-team contractor in conference room C runs &lt;code&gt;Rubeus.exe asreproast&lt;/code&gt; on a corporate laptop she was issued an hour ago. A junior auditor on the fourth floor, working from a desk with read-only Active Directory access, runs &lt;code&gt;bloodhound-python -c All&lt;/code&gt; for a routine quarterly review. A quiet service account on the SQL host in rack 14 runs &lt;code&gt;mimikatz &quot;lsadump::dcsync /domain:contoso.com /user:Administrator&quot;&lt;/code&gt;. The operator at the other end of that session is not on the payroll. Three different workstations. Three different intents. One domain controller on the receiving end of all three.&lt;/p&gt;
&lt;p&gt;The Security Operations Center has not noticed any of them yet. The watcher on the domain controller, however, has. By 14:35 three named alerts are sitting in the Defender XDR queue, each tagged with a MITRE ATT&amp;amp;CK technique ID, each waiting for someone to triage. &lt;em&gt;Suspected AS-REP Roasting attack&lt;/em&gt; (T1558.004) for the Rubeus invocation [@mslearn-mdi-alerts-xdr]. &lt;em&gt;Security principal reconnaissance (LDAP)&lt;/em&gt; for the BloodHound enumeration [@mslearn-mdi-alerts-mdi-classic]. &lt;em&gt;Suspected DCSync attack -- replication of directory services&lt;/em&gt;, External ID 2006, T1003.006, for the Mimikatz call [@mslearn-mdi-alerts-mdi-classic][@mitre-t1003-006]. The watcher is Microsoft Defender for Identity.SOC operators inside Microsoft customers describe this with a stock phrase: &quot;the watcher was already on the DC.&quot; The phrase shows up in incident-response runbooks, vendor training decks, and the Microsoft Defender for Identity Tech Community archive. It captures what is, architecturally, a strange thing -- the defender&apos;s sensor is co-located with the attacker&apos;s target, not perched outside it.&lt;/p&gt;

A Windows Server hosting the Active Directory Domain Services role, responsible for processing Kerberos authentication, NTLM challenges, LDAP queries, and inter-DC directory replication (DRSUAPI) for a domain. Every named MDI runtime alert in this article fires on signal that originates on or transits a domain controller; the deployment model assumes one MDI sensor per DC, plus optional sensors on AD FS, AD CS, and Microsoft Entra Connect servers when those identity roles run on dedicated hosts.
&lt;p&gt;Almost every offensive AD primitive a reader of the SpecterOps, Mimikatz, and Certipy corpus already knows has a runtime alert or a posture assessment shipped by Microsoft on that same DC. &lt;em&gt;Almost&lt;/em&gt; is the load-bearing word. The alert fires only if three things are true: the sensor is deployed on the surface the attack touches, the audit subcategory the alert depends on is enabled, and the SOC opens the Defender XDR incident inside the batched-emission window the cloud backend uses to aggregate signal. This article is about all three conditions, the twelve-year arc that built the watcher, and the structural blind spots no future MDI release will close.&lt;/p&gt;
&lt;p&gt;The watcher was not always on the domain controller. For the first decade of Active Directory, nothing on the DC saw what &lt;a href=&quot;https://paragmali.com/blog/ad-is-a-graph-how-bloodhound-made-defenders-think-like-attac/&quot; rel=&quot;noopener&quot;&gt;BloodHound&lt;/a&gt; today maps. To understand where the watcher came from -- and why its blind spots look the way they do -- we have to start with three founders in Herzliya and a Kerberos forgery presentation in Las Vegas.&lt;/p&gt;
&lt;h2&gt;2. Origins -- Aorato, the Israeli Startup That Became the Watcher&lt;/h2&gt;
&lt;p&gt;August 2014, Black Hat USA. Tal Be&apos;ery and Michael Cherny take the stage with Alva Duckwall and Benjamin Delpy to present &lt;em&gt;&quot;Abusing Microsoft Kerberos: Sorry You Guys Don&apos;t Get It,&quot;&lt;/em&gt; a demonstration that a stolen &lt;a href=&quot;https://paragmali.com/blog/krbtgt-the-account-that-owns-active-directory/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;krbtgt&lt;/code&gt;&lt;/a&gt; key lets an attacker mint Kerberos ticket-granting tickets that survive every password rotation in the standard remediation playbook [@blackhat-us14-briefings]. The audience is Active Directory operators who thought their password-reset runbook covered them. By the end of the talk it does not. The startup behind the research is &lt;strong&gt;Aorato&lt;/strong&gt;, three years old, headquartered in Herzliya, Israel. Three months later, Microsoft buys it.&lt;/p&gt;

The credential a Kerberos client receives from the Key Distribution Center (the KDC, which on a Windows network runs on every DC) after successful pre-authentication. The TGT is encrypted with the KDC&apos;s own long-term key -- on Active Directory, the password hash of the `krbtgt` account. Possession of the `krbtgt` hash therefore lets an attacker forge a valid TGT for any principal in the domain, since the KDC has no other way to distinguish a forged ticket from a real one. This forged-ticket class is what MITRE catalogues as T1558.001 Golden Ticket [@mitre-t1558-001].
&lt;p&gt;The Aorato deal closed on &lt;strong&gt;November 13, 2014&lt;/strong&gt;, announced on the Microsoft Official Blog by Takeshi Numoto, then Corporate Vice President of Cloud and Enterprise Marketing [@msblog-aorato]. The post named the central technology Microsoft was acquiring: Aorato&apos;s &lt;em&gt;Organizational Security Graph&lt;/em&gt;, described as &quot;a living, continuously-updated view of all of the people and machines accessing an organization&apos;s Windows Server Active Directory.&quot; Pre-acquisition Microsoft had Azure AD on the cloud side and per-DC event log auditing on the on-prem side, but no first-party behavioural-analytics product over Active Directory. Aorato&apos;s pre-acquisition product, the &lt;em&gt;Directory Services Application Firewall&lt;/em&gt;, did exactly that -- it parsed Kerberos, NTLM, LDAP, and DRSUAPI on the wire and ran per-principal behavioural baselines against the parsed protocol stream. Microsoft wanted that capability inside Windows Server, and inside Office 365.Aorato&apos;s three founders, per the Globes coverage of the acquisition in November 2014, were Idan Plotnik (CEO), Michael Dolinsky (VP R&amp;amp;D), and Ohad Plotnik (VP professional services). Tal Be&apos;ery was VP of Research. A popular reading of the deal names &quot;the Plotnik brothers and Tal Be&apos;ery&quot; as the co-founder trio, which compresses out Dolinsky&apos;s role -- the contemporaneous record names four people, not three [@globes-aorato-2014].&lt;/p&gt;
&lt;p&gt;The product lineage that follows is twelve years long and runs through five names. &lt;strong&gt;Microsoft Advanced Threat Analytics (ATA)&lt;/strong&gt; was announced as generally available on August 27, 2015 (build 1.4.2457, dated August 31, 2015) -- the on-prem productisation of Aorato&apos;s wire-side parser, packaged as a SPAN-mirror appliance (&quot;ATA Gateway&quot;) plus an on-prem analytics server (&quot;ATA Center&quot;) with its own MongoDB-style document store [@mstc-ata-ga][@atadocs-versions]. &lt;strong&gt;Azure ATP&lt;/strong&gt; went GA on March 1, 2018 -- the cloud-side rewrite that kept the on-DC sensor but moved the analytics engine to a multi-tenant cloud backend [@mstc-azureatp-ga][@mstc-azureatp-intro]. &lt;strong&gt;Microsoft Defender for Identity&lt;/strong&gt; was the September 22, 2020 rename announced at Ignite 2020, part of Microsoft&apos;s broader brand consolidation that also rebranded Office 365 ATP to Microsoft Defender for Office 365 and Microsoft Defender ATP to Microsoft Defender for Endpoint [@mssecblog-unified-xdr][@itpro-defender-rebrand][@infusedinnov-names]. The November 2023 Ignite keynote consolidated Microsoft 365 Defender into &lt;strong&gt;Microsoft Defender XDR&lt;/strong&gt; [@virtreview-ignite2023][@handsontek-defender-rebrand]. In October 2025 the &lt;strong&gt;v3.x sensor&lt;/strong&gt; GA folded MDI&apos;s on-DC sensor into the Microsoft Defender for Endpoint agent that organisations were already running on every server [@mslearn-mdi-whats-new][@modernsec-v3x][@jeffreyappel-v2v3]. The May 2026 release notes extended the v3.x sensor to cover AD FS, AD CS, and Microsoft Entra Connect identity roles directly when those roles run on a domain controller, and raised the per-workspace sensor cap from 350 to 1,000 [@mslearn-mdi-whats-new].&lt;/p&gt;

gantt
    title Microsoft Defender for Identity lineage, 2012-2026
    dateFormat YYYY-MM-DD
    axisFormat %Y
    section Aorato
    Aorato startup (DSAF product)        :a1, 2012-01-01, 2014-11-13
    section Microsoft ATA
    ATA initial release SPAN-mirror Gateway :a2, 2015-08-27, 2016-05-01
    ATA 1.6-1.9 Lightweight Gateway      :a3, 2016-05-01, 2018-03-01
    ATA Extended Support window          :a4, 2018-03-01, 2026-01-31
    section Cloud rewrite
    Azure ATP GA                          :a5, 2018-03-01, 2020-09-22
    Microsoft Defender for Identity name :a6, 2020-09-22, 2023-11-15
    section Defender XDR era
    MDI inside Defender XDR (v2.x)        :a7, 2023-11-15, 2025-10-01
    MDI v3.x MDE-integrated sensor        :a8, 2025-10-01, 2026-05-27
&lt;p&gt;Aorato&apos;s pitch in 2014 was that the Windows Security event log -- the thing every SIEM in the world was ingesting -- could not see the attacks an Active Directory operator most needed to catch. To believe that pitch you have to know exactly what the event log misses.&lt;/p&gt;
&lt;h2&gt;3. Why the Event Log Could Not See Golden Tickets&lt;/h2&gt;
&lt;p&gt;Present a Golden Ticket to a domain controller, and the LSA writes a successful event 4769 -- a &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos service ticket request&lt;/a&gt;. Present a legitimate ticket from the same principal, and the LSA writes a successful event 4769. Nothing in the event log&apos;s schema, anywhere in any field, distinguishes the two. The ticket is forged with the real &lt;code&gt;krbtgt&lt;/code&gt; key, so the KDC&apos;s signature checks pass. The event log records &lt;em&gt;that an authentication happened&lt;/em&gt;, not &lt;em&gt;whether the ticket presented was genuine&lt;/em&gt;. This is the structural ceiling the SIEM industry could not work around for the first decade of its existence, and it is the gap Aorato was built to close [@mitre-t1558-001][@semperis-golden-ticket].&lt;/p&gt;
&lt;p&gt;The bare-event-log model has three structural failure modes, each of which drove a generation of detection engineering. &lt;strong&gt;Forged-ticket invisibility&lt;/strong&gt; is the first: the LSA logs that an auth happened, but every byte in the 4769 event matches the legitimate case. &lt;strong&gt;Per-DC silo&lt;/strong&gt; is the second: a Kerberos auth against one DC and a follow-up auth against another DC five seconds later sit in two different &lt;code&gt;Security.evtx&lt;/code&gt; files, on two different machines, with no aggregation layer to ask &quot;did the same principal hit ten DCs in five minutes?&quot; &lt;strong&gt;Manual-review throughput collapse&lt;/strong&gt; is the third: a medium-sized forest emits thousands of 4624, 4768, 4769 events per minute per DC, and the human analyst hand-walking them never catches up.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/&quot; rel=&quot;noopener&quot;&gt;DCSync&lt;/a&gt; makes the first two failure modes vivid. Sean Metcalf&apos;s September 2015 ADSecurity writeup walks through running &lt;code&gt;lsadump::dcsync /domain:contoso.com /user:Administrator&lt;/code&gt; from a workstation: the DC handles the DRSUAPI replication request, the LSA emits a 4662 event for the directory-service-object access, and the attacker walks away with the password hash [@adsec-dcsync].Metcalf&apos;s companion DerbyCon V talk, &lt;em&gt;Red vs. Blue: Modern Active Directory Attacks &amp;amp; Defense&lt;/em&gt; (September 2015), is the canonical operator-grade introduction to the same material [@adsec-dump-ad]. The 4662 event is structurally indistinguishable from a legitimate replication request between two DCs. A SIEM rule that flagged 4662 events whose source IP was not a DC could catch it -- but only if the analyst maintained the IP allowlist (a single Microsoft Entra Connect server in the wrong subnet broke the rule), and only if 4662 was enabled at all (it was high-volume, and many SOCs disabled it to stay under the SIEM&apos;s GB/day licence).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The SIEM was not failing at Active Directory detection because the rules were wrong. It was failing because the event log -- the data source every SIEM relied on -- could not see what the SIEM needed it to see. Better rules over the same event log would not have closed the gap. Aorato&apos;s contribution was to find a different data source: the wire itself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Aorato&apos;s three primitives, none of which the SIEM-plus-event-log model had, were: &lt;strong&gt;per-principal behavioural baselines&lt;/strong&gt; so that a long-tail anomaly stood out without anybody writing a rule for it; &lt;strong&gt;on-DC network capture&lt;/strong&gt; so that the ticket structure, the DRSUAPI opnum, and the LDAP search filter were available to detection logic; and &lt;strong&gt;a graph over the directory&lt;/strong&gt; so that the path from compromised workstation to crown-jewel asset could be computed rather than inferred. ATA shipped the first two in 2015. The graph took longer.&lt;/p&gt;
&lt;h2&gt;4. Early Approaches -- ATA 1.x and the Generations That Tried Before&lt;/h2&gt;
&lt;p&gt;By the time Aorato shipped its first product, four prior generations of Active Directory detection had already tried and stalled. Each one could see something the previous generation could not. Each one had a structural ceiling an attacker primitive eventually pushed through. The seven generations that follow are the real spine of the article.&lt;/p&gt;

flowchart LR
    G1[&quot;Gen 1: bare per-DC&lt;br /&gt;event log audit&quot;] --&amp;gt; G2[&quot;Gen 2: SIEM-centralised&lt;br /&gt;events with static rules&quot;]
    G2 --&amp;gt; G3[&quot;Gen 3: first-generation UEBA&lt;br /&gt;over SIEM events&quot;]
    G3 --&amp;gt; G4[&quot;Gen 4: Aorato DSAF and&lt;br /&gt;ATA 1.4-1.5 (SPAN mirror)&quot;]
    G4 --&amp;gt; G5[&quot;Gen 5: ATA 1.6-1.9&lt;br /&gt;(Lightweight Gateway + LMP)&quot;]
    G5 --&amp;gt; G6[&quot;Gen 6: Azure ATP, MDI v1.x-v2.x&lt;br /&gt;(cloud analytics)&quot;]
    G6 --&amp;gt; G7[&quot;Gen 7: MDI v3.x&lt;br /&gt;(MDE-integrated + Identity Explorer)&quot;]
&lt;p&gt;&lt;strong&gt;Generation 1 -- bare per-DC event log auditing (1999-2008)&lt;/strong&gt; was already covered above. It was the only model that existed for the first decade of Active Directory, and its structural ceilings became Aorato&apos;s pitch deck.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 2 -- SIEM-centralised event log ingestion with static correlation rules (2005-2014)&lt;/strong&gt; is the era of ArcSight, Splunk, QRadar, and LogRhythm. Windows Event Forwarder agents on every DC streamed Security event log entries into a central index, and SOC operators wrote rule-based correlation searches in the vendor&apos;s query language. The model gave the SOC cross-DC correlation, a query language, and an audit trail that satisfied PCI-DSS Requirement 10. It did not give the SOC anything new about the data the LSA emitted. Mimikatz&apos;s &lt;code&gt;lsadump::dcsync&lt;/code&gt; was committed to the public Mimikatz repository in March 2015 [@mimikatz-github][@adsec-dcsync]. Sean Metcalf&apos;s longer ADSecurity writeup of the technique followed in September 2015. At commit time, every SIEM in production was correlating DC event logs and not one was emitting a DCSync alert, because the 4662 event was structurally identical to a legitimate DC-to-DC replication.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 3 -- first-generation UEBA on SIEM event data (2013-2017)&lt;/strong&gt; was Securonix, Exabeam, and Splunk UBA. Per-principal behavioural baselines layered on top of the SIEM event index could catch novel TTPs without prior signatures -- a Kerberoasting variant whose SPN list had never been seen before could still trip &quot;this account is requesting an unusual number of service tickets compared to its baseline.&quot; UEBA also closed Generation 2&apos;s per-principal context gap. It did not, however, see ticket structure: a Golden Ticket replayed against ten DCs produces ten successful auths that are behaviourally indistinguishable from the legitimate Domain Admin&apos;s pattern unless the attacker&apos;s source IP or geographic distribution breaks the baseline. This is the &lt;em&gt;legitimate-principal-compromise non-detection class&lt;/em&gt; that survives every defensive generation into 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 4 -- on-wire protocol analytics via off-DC SPAN-mirror Gateway&lt;/strong&gt; is where Aorato&apos;s product, and then Microsoft ATA 1.4 and 1.5, lived. A switch SPAN port mirrored DC traffic to a dedicated ATA Gateway appliance, which ran libpcap-equivalent capture and parsed Kerberos AS-REQ / TGS-REQ / AP-REQ, NTLM challenges, LDAP searches, and DRSUAPI replication calls. Parsed events streamed to the on-prem ATA Center, which ran detection logic and surfaced alerts in a web console [@mstc-ata-ga]. The wire-side parse closed Generation 1-3&apos;s biggest blind spot: ticket structure was finally visible. The SPAN-port operational tax killed the architecture in nine months. Many enterprises could not provision a SPAN mirror. Virtualised DCs on shared hypervisors had no equivalent of a physical SPAN. And the security review of &quot;all DC traffic now mirrors to this appliance&quot; was non-trivial.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 5 -- ATA 1.6 Lightweight Gateway through ATA 1.9 (May 2016 to March 2020)&lt;/strong&gt; moved the Gateway in-process onto the DC itself. ATA 1.6 (May 2016) introduced the Lightweight Gateway with dynamic resource management that capped the sensor&apos;s CPU and memory footprint and let the sensor consume events locally rather than via mirrored network traffic [@mslearn-ata-1-6]. ATA 1.7 (August 31, 2016) added Role-Based Access Control for the ATA Console, Windows Server Core support, and detection of reconnaissance through directory-services enumeration [@mssupport-ata-1-7][@atadocs-versions]. &lt;strong&gt;ATA 1.8 (June 30, 2017; announced July 26, 2017)&lt;/strong&gt; shipped behavioural-brute-force detection, a Golden Ticket lifetime detector, and the abnormal-modification-of-sensitive-groups alert [@mslearn-ata-1-8][@mstc-ata-1-8][@ataversions-1-8-availability]. &lt;strong&gt;ATA 1.9 (March 21, 2018)&lt;/strong&gt; shipped both the entity-profile lateral-movement-aware view and the &lt;em&gt;Lateral movement paths to sensitive accounts&lt;/em&gt; report [@mslearn-ata-1-9][@atadocs-versions][@atadocs-lmp-usecase].A widespread reading of the ATA timeline anchors LMP to ATA 1.7 in late 2017. The primary record contradicts this on both date and feature: ATA 1.7 shipped on August 31, 2016 per the Microsoft Support KB and the ATA-versions table, and the 1.7 release notes do not mention Lateral Movement Paths. Neither do the 1.8 release notes -- LMP first appears in ATA 1.9 (March 21, 2018), which introduced both the entity-profile lateral-movement view and the full Lateral movement paths to sensitive accounts report in the same release [@mssupport-ata-1-7][@atadocs-versions][@mslearn-ata-1-8][@mslearn-ata-1-9].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A popular framing of the LMP timeline says &quot;Microsoft adopted BloodHound-style graph attack paths in 2022.&quot; The primary sources contradict this. Graph-anchored attack-path evaluation in Microsoft&apos;s defensive stack originates in &lt;strong&gt;ATA 1.9 (March 2018)&lt;/strong&gt;, not in any 2022 adoption event. What did happen in 2022 was the start of the deprecation arc for the SAM-R-based discovery the LMP graph depended on, which culminated in Message Center notice &lt;strong&gt;MC1073068 in May 2025&lt;/strong&gt; when Microsoft disabled SAM-R-based local-administrators collection across MDI tenants [@handsontek-mc1073068]. The 2022 date that lingers in operator memory is the &lt;em&gt;deprecation&lt;/em&gt; anchor, not the adoption anchor.&lt;/p&gt;
&lt;/blockquote&gt;

An attack chain through Active Directory in which a non-sensitive account whose credentials are exposed on one workstation can be used to authenticate to a second workstation where a sensitive account&apos;s credentials are cached, which in turn can be used to reach a third workstation, and so on until a Domain Admin or comparable target is reached. ATA 1.9&apos;s Lateral Movement Paths report was the first graph-anchored defensive surface that computed the chain in advance; the report was populated by SAM-R queries that enumerated each host&apos;s local-administrators group. Microsoft disabled the SAM-R-based collection in May 2025 (MC1073068), and the post-LMP graph layer migrated to the Defender XDR hunting graph plus the April 2026 Identity Explorer preview.
&lt;p&gt;The limitation that drove Generation 5 into Generation 6 was the on-prem ATA Center&apos;s release cadence. Benjamin Delpy and Vincent Le Toux disclosed &lt;strong&gt;DCShadow&lt;/strong&gt; at BlueHat IL 2018 in January 2018 -- the technique of registering a rogue domain controller via &lt;code&gt;nTDSDSA&lt;/code&gt; object creation plus SPN registration, then pushing arbitrary updates into AD via legitimate DRSUAPI replication that the event log records as ordinary inter-DC traffic [@dcshadow-com][@mitre-t1207]. ATA 1.9 shipped two months later, in March 2018, with no DCShadow detection. Azure ATP -- the cloud-side rewrite, also GA in March 2018 -- shipped paired alerts External ID 2028 (&lt;em&gt;Suspected DCShadow attack -- domain controller promotion&lt;/em&gt;) and External ID 2029 (&lt;em&gt;Suspected DCShadow attack -- domain controller replication request&lt;/em&gt;) &lt;strong&gt;five months later, in July 2018&lt;/strong&gt; [@mslearn-mdi-alerts-mdi-classic][@mslearn-mdi-whats-new-archive]. The on-prem release cadence could not have closed that five-month gap. The cloud rewrite was the structural answer.&lt;/p&gt;
&lt;h2&gt;5. The Breakthrough -- Azure ATP and the Inverted Data Path&lt;/h2&gt;
&lt;p&gt;If the wire was the right data layer, the cloud was the right place to run the analytics. That is the architectural decision Azure ATP committed to in March 2018, and it is what distinguishes the Microsoft defensive product from every prior generation. The on-DC sensor stayed on the DC. The analytics engine moved.&lt;/p&gt;
&lt;p&gt;Four architectural shifts followed. &lt;strong&gt;First&lt;/strong&gt;, the on-DC sensor became a thin parser. Sensors no longer hosted detection logic; they captured the Kerberos / NTLM / LDAP / DRSUAPI traffic, parsed it into a stream of structured events, and shipped the stream upstream. &lt;strong&gt;Second&lt;/strong&gt;, the data path inverted. Generation 4 sent unparsed packets from the wire to the off-DC Gateway, which parsed them and stored them on-prem; Azure ATP sent parsed events from the on-DC sensor upstream to a multi-tenant cloud backend that ran detection logic and wrote alerts back into a tenant-specific workspace. &lt;strong&gt;Third&lt;/strong&gt;, per-principal behavioural baselines accumulated centrally rather than per-DC, so a baseline survived DC reboots, sensor restarts, and migrations across data centres. &lt;strong&gt;Fourth&lt;/strong&gt;, identity signal joined endpoint and email signal in the same incident queue once Azure ATP folded into Microsoft 365 Defender -- the cross-product correlation that no on-prem product had ever offered [@mstc-azureatp-ga][@mstc-azureatp-intro][@mslearn-xdr-overview].&lt;/p&gt;
&lt;p&gt;Then came the brand-and-architecture history every operator has to know to read a 2026 runbook. The &lt;strong&gt;September 22, 2020&lt;/strong&gt; rename from Azure Advanced Threat Protection to Microsoft Defender for Identity was a brand consolidation, not an architecture change -- the same sensor, the same alerts, the same workspace [@mssecblog-unified-xdr]. The legacy &lt;code&gt;portal.atp.azure.com&lt;/code&gt; standalone portal was &lt;strong&gt;retired on June 30, 2023&lt;/strong&gt; via Message Center notice MC567494, with all requests automatically redirected to &lt;code&gt;security.microsoft.com&lt;/code&gt; [@handsontek-mc567494][@mslearn-mdi-portal]. The &lt;strong&gt;November 15, 2023&lt;/strong&gt; Ignite keynote renamed Microsoft 365 Defender to Microsoft Defender XDR (Message Center MC696570) [@handsontek-defender-rebrand][@virtreview-ignite2023]. Again a brand change, again not an architecture change: the sensors stayed on the DC, the analytics stayed in the cloud, and the KQL schema -- &lt;code&gt;IdentityLogonEvents&lt;/code&gt;, &lt;code&gt;IdentityQueryEvents&lt;/code&gt;, &lt;code&gt;IdentityDirectoryEvents&lt;/code&gt; -- stayed the same [@mslearn-xdr-identitylogon][@mslearn-xdr-identityquery][@mslearn-xdr-identitydirectory].The legacy &lt;code&gt;portal.atp.azure.com&lt;/code&gt; URL is worth remembering because runbooks and SOAR rules from 2018 to 2023 frequently hard-coded it. Any rule that referenced the old portal needs an update; the redirect handles browser traffic but not API calls.&lt;/p&gt;
&lt;p&gt;What the sensor actually feeds into the cloud backend, in 2026, is four data-input layers, ordered roughly by evidence strength. &lt;strong&gt;First&lt;/strong&gt;, the Windows Security event log -- the audit subcategories that the MDI event-collection page lists as required, including &lt;em&gt;Audit Credential Validation&lt;/em&gt;, &lt;em&gt;Audit Kerberos Authentication Service&lt;/em&gt;, &lt;em&gt;Audit Kerberos Service Ticket Operations&lt;/em&gt;, &lt;em&gt;Audit Directory Service Access&lt;/em&gt;, and &lt;em&gt;Audit Computer Account Management&lt;/em&gt; among others [@mslearn-mdi-event-collection]. These are public, documented, and easy to verify with &lt;code&gt;auditpol /get /category:*&lt;/code&gt;. &lt;strong&gt;Second&lt;/strong&gt;, on-DC network capture of Kerberos, NTLM, LDAP, and DRSUAPI -- well-documented because the sensor&apos;s network requirements are part of the public deployment guide. &lt;strong&gt;Third&lt;/strong&gt;, &lt;a href=&quot;https://paragmali.com/blog/etw-how-windows-2000s-performance-hack-became-the-edr-substr/&quot; rel=&quot;noopener&quot;&gt;Event Tracing for Windows&lt;/a&gt; providers that the sensor subscribes to in order to get signal the event log does not surface. &lt;strong&gt;Fourth&lt;/strong&gt;, AD CS audit-log subscriptions added with the AD CS sensor release in August 2023 [@mstc-adcs-sensor][@dirteam-sander-aug2023].&lt;/p&gt;

Microsoft has never published the canonical list of Event Tracing for Windows providers that the MDI sensor subscribes to. Any specific list of providers a reader encounters traces back to community reverse-engineering: Synacktiv&apos;s *A primer on Microsoft Defender for Identity* by Guillaume Andre and Mickael Benassouli (November 2022) is the canonical operator-research primary [@synacktiv-primer-mdi][@synacktiv-primer-mdi-archive]. The methodological precedent is Olaf Hartong&apos;s *Microsoft Defender for Endpoint Internals* series, specifically the 0x02 entry on audit settings and telemetry, which documents the binary-side enumeration approach: run Matt Graeber&apos;s Get-TraceLoggingMetadata script against the sensor executable to enumerate the providers it registers, then use Sealighter to trace those providers to a file for further analysis [@falconforce-mde-0x02][@gist-tracelogging-metadata][@github-sealighter]. Hartong&apos;s 0x02 article reports &quot;roughly 111 public and MDE-exclusive providers used&quot; by MsSense.exe -- the MDI sensor binary is amenable to the same technique, and the provider mix differs (MDI subscribes heavily to LDAP, Kerberos, DRSUAPI, and SAM-R-class providers; MDE subscribes heavily to process, file, network, and image-load providers) but the methodology is shared [@falconforce-mde-0x03][@github-olafhartong]. Read any community-published MDI provider list as a snapshot of what the community has reverse-engineered, not as Microsoft-published ground truth.

The breakthrough was not better detection algorithms. The breakthrough was moving the analytics off the DC entirely, so the per-principal baselines could accumulate centrally and the detection set could ship on a cloud cadence instead of an on-prem one. That decision is why MDI shipped DCShadow detection within five months of disclosure -- a cadence the on-prem product could not have matched.
&lt;p&gt;That is the move that turned a wire-side parse into a sustained detection program. The proof is the DCShadow timeline: five months from disclosure to detection, on a cadence the on-prem product could not have matched. Now we can ask the question every reader of the offensive-AD corpus actually wants answered. What does the watcher catch in 2026?&lt;/p&gt;
&lt;h2&gt;6. MDI in 2026 -- Sensors, Alerts, KQL, and the Graph in Transition&lt;/h2&gt;
&lt;p&gt;This is the article&apos;s bookmarking section. Four parts: what is on the DC, what alerts fire, what KQL the operator writes when the alerts miss, and where the graph layer that began as ATA 1.9&apos;s Lateral Movement Paths report actually lives in 2026.&lt;/p&gt;
&lt;h3&gt;6.1 Sensor topology in 2026&lt;/h3&gt;
&lt;p&gt;What is on a Windows Server 2022 (or 2025) domain controller running MDI in May 2026? Two sensor families, two target-server matrices, and a workspace cap.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;v2.x sensor&lt;/strong&gt; is the legacy standalone agent: supported on Windows Server 2016 and earlier domain controllers, and on AD FS, AD CS issuing certificate authorities, and Microsoft Entra Connect servers that are not themselves domain controllers, per the v2.x prerequisites page [@mslearn-mdi-prereq-sensor-v2]. v2.x carries its own installer, its own update cadence, and its own packet capture stack (NPCap). It also requires a &lt;em&gt;Directory Service Account&lt;/em&gt; (DSA) -- a gMSA configured during install whose forest-wide read rights let the sensor enumerate AD objects.&lt;/p&gt;

A group Managed Service Account configured during MDI v2.x sensor installation, granted forest-wide read permissions on Active Directory objects so the sensor can resolve principal identities, enumerate group memberships, and read schema attributes that the wire-side parse refers to by SID. The v3.x sensor replaces the DSA pattern with LocalSystem impersonation -- the sensor impersonates the local-system account of the domain controller it runs on, which has equivalent on-DC read rights without needing a separate gMSA per tenant [@mslearn-mdi-deploy-sensor-v3][@mslearn-mdi-action-accounts].
&lt;p&gt;The &lt;strong&gt;v3.x sensor&lt;/strong&gt; is the current path. It requires Windows Server 2019 or later with the March 2026 (or later) cumulative update installed, the Defender for Endpoint agent already deployed and onboarded, and -- critically -- there is no separate MDI installer at all. The MDI sensor capability ships as an extension of the MDE SENSE service. Self-imposed resource caps: &lt;strong&gt;CPU at most 30% of the host DC&apos;s CPU, memory at most 1.5 GB&lt;/strong&gt;, with explicit Hyper-V Dynamic Memory and VMware reservation guidance that ensures the cap is honoured under contention [@mslearn-mdi-deploy-sensor-v3]. v3.x uses LocalSystem impersonation for AD reads rather than a gMSA-based DSA. The May 2026 release notes added direct v3.x support for AD FS, AD CS, and Microsoft Entra Connect identity roles &lt;em&gt;when those roles run on a domain controller&lt;/em&gt; (which is the recommended deployment pattern for most mid-sized tenants) [@mslearn-mdi-whats-new].The 30% CPU cap is honoured by the MDE SENSE service&apos;s scheduling, but Hyper-V Dynamic Memory and VMware ballooning can break the assumption -- if the hypervisor reclaims memory under contention the sensor cannot get its 1.5 GB and the local capture buffer drops events. Microsoft&apos;s deployment guide recommends a static memory reservation on virtualised DCs for that reason.&lt;/p&gt;
&lt;p&gt;The four target server roles are domain controllers (every DC, including RODCs), AD FS federation servers (not Web Application Proxies), AD CS online issuing certificate authorities (not offline root CAs), and Microsoft Entra Connect servers (both active and staging). The May 2026 release notes also raised the per-workspace capacity ceiling from 350 sensors to &lt;strong&gt;1,000 sensors per workspace&lt;/strong&gt; [@mslearn-mdi-whats-new].&lt;/p&gt;

flowchart TD
    DC1[&quot;Domain Controller&lt;br /&gt;(WS2019+, v3.x sensor&lt;br /&gt;inside MDE SENSE)&quot;]
    DC2[&quot;Domain Controller&lt;br /&gt;(WS2016, v2.x sensor)&quot;]
    ADFS[&quot;AD FS server&lt;br /&gt;(v2.x sensor, non-DC)&quot;]
    ADCS[&quot;AD CS issuing CA&lt;br /&gt;(v2.x or v3.x sensor)&quot;]
    EC[&quot;Entra Connect server&lt;br /&gt;(v2.x sensor)&quot;]
    CLOUD[&quot;MDI cloud backend&lt;br /&gt;(multi-tenant analytics,&lt;br /&gt;per-principal baselines)&quot;]
    XDR[&quot;Microsoft Defender XDR&lt;br /&gt;(security.microsoft.com)&lt;br /&gt;Identity tables + alerts&quot;]
    DC1 --&amp;gt; CLOUD
    DC2 --&amp;gt; CLOUD
    ADFS --&amp;gt; CLOUD
    ADCS --&amp;gt; CLOUD
    EC --&amp;gt; CLOUD
    CLOUD --&amp;gt; XDR
&lt;p&gt;The deployment matrix below is the operator-grade reference -- which role gets which sensor, which audit subcategories the sensor depends on, and what posture data the role unlocks.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server role&lt;/th&gt;
&lt;th&gt;Sensor version&lt;/th&gt;
&lt;th&gt;Required audit subcategories&lt;/th&gt;
&lt;th&gt;Posture coverage unlocked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Domain controller (WS 2019+)&lt;/td&gt;
&lt;td&gt;v3.x (preferred)&lt;/td&gt;
&lt;td&gt;Credential Validation; Kerberos AS; Kerberos TGS; Logon; DS Access; Computer Account Mgmt&lt;/td&gt;
&lt;td&gt;Full Identity Security Posture (entity hygiene, dormant accounts, weak crypto)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain controller (WS 2016)&lt;/td&gt;
&lt;td&gt;v2.x&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;td&gt;Same as above, minus v3.x-only enhancements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AD FS federation server&lt;/td&gt;
&lt;td&gt;v2.x (or v3.x if also a DC)&lt;/td&gt;
&lt;td&gt;AD FS audit logs (Application + Security)&lt;/td&gt;
&lt;td&gt;Hybrid auth signal (Entra ID + on-prem)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AD CS issuing CA&lt;/td&gt;
&lt;td&gt;v2.x (or v3.x if also a DC)&lt;/td&gt;
&lt;td&gt;AD CS audit logs (certificate request and template events)&lt;/td&gt;
&lt;td&gt;Nine ESC posture assessments (ESC1-Preview, ESC2, ESC3, ESC4, ESC6-Preview, ESC7, ESC8, ESC11, ESC15) [@mslearn-mdi-certificates-posture]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra Connect server&lt;/td&gt;
&lt;td&gt;v2.x (or v3.x if also a DC)&lt;/td&gt;
&lt;td&gt;Sync engine event log&lt;/td&gt;
&lt;td&gt;Sync-engine attribute-flow signal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For new DC deployments on Windows Server 2019 or later, use &lt;strong&gt;v3.x&lt;/strong&gt;: no separate installer, no gMSA, no NPCap, and the sensor ships its updates with the MDE agent. For AD FS, AD CS, or Entra Connect roles that run on dedicated Windows Server 2016 hosts, &lt;strong&gt;v2.x&lt;/strong&gt; is the supported path until those hosts are upgraded. Mixed environments are normal during the migration window; the cloud backend handles both versions without operator intervention [@modernsec-v3x][@jeffreyappel-v2v3]. &lt;strong&gt;One known limitation as of May 2026&lt;/strong&gt;: Windows Server 2025 domain controllers that currently run a v2.x sensor cannot be migrated to v3.x; Microsoft&apos;s What&apos;s New page is explicit that &quot;migration of domain controllers with Windows Server 2025 from sensor v2.x to sensor v3.x is not supported&quot; and the operator should continue on v2.x on those hosts until migration support ships [@mslearn-mdi-whats-new].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sensor topology determines coverage. Coverage determines which alerts can fire.&lt;/p&gt;
&lt;h3&gt;6.2 The alert taxonomy mapped to MITRE ATT&amp;amp;CK&lt;/h3&gt;
&lt;p&gt;Every offensive Active Directory primitive a reader of the SpecterOps, Mimikatz, and Certipy corpus knows has a row in MDI&apos;s alert catalogue. The catalogue is the article&apos;s bookmarkable artifact, and the table below is the load-bearing data-density object. Four MITRE-aligned categories, the named alert for each primitive, and the ATT&amp;amp;CK technique ID the alert maps to.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;MDI alert (External ID / detector)&lt;/th&gt;
&lt;th&gt;MITRE ATT&amp;amp;CK technique&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Reconnaissance&lt;/td&gt;
&lt;td&gt;Account enumeration reconnaissance (LDAP) -- External ID 2437&lt;/td&gt;
&lt;td&gt;T1087 Account Discovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reconnaissance&lt;/td&gt;
&lt;td&gt;Network-mapping reconnaissance (DNS)&lt;/td&gt;
&lt;td&gt;T1018 Remote System Discovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reconnaissance&lt;/td&gt;
&lt;td&gt;Security principal reconnaissance (LDAP)&lt;/td&gt;
&lt;td&gt;T1069 Permission Groups Discovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reconnaissance&lt;/td&gt;
&lt;td&gt;User and IP address reconnaissance (SMB)&lt;/td&gt;
&lt;td&gt;T1018&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Honeytoken activity (authentication / attribute / group)&lt;/td&gt;
&lt;td&gt;T1098 Account Manipulation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Suspected Skeleton Key attack&lt;/td&gt;
&lt;td&gt;T1556 (Modify Authentication Process)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Suspected Golden Ticket usage (encryption downgrade)&lt;/td&gt;
&lt;td&gt;T1558.001 Golden Ticket [@mitre-t1558-001]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Suspected Golden Ticket usage (forged authorization data)&lt;/td&gt;
&lt;td&gt;T1558.001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Suspected DCShadow attack (DC promotion) -- External ID 2028&lt;/td&gt;
&lt;td&gt;T1207 Rogue Domain Controller [@mitre-t1207]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Suspected DCShadow attack (DC replication request) -- External ID 2029&lt;/td&gt;
&lt;td&gt;T1207&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and privilege escalation&lt;/td&gt;
&lt;td&gt;Suspicious additions to sensitive groups&lt;/td&gt;
&lt;td&gt;T1098 Account Manipulation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential access&lt;/td&gt;
&lt;td&gt;Suspected DCSync attack (replication of directory services) -- External ID 2006&lt;/td&gt;
&lt;td&gt;T1003.006 DCSync [@mitre-t1003-006]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential access&lt;/td&gt;
&lt;td&gt;Suspected Brute Force attack (Kerberos, NTLM)&lt;/td&gt;
&lt;td&gt;T1110 Brute Force&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential access&lt;/td&gt;
&lt;td&gt;Suspected AS-REP Roasting attack&lt;/td&gt;
&lt;td&gt;T1558.004 AS-REP Roasting [@mitre-t1558-004]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential access&lt;/td&gt;
&lt;td&gt;Suspected Kerberos SPN exposure / Kerberoasting&lt;/td&gt;
&lt;td&gt;T1558.003 Kerberoasting [@mitre-t1558-003]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential access&lt;/td&gt;
&lt;td&gt;Suspected over-pass-the-hash attack&lt;/td&gt;
&lt;td&gt;T1550.002 Pass the Hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lateral movement&lt;/td&gt;
&lt;td&gt;Suspected identity theft (pass-the-hash)&lt;/td&gt;
&lt;td&gt;T1550.002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lateral movement&lt;/td&gt;
&lt;td&gt;Suspected identity theft (pass-the-ticket)&lt;/td&gt;
&lt;td&gt;T1550.003 Pass the Ticket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lateral movement&lt;/td&gt;
&lt;td&gt;Remote code execution attempt&lt;/td&gt;
&lt;td&gt;T1021 Remote Services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lateral movement&lt;/td&gt;
&lt;td&gt;Suspected NTLM relay attack (the ESC8 class)&lt;/td&gt;
&lt;td&gt;T1187 Forced Authentication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lateral movement&lt;/td&gt;
&lt;td&gt;Suspected NTLM authentication tampering&lt;/td&gt;
&lt;td&gt;T1557.001 LLMNR / NBT-NS / Man-in-the-Middle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Both alert documentation surfaces -- the classic-format alert reference and the XDR-format alert reference -- are the canonical primaries for this catalogue [@mslearn-mdi-alerts-mdi-classic][@mslearn-mdi-alerts-xdr]. Reading either page in sequence is the single most useful afternoon a SOC operator new to MDI can spend.The numeric External IDs (2006 for DCSync, 2028 and 2029 for DCShadow, 2437 for LDAP account enumeration, and so on) are a Microsoft-internal stability anchor that survives alert-name renames over time. Microsoft has renamed alerts -- &quot;Suspected DCSync attack&quot; was named differently in early Azure ATP -- but the External IDs do not change. Production SOAR rules should match on the External ID, not the alert name string.&lt;/p&gt;

An offensive primitive in which a principal that has been granted the *Replicating Directory Changes* and *Replicating Directory Changes All* extended rights uses the DRSUAPI replication interface (specifically `IDL_DRSGetNCChanges`) to request a full or partial replication of directory contents from a domain controller -- typically targeting the `unicodePwd` attribute on sensitive accounts like `krbtgt` and `Administrator`. The technique requires no code execution on the DC, no `Ntds.dit` copy, and no presence on a domain-joined machine other than network connectivity to a DC. Mimikatz&apos;s `lsadump::dcsync` command, written by Benjamin Delpy and Vincent Le Toux, is the canonical implementation; MITRE catalogues the technique as T1003.006 [@mitre-t1003-006][@adsec-dcsync].

A specific adversary behaviour catalogued in the MITRE ATT&amp;amp;CK framework, identified by a stable ID (for example T1003.006 for DCSync, T1558.001 for Golden Ticket, T1207 for Rogue Domain Controller). MITRE updates the framework periodically; the IDs themselves do not change, which is why detection-engineering tooling -- including MDI&apos;s per-alert MITRE mapping -- anchors to the IDs rather than the human-readable names.
&lt;p&gt;Concrete mechanism, for one named alert. &lt;em&gt;Suspected DCSync attack -- replication of directory services&lt;/em&gt;, External ID 2006, fires on the structural pattern that an &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; request reached a domain controller from a source that is not itself a domain controller. The mechanism is the one place where MDI&apos;s wire-side capture pays for itself most visibly -- the 4662 event the LSA emits records the directory-service-object access but does not identify the source as not-a-DC; only the wire view sees the calling host&apos;s IP and resolves it against the directory&apos;s &lt;code&gt;serverReference&lt;/code&gt; set.&lt;/p&gt;

sequenceDiagram
    autonumber
    participant Attacker as Attacker workstation (Mimikatz)
    participant DC as Domain Controller
    participant MDI as MDI v3.x sensor (on DC)
    participant Cloud as MDI cloud backend
    participant XDR as Defender XDR portal
    Attacker-&amp;gt;&amp;gt;DC: IDL_DRSGetNCChanges (DRSUAPI replication request)
    DC-&amp;gt;&amp;gt;DC: LSA writes event 4662 (DS object access)
    DC--&amp;gt;&amp;gt;Attacker: Replication response (unicodePwd, supplementalCredentials)
    MDI-&amp;gt;&amp;gt;MDI: Wire parse: caller IP not in serverReference set
    MDI-&amp;gt;&amp;gt;Cloud: Stream parsed event (caller, target object, attributes)
    Cloud-&amp;gt;&amp;gt;Cloud: Correlate against known-DC IPs, fire detector
    Cloud-&amp;gt;&amp;gt;XDR: Write alert External ID 2006 (T1003.006)
    XDR-&amp;gt;&amp;gt;XDR: Surface in unified incident queue
&lt;p&gt;The alert taxonomy makes the bookmarkable promise the rest of the article rests on. The trigger logic that fires each row, however, depends on signal the sensor can only acquire on the wire or in the event log -- and when the trigger logic misses, the operator&apos;s last-mile coverage is KQL.&lt;/p&gt;
&lt;h3&gt;6.3 The advanced-hunting schema and a worked KQL example&lt;/h3&gt;
&lt;p&gt;When the alert template misses, the hunter writes Kusto Query Language. Defender XDR exposes three identity-specific tables that the MDI sensor populates -- &lt;code&gt;IdentityLogonEvents&lt;/code&gt; for authentication activity captured against on-prem AD, &lt;code&gt;IdentityQueryEvents&lt;/code&gt; for queries performed against AD objects, and &lt;code&gt;IdentityDirectoryEvents&lt;/code&gt; for events involving an on-prem domain controller including password changes, expirations, UPN changes, scheduled tasks, and PowerShell activity [@mslearn-xdr-identitylogon][@mslearn-xdr-identityquery][@mslearn-xdr-identitydirectory]. Cross-product context is available from the unified &lt;code&gt;AlertInfo&lt;/code&gt;, &lt;code&gt;AlertEvidence&lt;/code&gt;, and &lt;code&gt;DeviceLogonEvents&lt;/code&gt; tables.&lt;/p&gt;
&lt;p&gt;The worked example below is the structural DCSync detector that catches the encrypted-channel case the alert can miss. The runner in this environment cannot execute KQL directly, so the block is annotated rather than runnable -- a non-runnable KQL detector is stronger pedagogy here than a hand-rolled Python simulation, because the query as written is exactly what an operator would paste into the Defender XDR advanced-hunting console against the actual &lt;code&gt;IdentityDirectoryEvents&lt;/code&gt; table.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kql&quot;&gt;// Structural DCSync detector -- DRSUAPI from non-DC IPs
// Run against the Defender XDR advanced-hunting IdentityDirectoryEvents table.
IdentityDirectoryEvents
| where Timestamp &amp;gt; ago(24h)                                  // tune window per triage cadence
| where ActionType == &quot;DRSReplicate&quot;                          // the DRSUAPI replication call
| extend SourceIP = tostring(parse_json(AdditionalFields).SourceIPAddress)
| where SourceIP !in (&quot;10.0.1.10&quot;, &quot;10.0.1.11&quot;, &quot;10.0.1.12&quot;)  // tenant DC IPs go here
| where AccountName !startswith &quot;MSOL_&quot;                       // Entra Connect Cloud Sync FP class
| where AccountName !in (&quot;ADConnectSync&quot;)                     // Entra Connect on-prem FP class
| project Timestamp, AccountName, SourceIP, TargetDeviceName, AdditionalFields
| order by Timestamp desc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output rows that survive the filters are the operator&apos;s investigation queue: DRSUAPI replication requests against a DC from a source that is not itself a DC, and not a recognised hybrid-identity sync principal. The two cleanup principals -- &lt;code&gt;MSOL_*&lt;/code&gt; (the Microsoft Entra Connect Cloud Sync service account, with a stable &lt;code&gt;MSOL_&lt;/code&gt; prefix and an 8-character random suffix) and &lt;code&gt;ADConnectSync&lt;/code&gt; (the on-prem Entra Connect service account) -- are the two most common false positives every MDI tenant sees. Adding them to the &lt;code&gt;!startswith&lt;/code&gt; and &lt;code&gt;!in&lt;/code&gt; clauses cuts the FP rate by an order of magnitude in most environments. The third FP class that operators tune for is &lt;strong&gt;legitimate vulnerability scanners&lt;/strong&gt; triggering the LDAP / SMB reconnaissance alerts -- the scanner&apos;s authenticated enumeration looks behaviourally identical to a SharpHound collector unless the scanner&apos;s source IP is in an allowlist.&lt;/p&gt;

flowchart LR
    A[&quot;IdentityDirectoryEvents&lt;br /&gt;(DRSReplicate)&quot;] --&amp;gt; B[&quot;Filter: source IP&lt;br /&gt;not in known_dc_ips&quot;]
    B --&amp;gt; C[&quot;Filter: account&lt;br /&gt;not in sync allowlist&quot;]
    C --&amp;gt; D[&quot;Suspect rows&lt;br /&gt;(operator triage)&quot;]
&lt;p&gt;Beyond the three identity tables there is one more surface worth naming. The April 2026 &lt;em&gt;Identity Explorer&lt;/em&gt; Preview in the Defender XDR Identity page builds on the Microsoft Sentinel data lake -- Microsoft&apos;s 2026 cross-product cold-storage and analytics layer with up to 12 years of retention in Parquet format [@mslearn-sentinel-datalake][@mslearn-mdi-whats-new]. Identity Explorer uses the Defender XDR hunting graph to visualise identity attack paths as interactive graphs with predefined scenarios for lateral movement, privilege escalation, and credential-access risk [@mslearn-xdr-hunting-graph][@mslearn-xdr-investigate-users].&lt;/p&gt;
&lt;p&gt;The query language is the operator&apos;s last-mile coverage layer. Everything in section 6 so far is what MDI gives you. KQL is what you do when MDI does not.&lt;/p&gt;
&lt;h3&gt;6.4 The graph layer in transition&lt;/h3&gt;
&lt;p&gt;The graph that began as ATA 1.9&apos;s Lateral Movement Paths report no longer exists in the form most operators remember. The history is a clean three-step arc and a transition still in progress.&lt;/p&gt;
&lt;p&gt;ATA 1.9 (March 2018) shipped the &lt;em&gt;Lateral movement paths to sensitive accounts&lt;/em&gt; report, built on SAM-R-based local-administrator discovery: the sensor remotely enumerated each member host&apos;s local-administrators group and computed the chain of &quot;who can become whom&quot; through cached credentials [@mslearn-ata-1-9][@atadocs-lmp-usecase]. That report carried through Azure ATP, through the Microsoft Defender for Identity rename, and through the Microsoft Defender XDR rebrand essentially unchanged for seven years.&lt;/p&gt;
&lt;p&gt;In May 2025, Microsoft disabled the SAM-R-based discovery via Message Center notice MC1073068, citing alignment with the broader &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;Windows NTLM-deprecation roadmap&lt;/a&gt; [@handsontek-mc1073068]. The message body is explicit: &lt;em&gt;&quot;Disabling this feature will impact the ability to map potential lateral movement paths (using SAM-R queries) because the data used to calculate potential lateral movement paths will no longer be collected by the Defender for Identity sensor.&quot;&lt;/em&gt; SAM-R as a remote-discovery primitive had become a security debt as much as a feature; the deprecation brought MDI&apos;s collection behaviour into line with Restricted SAM and Microsoft&apos;s NTLM-deprecation posture, but it left the LMP surface without its primary data source.&lt;/p&gt;
&lt;p&gt;The replacement is in two pieces. The first is the unified &lt;strong&gt;attack-path exploration&lt;/strong&gt; surface in Microsoft Defender XDR, driven primarily by Microsoft Defender for Cloud&apos;s Cloud Security Posture Management (CSPM) attack-path engine [@mslearn-defenderforcloud-attack-path], with MDI feeding identity signal into the same correlation. The second is the &lt;strong&gt;Identity Explorer&lt;/strong&gt; Preview that launched in April 2026 on the Microsoft Sentinel data lake, specifically for identity attack paths -- visible from the Identity page in Defender XDR for tenants with a Sentinel data lake licence [@mslearn-mdi-whats-new][@mslearn-xdr-hunting-graph][@mslearn-xdr-investigate-users]. The honest framing in 2026 is that the post-SAM-R LMP coverage is &lt;strong&gt;not yet fully closed&lt;/strong&gt; by either replacement -- the Defender XDR hunting graph is rich, the Identity Explorer is improving, but the seven-year-old SAM-R-derived LMP report had operator workflows around it that the new surfaces have not all reproduced.&lt;/p&gt;
&lt;p&gt;MDI&apos;s graph layer is in transition. The cloud rewrite handed Microsoft the platform to ship a better graph than ATA ever could; in 2026 the build-out is still in progress. Section 9 will name this as one of the article&apos;s open problems. First, though, we have to look at the competitive market the watcher sits inside.&lt;/p&gt;
&lt;h2&gt;7. Competing Approaches -- the 2026 Identity-Detection Market&lt;/h2&gt;
&lt;p&gt;If MDI is the watcher on the DC, what is everybody else? Five named methods share the 2026 identity-threat detection market with MDI, each optimising for a different trade-off. The table below is the six-column shorthand; the prose that follows is the per-method analysis.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vendor / project&lt;/th&gt;
&lt;th&gt;On-DC sensor model&lt;/th&gt;
&lt;th&gt;Data-input mix&lt;/th&gt;
&lt;th&gt;Alert taxonomy&lt;/th&gt;
&lt;th&gt;Graph model&lt;/th&gt;
&lt;th&gt;Pricing model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MDI&lt;/td&gt;
&lt;td&gt;On-DC sensor (v2.x standalone or v3.x MDE-integrated)&lt;/td&gt;
&lt;td&gt;Wire + event log + ETW + AD CS audit&lt;/td&gt;
&lt;td&gt;MITRE-aligned alert catalogue + nine ESC posture&lt;/td&gt;
&lt;td&gt;Hunting graph + Identity Explorer Preview&lt;/td&gt;
&lt;td&gt;Bundled with M365 E5 / E5 Security / F5 Security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CrowdStrike Falcon Identity Protection&lt;/td&gt;
&lt;td&gt;Connector on/near DC + endpoint agent&lt;/td&gt;
&lt;td&gt;Wire (via connector) + endpoint telemetry&lt;/td&gt;
&lt;td&gt;ITDR-style alerts, less granular ATT&amp;amp;CK mapping&lt;/td&gt;
&lt;td&gt;Identity attack-path view (inline enforcement)&lt;/td&gt;
&lt;td&gt;Falcon ITDR module add-on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semperis DSP + ADFR&lt;/td&gt;
&lt;td&gt;Off-DC change-tracking agent&lt;/td&gt;
&lt;td&gt;AD object-change events (LDAP / replication)&lt;/td&gt;
&lt;td&gt;IoC and IoE runtime alerts plus drift / tamper alerts&lt;/td&gt;
&lt;td&gt;Tier 0 exposure graph + rollback graph&lt;/td&gt;
&lt;td&gt;Standalone licence per AD object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SpecterOps BloodHound Enterprise&lt;/td&gt;
&lt;td&gt;Off-DC collector (SharpHound CE)&lt;/td&gt;
&lt;td&gt;AD permissions graph + Azure / Okta / Mac extensions&lt;/td&gt;
&lt;td&gt;Attack-path exposure findings&lt;/td&gt;
&lt;td&gt;Pure graph (Cypher over Postgres / Neo4j)&lt;/td&gt;
&lt;td&gt;Standalone SaaS licence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Sentinel native UEBA&lt;/td&gt;
&lt;td&gt;None on DC (consumes MDI + other sources)&lt;/td&gt;
&lt;td&gt;Sentinel data lake (cross-product)&lt;/td&gt;
&lt;td&gt;UEBA risk scores, anomaly events&lt;/td&gt;
&lt;td&gt;None on identity graph directly&lt;/td&gt;
&lt;td&gt;Sentinel ingestion + UEBA add-on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sigma + SIEM (open source)&lt;/td&gt;
&lt;td&gt;None on DC (event forwarder agents)&lt;/td&gt;
&lt;td&gt;Windows event logs, ETW via OSQuery / Velociraptor&lt;/td&gt;
&lt;td&gt;Custom rule library&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Free (rule library); SIEM cost separate&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;CrowdStrike Falcon Identity Protection&lt;/strong&gt; is the post-acquisition rename of &lt;em&gt;Preempt Platform&lt;/em&gt;, the product line CrowdStrike bought when it completed the &lt;strong&gt;Preempt Security acquisition on September 30, 2020&lt;/strong&gt; [@businesswire-cs-preempt]. Architecturally distinct from MDI: rather than relying on an on-DC sensor that parses wire traffic and event logs, Falcon Identity Protection inspects authentication traffic via a connector deployed on or near each DC and correlates it with Falcon-agent telemetry already collected from every protected endpoint. Identity-policy enforcement is &lt;em&gt;inline&lt;/em&gt; -- the product can require an MFA challenge or block an authentication at the point of decision rather than emit a post-hoc alert [@crowdstrike-falcon-id]. This is the only commercial product in the survey that does inline enforcement on AD Kerberos and NTLM authentications; it is also the only one that is not bundled with a Microsoft 365 licence.&lt;/p&gt;

The product category that combines runtime detection of identity-targeted attacks (Kerberos forgery, credential theft, lateral movement) with response capabilities (force MFA, disable user, revoke session). Gartner formalised the term in 2022. CrowdStrike Falcon Identity Protection and SentinelOne Singularity Identity are the largest ITDR-positioned products outside the Microsoft stack; MDI plus the Defender XDR remediation actions surface effectively functions as Microsoft&apos;s ITDR offering for tenants already inside the Microsoft 365 estate [@mslearn-mdi-remediation-actions].
&lt;p&gt;&lt;strong&gt;Semperis Directory Services Protector (DSP)&lt;/strong&gt; and the companion &lt;strong&gt;Active Directory Forest Recovery (ADFR)&lt;/strong&gt; product are best known for change-tracking and recovery, layered over a runtime Indicators-of-Compromise and Indicators-of-Exposure detection set that overlaps with MDI&apos;s alert taxonomy on classes like DCSync, DCShadow, and Golden Ticket replay [@semperis-dsp][@semperis-adfr]. DSP tracks AD object changes in near-real-time, fires IoC and IoE alerts on the same primitives MDI watches, and offers post-attack rollback as its primary differentiator; ADFR handles malware-free forest recovery in minutes-to-hours rather than days-to-weeks. The pair is partly complementary, partly overlapping with MDI: DSP catches the post-attack drift (the unauthorised group membership change, the rogue ACL) and offers a rollback path MDI does not have; MDI&apos;s per-principal behavioural baselines and unified Defender XDR incident queue are the differentiator on the in-flight detection axis; ADFR handles &quot;the worst day of your career&quot; forest-recovery scenarios where rebuilding the directory is the only remediation. Many tenants run all three.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SpecterOps BloodHound Enterprise (BHE)&lt;/strong&gt; is the commercial form of the BloodHound 2016 graph model that Andy Robbins, Rohan Vazarkar, and Will Schroeder published at DEF CON 24 [@defcon-six-degrees][@bloodhound-github-specterops][@neo4j-bh]. Pure graph attack-path exposure model: BHE maps the paths that &lt;em&gt;exist&lt;/em&gt; (Tier Zero hygiene, principal-to-principal cross-domain trust paths, Entra to on-prem pivots) rather than alerts on attacks in flight [@specterops-bhe]. Complementary to MDI: BHE tells you the attack path exists in the directory, MDI tells you someone is walking it right now. The SpecterOps team&apos;s &lt;em&gt;Certified Pre-Owned&lt;/em&gt; whitepaper (June 2021) by Will Schroeder and Lee Christensen is the source of the &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;ESC1-ESC8 vocabulary&lt;/a&gt; that downstream MDI ADCS posture assessments map to [@specterops-cpo-pdf][@specterops-cpo-blog].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Sentinel native UEBA&lt;/strong&gt; is the SIEM-side behavioural-baselines product over the broader event corpus that Sentinel ingests. Sentinel UEBA uses machine learning to build dynamic behavioural profiles for users, hosts, IP addresses, applications, and other entities, with named data-source connectors including Defender for Identity [@mslearn-sentinel-ueba]. Sentinel UEBA is the &quot;outside the identity tables&quot; layer -- detection that needs to correlate identity signal with email, endpoint, network, and SaaS signal lives there rather than in the identity tables themselves. The Defender XDR-to-Sentinel connector unifies the surfaces [@mslearn-sentinel-defender-connector].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open-source detection stacks&lt;/strong&gt; -- Sigma rules deployed against Sentinel, Splunk, or Elastic, plus Velociraptor and Wazuh -- can match many of MDI&apos;s pattern-based alerts but cannot match MDI&apos;s per-principal behavioural baselines without significant in-house investment [@sigmahq-github]. The SigmaHQ rule corpus contains over 3,000 detection rules in a vendor-neutral SIEM format. Olaf Hartong&apos;s FalconForce team publishes the &lt;em&gt;FalconFriday&lt;/em&gt; hunting-query repository (MDE-schema KQL queries for DLL injection, COM hijacking, LOLBins, LDAP anomalies, and SMB NULL sessions) -- the operator-side companion to community-built detection libraries [@github-falconfriday][@falconforce-blog].&lt;/p&gt;
&lt;p&gt;MDI is the high-coverage, low-effort identity-threat detection product if you already have Microsoft 365 E5 or E5 Security. The third-party products in this market win on differentiation -- inline enforcement, change-tracking, exposure-graph mastery -- rather than baseline coverage. The interesting question for an architect in 2026 is not which to buy. The interesting question is what MDI, by design, cannot see at all.&lt;/p&gt;
&lt;h2&gt;8. Theoretical Limits -- the Five Structural Ceilings&lt;/h2&gt;
&lt;p&gt;There are attacks no version of MDI will ever detect. Not because Microsoft has not shipped the alert yet, and not because the engineering team has not gotten around to it. Because the alert is structurally impossible.&lt;/p&gt;
&lt;p&gt;Five named ceilings, each anchored to a primary source. Together they are the residual blind-spot inventory every operator should be able to name from memory.&lt;/p&gt;

flowchart TD
    subgraph causes [&quot;Attacker-side cause&quot;]
        C1[&quot;OS does not expose&lt;br /&gt;the credential operation&quot;]
        C2[&quot;Forged ticket is&lt;br /&gt;cryptographically identical&quot;]
        C3[&quot;Wire traffic is wrapped&lt;br /&gt;in an encrypted channel&quot;]
        C4[&quot;Attack pivots through&lt;br /&gt;a forest without a sensor&quot;]
        C5[&quot;Attacker uses real DA&lt;br /&gt;real credentials&quot;]
    end
    subgraph gaps [&quot;Defender-side gap&quot;]
        G1[&quot;Credential Guard wall&quot;]
        G2[&quot;Sapphire Ticket class&quot;]
        G3[&quot;Encrypted-channel DCSync&quot;]
        G4[&quot;Cross-forest tail&quot;]
        G5[&quot;Legitimate principal&lt;br /&gt;non-detection&quot;]
    end
    C1 --&amp;gt; G1
    C2 --&amp;gt; G2
    C3 --&amp;gt; G3
    C4 --&amp;gt; G4
    C5 --&amp;gt; G5
&lt;p&gt;&lt;strong&gt;Ceiling 1 -- the Credential Guard wall.&lt;/strong&gt; Anything the operating system itself cannot see is invisible to MDI. The DCSync class is the canonical example with a twist: &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; isolates the LSASS process so that credentials in memory cannot be scraped from a compromised endpoint, but it does not prevent DRSUAPI-level secret extraction against the DC because the DRSUAPI replication interface is &lt;em&gt;supposed&lt;/em&gt; to return password hashes to legitimate replication partners. MDI catches DCSync by detecting the wire-side pattern (DRSUAPI from a non-DC source), not by Credential Guard&apos;s protection. Anything the OS does not expose in event log, wire traffic, or instrumented API -- a custom kernel driver that reads secrets through a side channel, a hypervisor-level credential extraction on a non-Secured-core host -- is, by construction, outside MDI&apos;s data layer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ceiling 2 -- forged-ticket cryptographic indistinguishability, the Sapphire Ticket.&lt;/strong&gt; This is the most important ceiling, and the one whose permanence the rest of this section orbits.&lt;/p&gt;

A forged Kerberos Ticket Granting Ticket whose Privileged Attribute Certificate (PAC) is a verbatim copy of a legitimate principal&apos;s PAC, obtained via the S4U2self plus User-to-User PAC-copy flow against the target principal and then encrypted with the stolen `krbtgt` key. The technique was disclosed by Charlie Bromberg (Synacktiv / Shutdown) in October 2022 and documented on The Hacker Recipes wiki [@hackerrecipes-sapphire]. The defining property: every byte of the forged ticket&apos;s PAC matches the byte pattern of a ticket the genuine KDC would have issued for the legitimate principal, including the group SID set, the user ID, the logon time, and the authorisation-data fields. The classic Golden Ticket leaves PAC anomalies that MDI&apos;s *Suspected Golden Ticket usage (forged authorization data)* alert fires on; the Sapphire Ticket leaves no PAC anomaly because there is no anomaly to leave.

The Sapphire Ticket attack obtains a target principal&apos;s PAC via the S4U2self plus User-to-User PAC-copy technique -- a Kerberos protocol flow Microsoft published as part of MS-SFU and MS-KILE -- which extracts a genuine PAC into a usable form without ever needing to authenticate as the target. The attacker then forges a new ticket whose PAC is the captured PAC, encrypted with the stolen `krbtgt` key. The mechanical sequence is: S4U2self against the target produces a ticket containing the target&apos;s PAC; the U2U flow lets the attacker decrypt the embedded PAC blob; the attacker then mints a fresh TGT around that PAC with the genuine signing key. The KDC&apos;s signature checks pass because the signing key is real, and the PAC&apos;s structural fields pass because they were lifted from a ticket the genuine KDC just issued. Only the original credential compromise that produced the `krbtgt` hash leaves a trail.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Cryptographic indistinguishability is a permanent class. No future MDI release fixes the Sapphire Ticket without breaking Kerberos itself.&lt;/p&gt;
&lt;/blockquote&gt;

Rotate `krbtgt` twice on a defined cadence -- 90 days is common; some Tier Zero playbooks rotate every 30 days. The &quot;twice&quot; is non-optional: a single rotation leaves the prior `krbtgt` key valid for the duration of any tickets the KDC has previously issued, so the stolen key is still usable for up to 10 hours (or longer, on `MaxRenewAge` extensions). Combine with Authentication Policy Silos for Tier Zero service accounts, Tier Zero access reviews, and Privileged Access Workstations for any administrator who can read `krbtgt`. None of these closes the Sapphire Ticket; together they shrink the window in which a stolen key remains weaponisable. Sample PowerShell for the double rotation is in the Microsoft-published `Reset-KrbTgt` script in the GitHub samples repository [@msdefender-id-github].
&lt;p&gt;&lt;strong&gt;Ceiling 3 -- the encrypted-channel DCSync class.&lt;/strong&gt; When DRSUAPI is wrapped in a transport the on-DC capture cannot decode -- DCSync over LDAPS via a SPN-bound impersonation chain, for instance -- the wire-side pattern recognition that powers the External ID 2006 alert degrades. The structural detector in Section 6.3 catches the unencrypted case; the encrypted case requires either a different observation surface (the DRSUAPI handler&apos;s own instrumentation) or behavioural baselining on the post-fact replication-log signal. MDI&apos;s coverage in this case is partial, not complete.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ceiling 4 -- the cross-forest under-instrumentation tail.&lt;/strong&gt; MDI sees the forests its sensors are deployed in. Pivot through an external trust to a forest without MDI coverage and the signal is incomplete -- the attacker&apos;s pre-pivot reconnaissance, the actual trust traversal, and any post-pivot actions on the trusting side that do not also touch an MDI-monitored forest will be invisible. This is a deployment property, not a product property: a tenant with MDI on every forest in its environment does not have this ceiling. A tenant whose acquisition portfolio includes three forests it does not yet monitor does.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ceiling 5 -- legitimate-principal compromise non-detection.&lt;/strong&gt; When the attacker uses a real Domain Admin&apos;s real credentials, every action is behaviourally indistinguishable from the legitimate principal unless timing, geolocation, or device fingerprint breaks the baseline. The 2025 and 2026 &lt;em&gt;Suspected session cookie theft&lt;/em&gt; and related XDR-format alerts close part of this gap by adding behavioural side channels that the older Azure ATP alert catalogue did not cover [@mslearn-mdi-alerts-xdr]. The residual is permanent: a sufficiently disciplined attacker operating from the legitimate principal&apos;s normal workstation, during the legitimate principal&apos;s normal hours, doing things the legitimate principal might plausibly do, is, by construction, indistinguishable from the legitimate principal.&lt;/p&gt;
&lt;p&gt;A sixth honourable mention sits adjacent to these five: &lt;strong&gt;out-of-band physical access&lt;/strong&gt; -- a stolen &lt;code&gt;Ntds.dit&lt;/code&gt; backup, an attacker-controlled DC&apos;s offline export, supply-chain firmware compromise on the DC hardware -- is outside the data layer MDI operates over. The hardware-trust-root community owns this class of mitigation, not the identity-threat detection community.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The five structural ceilings are knowable, not surprises. A SOC that names them ahead of time has a better incident-response runbook than one that does not -- specifically, the runbook for &quot;we just realised the attacker used a Sapphire Ticket&quot; is fundamentally different from the runbook for &quot;MDI fired and we ignored it.&quot; The first runbook starts with &lt;code&gt;krbtgt&lt;/code&gt; rotation and Tier Zero hygiene review; the second starts with disciplinary review and SOAR-rule tuning. Knowing which runbook to pick depends on naming the ceiling correctly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These five named residuals are why the rest of the article exists. If MDI caught everything, the operator playbook in Section 10 would be unnecessary. Because MDI does not, and because the gaps are knowable, the playbook in Section 10 is the difference between MDI as a licence line item and MDI as a working part of the SOC&apos;s day. But before the playbook, one last open-problem inventory: where is the research roadmap actually working?&lt;/p&gt;
&lt;h2&gt;9. Open Problems -- What the Research Roadmap Is Working On&lt;/h2&gt;
&lt;p&gt;Five open problems sit between the 2026 floor and a hypothetically perfect identity-threat detector. Each one has a current best partial result and a citation. None of them is closed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Problem 1 -- the post-PKINIT NTLM-relay class beyond ESC8.&lt;/strong&gt; Synacktiv&apos;s &lt;em&gt;Understanding and evading Microsoft Defender for Identity PKINIT detection&lt;/em&gt; paper (Guillaume Andre, 2024) reverse-engineered MDI&apos;s PKINIT-class detection: MDI fingerprints offensive-tool-generated AS-REQ messages by the encryption types they advertise, which differ from the encryption-type list a legitimate Windows API PKINIT request generates [@synacktiv-pkinit-evasion][@synacktiv-pkinit-evasion-archive]. The companion &lt;code&gt;Invoke-RunAsWithCert&lt;/code&gt; PowerShell tool generates AS-REQ messages via the Windows API itself, producing requests structurally identical to legitimate enterprise PKINIT authentication and bypassing the fingerprint-based detection [@synacktiv-runascert-gh][@deepwiki-runascert]. Aura Security&apos;s follow-on writeup confirms the technique against the current MDI version and walks through modifying Certipy to produce matching AS-REQ shapes [@aurainfosec-mdi-pkinit]. The partial mitigation in 2026 is the additional posture-side coverage in the nine MDI Certificates assessments, which closes some of the configurations the offensive tools target [@mslearn-mdi-certificates-posture]. The runtime detection arms race continues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Problem 2 -- the graph-layer transition from SAM-R LMP to Identity Explorer.&lt;/strong&gt; Section 6.4 covered the deprecation of SAM-R-based LMP discovery in May 2025 (MC1073068) and the two replacement surfaces: the Defender XDR attack-path exploration driven by Defender for Cloud&apos;s CSPM engine, and the April 2026 Identity Explorer Preview on the Sentinel data lake [@handsontek-mc1073068][@mslearn-defenderforcloud-attack-path][@mslearn-mdi-whats-new][@mslearn-xdr-hunting-graph]. The honest open question is whether either surface reproduces, in 2026, the operator workflows the seven-year-old SAM-R-derived LMP report had built up around itself. The Defender XDR hunting graph is richer than the LMP report ever was, but its data model is different; the Identity Explorer is closer in spirit but in Preview rather than GA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Problem 3 -- the Sentinel data lake correlation and the Identity Explorer GA path.&lt;/strong&gt; Microsoft Sentinel data lake, the cross-product cold-storage and analytics layer, went public preview in 2025 and ships with up to 12 years of retention in Parquet format, a clean separation of storage and compute, and KQL plus Jupyter notebook query surfaces [@mslearn-sentinel-datalake][@mstc-sentinel-datalake-preview]. Identity Explorer is the first identity-specific surface built on top of the data lake; it is in Preview as of April 2026 with no GA date published. The open problem is whether the data-lake-tier correlation can match the alert-tier MDI quality for long-running attacker dwell -- the &lt;em&gt;months between Sapphire Ticket use and discovery&lt;/em&gt; class -- without producing more noise than signal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Problem 4 -- the MDI evasion research arms race.&lt;/strong&gt; Synacktiv&apos;s two papers (the sensor primer by Andre and Benassouli in 2022; the PKINIT evasion paper by Andre in 2024) plus the operator notes on alert-timing exploitation that show up in adsecurity.org and SpecterOps content are the public record of the offensive-research community&apos;s targeting of MDI specifically [@synacktiv-primer-mdi][@synacktiv-primer-mdi-archive][@synacktiv-pkinit-evasion][@synacktiv-pkinit-evasion-archive]. FalconForce&apos;s reverse-engineering of the MDE sensor (via Olaf Hartong&apos;s MDE Internals series) is the methodological precedent for the same approach against MDI; the FalconForce blog and the FalconFriday hunting-query repository are the operator-facing primaries [@falconforce-mde-0x02][@falconforce-mde-0x03][@falconforce-blog][@github-falconfriday][@github-olafhartong]. The Charlie Bromberg Sapphire Ticket disclosure (October 2022) is the cryptographic-attack-class research that Section 8&apos;s third ceiling rests on [@hackerrecipes-sapphire]. The arms-race property is permanent; the defensive product team&apos;s job is to keep the detection-shipping cadence faster than the evasion-shipping cadence, which the cloud rewrite (see Section 5) made structurally possible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open Problem 5 -- the non-Windows directory coverage tail.&lt;/strong&gt; MDI covers Active Directory and (via the Microsoft Entra Connect sensor) the on-prem-to-Entra-ID sync surface. Native Entra ID attacks (token theft against Entra ID itself, OAuth consent phishing, Conditional Access bypass) are covered by Defender for Cloud Apps and Entra ID Protection, not by MDI. The boundary between MDI&apos;s scope and the adjacent products is operationally meaningful: a SOC operator reading &quot;MDI did not fire&quot; on an Entra-ID-only attack should not conclude the attack went undetected -- another product likely did fire, in another part of the same Defender XDR portal. The unified incident queue stitches the alerts together; the operator&apos;s mental model has to know which sensor surface to look at when triaging.&lt;/p&gt;
&lt;p&gt;The article does &lt;em&gt;not&lt;/em&gt; claim &quot;BloodHound CE forced MDI to add ADCS detections in 2024.&quot; The framing is parallel evolution: as BloodHound CE expanded ADCS attack-path coverage in 2024-2025, MDI extended its ADCS posture assessments and PKINIT-class runtime detections during the same window. The two product communities watch each other; neither one &quot;forces&quot; the other.&lt;/p&gt;
&lt;p&gt;The roadmap is real, the build-out is in progress, and the operator decision in 2026 is not &quot;wait for the perfect product.&quot; It is &quot;deploy what works now, and cover the residuals with KQL.&quot;&lt;/p&gt;
&lt;h2&gt;10. The MDI Deployment and Triage Playbook&lt;/h2&gt;
&lt;p&gt;Four lanes, mapped to four operator personas: the architect who designs the sensor footprint, the SOC analyst who triages the alerts, the threat hunter who writes the KQL that fills the gaps, and everyone who needs to know what does not work.&lt;/p&gt;
&lt;h3&gt;Lane 1 -- sensor placement and prerequisite hygiene&lt;/h3&gt;
&lt;p&gt;Deploy the &lt;strong&gt;v3.x sensor on every domain controller running Windows Server 2019 or later&lt;/strong&gt;, paired with the MDE agent. The deployment path is the Microsoft Defender portal&apos;s migration wizard or the standalone install via the MDE agent&apos;s onboarding flow [@mslearn-mdi-deploy-sensor-v3][@modernsec-v3x][@jeffreyappel-v2v3].&lt;/p&gt;
&lt;p&gt;Deploy the &lt;strong&gt;v2.x sensor&lt;/strong&gt; on every AD FS federation server, every AD CS online issuing certificate authority, and every Microsoft Entra Connect server (both active and staging), unless those roles already run on a domain controller covered by a v3.x sensor with the May 2026 identity-role extension enabled [@mslearn-mdi-prereq-sensor-v2][@mslearn-mdi-whats-new].&lt;/p&gt;
&lt;p&gt;Configure the &lt;strong&gt;required Windows audit subcategories&lt;/strong&gt; via the Group Policy &lt;em&gt;Subcategory Settings&lt;/em&gt; path that the MDI event-collection page enumerates -- &lt;em&gt;Audit Credential Validation&lt;/em&gt;, &lt;em&gt;Audit Kerberos Authentication Service&lt;/em&gt;, &lt;em&gt;Audit Kerberos Service Ticket Operations&lt;/em&gt;, &lt;em&gt;Audit Logon&lt;/em&gt;, &lt;em&gt;Audit Directory Service Access&lt;/em&gt;, &lt;em&gt;Audit Computer Account Management&lt;/em&gt;, plus the additional subcategories for AD CS and AD FS roles. The v3.x sensor includes an &lt;em&gt;Automatic Windows auditing configuration&lt;/em&gt; toggle that uses the Windows LSA audit-policy APIs to set the subcategories directly, eliminating the GPO step [@mslearn-mdi-event-collection].&lt;/p&gt;
&lt;p&gt;Set the &lt;strong&gt;MDI Action Account&lt;/strong&gt; in the Defender portal. The default is LocalSystem impersonation on the sensor host, which works for response actions targeting AD objects (force password reset, disable user). A gMSA-based Action Account is the alternative for tenants that want least-privilege response identities scoped per workspace [@mslearn-mdi-action-accounts][@mslearn-mdi-remediation-actions]. Avoid configuring the same gMSA across multiple sensor hosts -- the documented anti-pattern is to use one Action Account for DC-side actions only.&lt;/p&gt;
&lt;p&gt;Verify the &lt;strong&gt;Microsoft Defender portal role assignments&lt;/strong&gt; so that SOC analysts have the correct read-and-respond permissions on identity alerts. The Microsoft Defender for Identity enterprise application (ID &lt;code&gt;60ca1954-583c-4d1f-86de-39d835f3e452&lt;/code&gt;) is the consent surface for the response actions; tenants that have not granted consent will see &quot;remediation action unavailable&quot; on identity-targeted incidents [@mslearn-mdi-remediation-actions].&lt;/p&gt;
&lt;h3&gt;Lane 2 -- alert triage SLAs&lt;/h3&gt;
&lt;p&gt;The triage matrix maps alert category to response-time target and the named SOC role that owns triage. Numbers below are typical Tier 1 / Tier 2 SOC targets; tune to your environment&apos;s incident-response policy.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alert category&lt;/th&gt;
&lt;th&gt;Response-time target&lt;/th&gt;
&lt;th&gt;Owning SOC role&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;DCSync, DCShadow, Golden Ticket&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;Tier 2 (privileged-account-compromise specialist)&lt;/td&gt;
&lt;td&gt;Treat as confirmed compromise pending evidence to the contrary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AS-REP Roasting, Kerberoasting&lt;/td&gt;
&lt;td&gt;4 hours&lt;/td&gt;
&lt;td&gt;Tier 2&lt;/td&gt;
&lt;td&gt;Higher-FP class; verify offending principal pattern before escalation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NTLM relay (ESC8 class)&lt;/td&gt;
&lt;td&gt;4 hours&lt;/td&gt;
&lt;td&gt;Tier 2&lt;/td&gt;
&lt;td&gt;ADCS-aware; coordinates with CA team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reconnaissance (LDAP / SMB / DNS)&lt;/td&gt;
&lt;td&gt;24 hours&lt;/td&gt;
&lt;td&gt;Tier 1&lt;/td&gt;
&lt;td&gt;Highest-FP class; allowlist legitimate scanners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Honeytoken activity&lt;/td&gt;
&lt;td&gt;1 hour&lt;/td&gt;
&lt;td&gt;Tier 1 plus Tier 2 escalation&lt;/td&gt;
&lt;td&gt;Near-zero FP; any hit is investigation-worthy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two false-positive cleanup patterns appear in nearly every tenant. The Azure AD Connect Cloud Sync service principal -- &lt;code&gt;MSOL_&lt;/code&gt; plus an 8-character random suffix -- legitimately performs DRSUAPI-like operations as part of the hybrid identity sync flow, and will fire DCSync-class alerts unless allowlisted. Legitimate vulnerability scanners (Tenable, Rapid7, Qualys) perform authenticated enumeration that triggers the LDAP and SMB reconnaissance alerts; scanner IPs go in an exclusion list per the Defender XDR portal&apos;s identity-alert tuning surface.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;MDI Action Accounts and Remediation Actions&lt;/strong&gt; surface lets the responder disable a user, force a password reset, revoke an Entra ID session, or mark an account as compromised -- triggered manually from the alert flow or automatically via the Defender XDR &lt;em&gt;automatic attack disruption&lt;/em&gt; engine, which requires 99 percent or higher detector precision before taking containment action [@mslearn-xdr-attack-disruption][@mslearn-mdi-remediation-actions][@mslearn-xdr-investigate-users]. Automatic attack disruption is opt-in per containment action; the conservative default leaves analyst confirmation in the loop for password-reset-class actions and automates disable-user only on the highest-precision detector classes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The cloud-side analytics pipeline aggregates signal across the per-principal baseline window before deciding to emit. Empirically the alert latency is &lt;strong&gt;minutes-cadence, not seconds-cadence&lt;/strong&gt;. Incident response runbooks that assume sub-second alert arrival will be wrong; the operator clock starts when the alert hits the Defender XDR queue, which is itself minutes after the wire-side event. Plan for this in the SLA matrix above -- the &quot;1 hour&quot; target for DCSync starts from the alert timestamp, not the attack timestamp, and the attack itself may have happened five or ten minutes earlier. The Microsoft alerts-overview page is explicit that MDI is &quot;not designed to serve as an auditing or logging solution that captures every single operation or activity on the servers where the sensor is installed; it only captures the data required for its detection and recommendation mechanisms&quot; [@mslearn-mdi-alerts-overview].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Lane 3 -- advanced-hunting queries that fill the gaps&lt;/h3&gt;
&lt;p&gt;Three structural detectors in KQL form, each one targeting a class the named alerts can miss. Each query names the table, the columns, and the threshold tuning the operator will need.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;structural DCSync detector&lt;/strong&gt; runs against &lt;code&gt;IdentityDirectoryEvents&lt;/code&gt; and catches the encrypted-channel case the External ID 2006 alert may miss:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kql&quot;&gt;IdentityDirectoryEvents
| where Timestamp &amp;gt; ago(24h)
| where ActionType == &quot;DRSReplicate&quot;
| extend SourceIP = tostring(parse_json(AdditionalFields).SourceIPAddress)
| where SourceIP !in (&quot;10.0.1.10&quot;, &quot;10.0.1.11&quot;, &quot;10.0.1.12&quot;)   // tenant DC IPs
| where AccountName !startswith &quot;MSOL_&quot; and AccountName !in (&quot;ADConnectSync&quot;)
| project Timestamp, AccountName, SourceIP, TargetDeviceName, AdditionalFields
| order by Timestamp desc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Threshold tuning: keep the time window short (24 hours) for daily triage. Cleanup principals (&lt;code&gt;MSOL_*&lt;/code&gt;, &lt;code&gt;ADConnectSync&lt;/code&gt;, plus any per-tenant sync identities) go in the &lt;code&gt;!startswith&lt;/code&gt; and &lt;code&gt;!in&lt;/code&gt; clauses. The query produces a clean queue of &quot;DRSUAPI replication from a host that should not be doing DRSUAPI.&quot; False-positive class: legitimate Azure AD Connect Cloud Sync service principals; resolve by adding the principal to the allowlist.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;slow-burn Kerberoasting detector&lt;/strong&gt; runs against &lt;code&gt;IdentityLogonEvents&lt;/code&gt; and catches the rate-limited Kerberoast pattern that modern attackers use to stay below the MDI behavioural-baseline threshold:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kql&quot;&gt;IdentityLogonEvents
| where Timestamp &amp;gt; ago(7d)
| where Protocol == &quot;Kerberos&quot;
| where ActionType == &quot;ServiceTicketRequest&quot;
| extend EncType = tostring(parse_json(AdditionalFields).EncryptionType)
| where EncType in (&quot;RC4-HMAC&quot;, &quot;DES-CBC-MD5&quot;)
| summarize SpnCount = dcount(TargetSpn), SpnList = make_set(TargetSpn) by AccountName, bin(Timestamp, 1d)
| where SpnCount &amp;gt; 5     // tune per tenant baseline
| order by Timestamp desc, SpnCount desc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Threshold tuning: the &lt;code&gt;SpnCount &amp;gt; 5&lt;/code&gt; threshold is the load-bearing knob. Tenants with legitimate operational accounts that request many SPNs per day (privileged service accounts running scheduled tasks across many target hosts) will need a higher threshold and an allowlist. The seven-day window catches the slow-burn pattern that a one-hour window misses.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;PKINIT-relay structural detector&lt;/strong&gt; runs against &lt;code&gt;IdentityLogonEvents&lt;/code&gt; and watches for AS-REQ with PA-PK-AS-REQ pre-auth coming from unexpected client subnets:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kql&quot;&gt;IdentityLogonEvents
| where Timestamp &amp;gt; ago(24h)
| where Protocol == &quot;Kerberos&quot;
| where ActionType == &quot;InitialAuthentication&quot;
| extend PreAuth = tostring(parse_json(AdditionalFields).PreAuthType)
| where PreAuth == &quot;PA-PK-AS-REQ&quot;
| extend ClientSubnet = strcat(split(IPAddress, &quot;.&quot;)[0], &quot;.&quot;, split(IPAddress, &quot;.&quot;)[1])
| where ClientSubnet !in (&quot;10.0.5&quot;, &quot;10.0.6&quot;)    // legitimate smartcard subnets
| project Timestamp, AccountName, IPAddress, DeviceName, AdditionalFields
| order by Timestamp desc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Threshold tuning: PKINIT is legitimate when smartcard logon is in use. Identify the legitimate smartcard-issuing subnets and add them to the &lt;code&gt;!in&lt;/code&gt; clause. The residual queue is PKINIT from unexpected sources -- the structural pattern behind both the post-ESC8 NTLM-relay class and the Synacktiv &lt;code&gt;Invoke-RunAsWithCert&lt;/code&gt; evasion class.&lt;/p&gt;
&lt;p&gt;Tenants that want the alert and event corpus in their SIEM as well as in Defender XDR should configure the &lt;strong&gt;MDI to Microsoft Sentinel connector&lt;/strong&gt; through the Defender XDR-to-Sentinel integration; the connector is auto-enabled when Sentinel is onboarded to the Defender portal [@mslearn-sentinel-defender-connector].&lt;/p&gt;
&lt;h3&gt;Lane 4 -- what does NOT work&lt;/h3&gt;
&lt;p&gt;Five named operator myths, each refuted with a one-paragraph structural reason.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Myth 1: &quot;MDI without the DC sensor still catches Kerberos attacks via the Entra ID side.&quot;&lt;/strong&gt; Wrong. The Kerberos protocol layer is on-prem; the analytics require on-DC capture of the AS-REQ / TGS-REQ / AP-REQ exchange. Entra ID&apos;s side of the hybrid auth flow does not carry the same protocol detail. A tenant with MDI licensed but the sensor not deployed on the DCs has no Kerberos detection at all -- the licensed state is necessary but not sufficient.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Myth 2: &quot;Disabling the v2.x sensor on AD FS is fine since it is covered by the DC sensor.&quot;&lt;/strong&gt; Wrong. The AD FS authentication flow generates federation-side events (SAML assertions, OAuth tokens, the Application and Security event logs that AD FS itself writes) that the DC sensor does not see. AD FS deserves its own sensor unless the AD FS role is collapsed onto a domain controller, in which case the May 2026 v3.x identity-role extension covers it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Myth 3: &quot;Defender for Endpoint covers what MDI covers.&quot;&lt;/strong&gt; Wrong. MDE catches endpoint behaviour -- process creation, file access, network connections, registry writes. MDI catches protocol-level Kerberos, NTLM, LDAP, and DRSUAPI patterns. The two products share an agent surface in the v3.x architecture, but the &lt;em&gt;signal classes&lt;/em&gt; are different. An MDE-only deployment will not catch a DCSync from a workstation if MDI is not licensed and the sensor is not deployed; the MDE agent on the DC sees the local process activity but not the wire-side replication call&apos;s source.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Myth 4: &quot;MDI alerts are real-time.&quot;&lt;/strong&gt; Wrong. As Callout in Lane 2 above. The cloud-side batched-emission cadence is minutes-not-seconds, and incident response runbooks need to account for it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Myth 5: &quot;MDI requires no tuning.&quot;&lt;/strong&gt; Wrong. Every environment has unique false-positive patterns from internal tooling that need exclusions. Microsoft ships the default detector thresholds; tenants tune them through the Defender XDR portal&apos;s identity-alert configuration surface. A tenant that has not tuned the recon-alert allowlist for its vulnerability scanners will receive far more noise than signal.&lt;/p&gt;
&lt;p&gt;Coverage, triage, KQL, and humility about what does not work. The four lanes are the difference between MDI as a licence item on a renewal sheet and MDI as a working part of the SOC&apos;s day.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions and Closing&lt;/h2&gt;
&lt;p&gt;Six questions that come up every time MDI is on a whiteboard, each in the misconception-removal pattern: wrong answer named first, then refuted.&lt;/p&gt;

No. See the *common misreading worth fixing* Callout in Section 4: graph-anchored attack-path evaluation in Microsoft&apos;s defensive stack originates in ATA 1.9 (March 2018), and the 2022 anchor in operator memory is the start of the SAM-R-discovery deprecation arc that culminated in MC1073068 in May 2025 [@mslearn-ata-1-9][@handsontek-mc1073068].

Not as one alert per ESC class. The MDI Certificates posture page documents **nine ADCS posture assessments** -- ESC1 (Preview), ESC2, ESC3, ESC4 (template-owner and template-ACL variants), ESC6 (Preview), ESC7, ESC8, ESC11, and ESC15 [@mslearn-mdi-certificates-posture]. The runtime detection surface for the ESC8 NTLM-relay class is the *Suspected NTLM relay attack* alert in the XDR catalogue [@mslearn-mdi-alerts-xdr]. PKINIT-class runtime detection (the post-ESC8 chain) is the AS-REQ encryption-type fingerprint that Synacktiv documented and partially evaded; the August 2023 AD CS sensor release is the prerequisite for posture coverage [@mstc-adcs-sensor][@synacktiv-pkinit-evasion][@synacktiv-pkinit-evasion-archive]. Coverage is &quot;nine posture assessments plus one runtime alert,&quot; not &quot;one alert per ESC1 through ESC15.&quot;

Microsoft has never published the canonical list; community reverse-engineering is the only source. See the *honest provenance of the ETW provider list* Aside in Section 5 for the full provenance (Synacktiv&apos;s November 2022 primer; Olaf Hartong&apos;s FalconForce MDE Internals 0x02 methodology; the Get-TraceLoggingMetadata + Sealighter toolchain) and the snapshot-not-ground-truth framing [@synacktiv-primer-mdi][@falconforce-mde-0x02].

In the cloud since Azure ATP went GA in March 2018 [@mstc-azureatp-ga][@mstc-azureatp-intro]. The on-DC sensor is a thin parser that captures Kerberos / NTLM / LDAP / DRSUAPI on the wire, parses the protocols into structured events, and streams the parsed signal to the multi-tenant cloud backend over HTTPS. The detection logic, the per-principal behavioural baselines, and the alert-emission pipeline all run in the cloud. The legacy on-prem ATA Center model ended with Azure ATP; ATA itself shipped its last release (1.9.3) in September 2020 and Extended Support ends January 2026 [@mstc-ata-eol][@atadocs-versions].

No. The framing is parallel evolution, not a &quot;forcing&quot; relationship. BloodHound CE expanded ADCS attack-path coverage substantially in 2024 and 2025; during the same window MDI extended its ADCS posture assessment surface and added the AD CS sensor release in August 2023 [@mstc-adcs-sensor][@dirteam-sander-aug2023]. Both product communities watch each other -- the Defender team uses BloodHound to red-team its own environments, the SpecterOps team uses MDI when consulting in enterprise Microsoft shops -- but the causal claim &quot;BloodHound forced MDI&quot; is not supported by the public release record. The two communities&apos; work has been concurrent and mutually informing.

Almost. The MITRE-aligned alert catalogue in Section 6.2 covers the most-prevalent offensive primitives. Section 8 names the five structural ceilings that remain by-construction unclosable; *almost* is the load-bearing word.
&lt;p&gt;Friday, 14:35. The watcher on the domain controller has written three named alerts into the Defender XDR queue. The red-team contractor&apos;s &lt;code&gt;Rubeus.exe asreproast&lt;/code&gt; fired &lt;em&gt;Suspected AS-REP Roasting attack&lt;/em&gt; (T1558.004). The junior auditor&apos;s &lt;code&gt;bloodhound-python -c All&lt;/code&gt; fired &lt;em&gt;Security principal reconnaissance (LDAP)&lt;/em&gt;. The Mimikatz DCSync against the SQL host&apos;s service account fired &lt;em&gt;Suspected DCSync attack -- replication of directory services&lt;/em&gt;, External ID 2006, T1003.006. Three alerts. Three MITRE technique IDs. Three rows in a Tier 1 analyst&apos;s queue.&lt;/p&gt;
&lt;p&gt;The watcher&apos;s job is done. Whether the analyst opens the right one first, whether the Tier 2 escalation happens inside the one-hour SLA, whether the response action gets approved before the attacker has moved on -- none of that is MDI&apos;s problem to solve. It is yours.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;microsoft-defender-for-identity-the-defensive-ad-stack-that-sees-what-bloodhound&quot; keyTerms={[
  { term: &quot;DCSync&quot;, definition: &quot;An offensive primitive in which a principal with replication rights uses DRSUAPI&apos;s IDL_DRSGetNCChanges to extract password hashes from a DC; MDI alert External ID 2006, MITRE T1003.006.&quot; },
  { term: &quot;DCShadow&quot;, definition: &quot;Registering a rogue DC via nTDSDSA object creation plus SPN registration, then writing arbitrary updates via legitimate DRSUAPI replication; MDI alerts External ID 2028 and 2029, MITRE T1207.&quot; },
  { term: &quot;Golden Ticket&quot;, definition: &quot;A forged Kerberos TGT minted with the stolen krbtgt key, valid for any principal in the domain; MDI catches via encryption-downgrade and forged-authorisation-data anomalies, MITRE T1558.001.&quot; },
  { term: &quot;Sapphire Ticket&quot;, definition: &quot;A Golden Ticket whose PAC is bit-for-bit identical to a legitimate principal&apos;s PAC (via S4U2self plus U2U PAC copy); cryptographically indistinguishable from a genuine ticket, structurally invisible to PAC-anomaly detectors.&quot; },
  { term: &quot;Lateral Movement Path (LMP)&quot;, definition: &quot;A graph-anchored attack chain through Active Directory; the ATA 1.9 LMP report (March 2018) shipped on SAM-R discovery, which was deprecated in May 2025 via MC1073068.&quot; },
  { term: &quot;Directory Service Account (DSA)&quot;, definition: &quot;The gMSA the MDI v2.x sensor uses for forest-wide AD reads; replaced by LocalSystem impersonation in the v3.x sensor.&quot; },
  { term: &quot;MDI sensor v3.x&quot;, definition: &quot;The October 2025 MDE-integrated sensor; requires Windows Server 2019+, ships inside the MDE SENSE service, capped at 30 percent CPU and 1.5 GB RAM per DC.&quot; },
  { term: &quot;Identity Security Posture Assessment&quot;, definition: &quot;MDI&apos;s posture (non-runtime) detection surface; the AD CS subset enumerates nine ESC posture assessments aligned to the SpecterOps Certified Pre-Owned vocabulary.&quot; },
  { term: &quot;KQL hunting graph&quot;, definition: &quot;The Defender XDR interactive attack-path visualisation surface that operates over the unified hunting schema; the post-LMP replacement for graph-anchored identity attack-path analysis.&quot; },
  { term: &quot;Identity Explorer (Preview)&quot;, definition: &quot;The April 2026 Sentinel-data-lake-backed identity-attack-path surface in the Defender XDR Identity page; uses the hunting graph to visualise lateral movement, privilege escalation, and credential-access risks.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>active-directory</category><category>microsoft-defender</category><category>identity-protection</category><category>threat-detection</category><category>kerberos</category><category>attack-paths</category><category>soc-operations</category><category>windows-security</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>AD Is a Graph: How BloodHound Made Defenders Think Like Attackers</title><link>https://paragmali.com/blog/ad-is-a-graph-how-bloodhound-made-defenders-think-like-attac/</link><guid isPermaLink="true">https://paragmali.com/blog/ad-is-a-graph-how-bloodhound-made-defenders-think-like-attac/</guid><description>From Lambert&apos;s 2015 essay to Microsoft Security Exposure Management in 2024 -- how the attack-path graph became the default model for Active Directory security.</description><pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate><content:encoded>
**AD is a graph.** In April 2015 John Lambert named the missing model in two sentences. In August 2016 Andy Robbins, Rohan Vazarkar, and Will Schroeder shipped the tool that made it operational: BloodHound treats Active Directory as a directed graph of privilege relationships, queries it with Neo4j&apos;s Cypher, and turns weeks of red-team whiteboard work into a 200 ms shortest-path lookup. By November 2024 Microsoft itself shipped the same mental model as Microsoft Security Exposure Management. This article is half tool history (1998 academic attack graphs through OpenGraph 2025) and half graph-theory exposition: property graphs, BFS shortest paths, the edge taxonomy, and the open problem of *weighting* what is currently treated as one BFS hop per privilege.
&lt;h2&gt;1. How do I get from this user to Domain Admin?&lt;/h2&gt;
&lt;p&gt;In 2014, a red-team analyst with a help-desk account inside a 40,000-user Active Directory forest asks the question every red-team analyst asks: &lt;em&gt;is there a path from here to Domain Admins?&lt;/em&gt; The answer takes two analysts five days of PowerView scripts, hand-drawn whiteboard diagrams, and per-host RDP probing. The same question in 2024 is a ninety-character Cypher query that returns in 200 milliseconds.&lt;/p&gt;
&lt;p&gt;What happened in those ten years is the story of one sentence -- &lt;em&gt;defenders think in lists, attackers think in graphs&lt;/em&gt; -- becoming, in turn, a tool, a discipline, and a Microsoft product.&lt;/p&gt;
&lt;p&gt;The 2014 reality was a stack of CSV files. PowerView, the PowerShell enumeration toolkit Will Schroeder first published in August 2014 [@powersploit-repo], could dump every group membership, every &lt;a href=&quot;https://paragmali.com/blog/windows-access-control-25-years-of-attacks/&quot; rel=&quot;noopener&quot;&gt;Access Control Entry&lt;/a&gt;, and every active session from a low-privilege account [@powertools-powerview]. The outputs were rows. Hundreds of thousands of rows. Composing them into a coherent attack path was a job for a marker and a whiteboard, and the join keys were Distinguished Names that wrapped twice across an analyst&apos;s notebook page. Five days to map a single 40,000-user forest was not unusual. It was the price of doing business.&lt;/p&gt;
&lt;p&gt;The 2024 reality is a query. The analyst loads SharpHound&apos;s JSON dump into a Neo4j graph, opens the BloodHound web interface in a browser, types&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cypher&quot;&gt;MATCH p = shortestPath(
  (u:User {name:&apos;HELPDESK@CORP.LOCAL&apos;})-[*1..]-&amp;gt;(g:Group {name:&apos;DOMAIN ADMINS@CORP.LOCAL&apos;})
) RETURN p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and clicks Run. The graph renders. The shortest path is highlighted. The pivot points are circled. Time elapsed: 200 milliseconds on the database, plus a second for the browser to draw the SVG [@bloodhound-ce-repo].&lt;/p&gt;
&lt;p&gt;Whatever happened in those ten years has to be more than a software release. It has to be a change in how the entire community models the problem. The change has a date and a sentence. Both arrived in April 2015. Let us start with the sentence.&lt;/p&gt;
&lt;h2&gt;2. From ACL lists to graphs -- why the model matters&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;An access-control list is not the same as a graph -- and the difference is everything.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Consider five accounts in a hypothetical &lt;code&gt;CORP.LOCAL&lt;/code&gt; forest. Bob, a help-desk operator, has been granted &lt;code&gt;ForceChangePassword&lt;/code&gt; on Carol&apos;s account by a long-departed administrator who once needed to delegate password resets. Carol is a member of &lt;code&gt;Server Operators&lt;/code&gt;. &lt;code&gt;Server Operators&lt;/code&gt;, by default, can log on locally to Domain Controllers and back up the directory database. The Domain Controller hosts the &lt;a href=&quot;https://paragmali.com/blog/krbtgt-the-account-that-owns-active-directory/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;krbtgt&lt;/code&gt; account&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Three rows in three different audit reports. One attack path.&lt;/p&gt;
&lt;p&gt;A per-object Access Control List audit looks at Bob&apos;s row, sees a &lt;code&gt;ForceChangePassword&lt;/code&gt; ACE, and flags it as &quot;an over-broad delegation.&quot; It looks at Carol&apos;s row, sees that she belongs to &lt;code&gt;Server Operators&lt;/code&gt;, and flags it as &quot;a privileged group membership.&quot; It looks at the Domain Controller and sees that &lt;code&gt;Server Operators&lt;/code&gt; has logon rights, which is the default. Nothing in the audit composes the three facts. Reachability is not a property the report computes.&lt;/p&gt;

A set of nodes (vertices) and directed edges (arrows) between them. Each edge points from one node to another. A *path* is a sequence of edges that can be traversed in the direction of their arrows. A node B is *reachable* from a node A if some path leads from A to B.

A property of two nodes A and B in a directed graph: B is reachable from A if there exists a sequence of edges leading from A to B, regardless of length. Reachability is fundamentally a graph property and cannot be answered by inspecting any single edge in isolation.
&lt;p&gt;Now draw the same five accounts as a directed graph. Bob is a node. Carol is a node. &lt;code&gt;Server Operators&lt;/code&gt; is a node. The Domain Controller is a node. The &lt;code&gt;krbtgt&lt;/code&gt; account is a node. There is an edge from Bob to Carol labelled &lt;code&gt;ForceChangePassword&lt;/code&gt;. There is an edge from Carol to &lt;code&gt;Server Operators&lt;/code&gt; labelled &lt;code&gt;MemberOf&lt;/code&gt;. There is an edge from &lt;code&gt;Server Operators&lt;/code&gt; to the Domain Controller labelled &lt;code&gt;CanRDP&lt;/code&gt;. There is an edge from the Domain Controller to &lt;code&gt;krbtgt&lt;/code&gt; labelled &lt;a href=&quot;https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;DCSync&lt;/code&gt;&lt;/a&gt;. Trace the arrows. Bob can reach &lt;code&gt;krbtgt&lt;/code&gt;.&lt;/p&gt;

flowchart LR
    Bob([Bob, help-desk]) --&amp;gt;|ForceChangePassword| Carol([Carol])
    Carol --&amp;gt;|MemberOf| SO([Server Operators])
    SO --&amp;gt;|CanRDP| DC([Domain Controller])
    DC --&amp;gt;|DCSync| Krb([krbtgt])
&lt;p&gt;The graph form makes reachability visually obvious. The list form does not. This is not a presentation difference. It is a data-model difference, and it is the difference that decides whether a tool can answer the question &lt;em&gt;&quot;is there a path from A to B?&quot;&lt;/em&gt; at all.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Reachability is a property of the graph that the list does not, in general, express. This is not a UX difference. It is a data-model difference, and it is the entire reason BloodHound exists.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The sentence that named this gap appeared on April 26, 2015. John Lambert, then a Distinguished Engineer in the Microsoft Threat Intelligence Center, published a short essay to a personal GitHub repository [@lambert-2015-defenders-lists-attackers-graphs]. No peer review. No formal venue. Two declarative opening sentences that every defender attack-path product since has cited approvingly.&lt;/p&gt;

Defenders don&apos;t have a list of assets -- they have a graph. Assets are connected to each other by security relationships. As long as defenders use a list and attackers use a graph, attackers win. -- John Lambert, April 26, 2015.
&lt;p&gt;Lambert then enumerated five concrete classes of &quot;security dependencies&quot; that constitute edges in any real network: shared local-admin passwords; logon scripts on file servers; print-driver propagation from print servers; certificate authorities that mint smart-card logon certificates; and database administrators who run code as a privileged DB process. The essay closed with a defender prescription: &lt;em&gt;&quot;The first step is to visualize your network by turning your lists into graphs.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If the diagnosis is so obvious in retrospect, why was every mainstream AD audit tool from 2000 through 2015 list-shaped? The answer is that the academic literature had the right model but the wrong substrate, and the operator community had the right substrate but the wrong model. The two did not meet until April 2015.&lt;/p&gt;
&lt;h2&gt;3. Attack graphs before BloodHound, 1998 to 2015&lt;/h2&gt;
&lt;p&gt;The phrase &lt;em&gt;attack graph&lt;/em&gt; is older than Active Directory itself.&lt;/p&gt;
&lt;p&gt;In September 1998, two researchers at Sandia National Laboratories presented a paper titled &lt;em&gt;A Graph-Based System for Network-Vulnerability Analysis&lt;/em&gt; at the New Security Paradigms Workshop in Charlottesville, Virginia. The authors, Cynthia Phillips and Laura Painton Swiler, proposed that a network&apos;s worst-case attack was a &lt;em&gt;graph traversal&lt;/em&gt; problem [@phillips-swiler-1998-nspw]. Nodes encoded network states (the set of attacker privileges across the set of hosts). Edges encoded atomic attack steps (an exploit that, given prerequisite privileges, granted new ones). The shortest path from &quot;attacker outside the network&quot; to &quot;attacker has goal asset&quot; was the worst-case attack.&lt;/p&gt;
&lt;p&gt;Phillips and Swiler observed in a now-canonical sentence that &lt;em&gt;&quot;the security of a network is more than the sum of the security of its hosts.&quot;&lt;/em&gt; It is the conceptual ancestor of every attack-path tool that followed.&lt;/p&gt;
&lt;p&gt;Four years later, at IEEE Symposium on Security and Privacy 2002, Oleg Sheyner (then a CMU PhD student) along with Joshua Haines and Richard Lippmann (MIT Lincoln Lab), Somesh Jha (Wisconsin), and Jeannette Wing (CMU) made the construction automatic [@sheyner-et-al-2002-attack-graphs]. They encoded the network and attacker model as an NuSMV model-checker specification, treated the negation of the security goal as a temporal-logic property, and let the model checker generate every counterexample. The union of counterexamples was the attack graph.&lt;/p&gt;
&lt;p&gt;They also proved that the &lt;em&gt;minimum&lt;/em&gt; set of edges whose removal disconnects the attacker from the goal is NP-hard, but admits an O(log n) approximation -- the first asymptotic bound for the defender-hardening problem.&lt;/p&gt;
&lt;p&gt;Sheyner&apos;s companion 2004 thesis -- &lt;em&gt;Scenario Graphs and Attack Graphs&lt;/em&gt;, CMU-CS-04-122 -- remains the most readable book-length treatment of the academic-attack-graph generation [@sheyner-2004-thesis].&lt;/p&gt;
&lt;p&gt;By 2005 the academic line had a scale solution. Xinming Ou, Sudhakar Govindavajhala, and Andrew Appel at Princeton released &lt;strong&gt;MulVAL&lt;/strong&gt; at USENIX Security 2005 [@mulval-usenix-2005], encoding network state and attacker rules as Datalog facts and running them through XSB Prolog. From the paper&apos;s abstract: &lt;em&gt;&quot;Once the information is collected, the analysis can be performed in seconds for networks with thousands of machines.&quot;&lt;/em&gt; NetSPA at MIT Lincoln Lab (2006) and TVA / CAULDRON at George Mason (2003 to 2005) achieved similar scale through different mechanisms.&lt;/p&gt;
&lt;p&gt;In parallel, on the Windows operator side, Sean Metcalf was running adsecurity.org and documenting AD misconfiguration patterns one writeup at a time [@adsecurity-org]. Microsoft was rolling out its Enhanced Security Administrative Environment (&quot;Red Forest&quot;) tiered-administration model -- the predecessor that the Enterprise Access Model later replaced [@ms-enterprise-access-model] -- which was implicitly graph-aware (the entire ESAE prescription is a tier diagram) but never exposed the tier graph as a queryable structure. ESAE was a deployment blueprint, not a tool.&lt;/p&gt;

gantt
    title Three parallel tracks converging on the attack-path graph
    dateFormat YYYY
    axisFormat %Y&lt;pre&gt;&lt;code&gt;section Academic CVE line
Phillips and Swiler NSPW   :a1, 1998, 1999
Sheyner et al. IEEE SP     :a2, 2002, 2003
MulVAL USENIX              :a3, 2005, 2006
NetSPA TVA                 :a4, 2006, 2008

section Windows operator line
adsecurity.org writeups    :b1, 2014, 2016
PowerView                  :b2, 2014, 2016
Lambert essay              :milestone, b3, 2015-04-26, 1d
BloodHound DEF CON 24      :b4, 2016, 2018
AzureHound BloodHound 4.0  :b5, 2020, 2023
BloodHound CE 5.0          :b6, 2023, 2024
ADCS attack paths          :b7, 2024, 2025
Butterfly v6.3             :b8, 2024, 2026
OpenGraph v8.0             :b9, 2025, 2026

section Microsoft defender stack
ESAE Red Forest blueprint  :c1, 2015, 2018
Azure ATP LMPs preview     :c2, 2018, 2020
Defender CSPM attack paths :c3, 2022, 2024
MSEM GA                    :milestone, c4, 2024-11-19, 1d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The April 2015 essay sat between the two tracks. Lambert was inside Microsoft. He had read the academic literature. He worked next to the threat-intelligence teams who watched real intrusions unfold. The essay was the moment the two communities&apos; vocabularies met. The diagnosis was right. The cure was sixteen months away. It would not come from Microsoft, and it would not come from academia. It would come from a red-team consultancy and a free graph database, and it would debut on a Saturday in August at a hacker convention in Las Vegas.&lt;/p&gt;
&lt;h2&gt;4. Defenders evaluating Active Directory as a list of ACLs&lt;/h2&gt;
&lt;p&gt;If you were a Microsoft-aligned AD security engineer in 2013, your job was to read ACLs. One object at a time. Down a list.&lt;/p&gt;
&lt;p&gt;The mainstream defender toolchain of the era was, almost without exception, list-shaped. Microsoft shipped &lt;code&gt;dsacls.exe&lt;/code&gt; and PowerShell&apos;s &lt;code&gt;Get-Acl&lt;/code&gt;; both produced row-oriented output that an analyst read sequentially. The commercial AD-audit market -- NetWrix Auditor [@netwrix-auditor], ManageEngine ADAudit Plus [@manageengine-adaudit-plus], Quest ActiveRoles [@quest-activeroles], and others -- produced HTML reports with one section per directory object, one row per non-default Access Control Entry, and severity classifications based on a fixed checklist of &quot;dangerous rights&quot; (&lt;code&gt;GenericAll&lt;/code&gt;, &lt;code&gt;WriteDacl&lt;/code&gt;, &lt;code&gt;WriteOwner&lt;/code&gt;, and a handful of others).&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s own &lt;em&gt;Best Practices for Securing Active Directory&lt;/em&gt; document codified this approach. Its central recommendation was &lt;em&gt;per-object delegation review&lt;/em&gt;: walk the directory tree, evaluate each object&apos;s ACL against a hardening checklist, and remediate non-default ACEs that exceed the documented privilege model [@ms-best-practices-ad]. The document is excellent at what it sets out to do. What it does not do -- because the format does not permit it -- is compose multi-hop reachability.&lt;/p&gt;
&lt;p&gt;This was the failure mode Lambert described. A help-desk operator with &lt;code&gt;ForceChangePassword&lt;/code&gt; on a junior service account appears as one row in the audit. The junior service account&apos;s &lt;code&gt;MemberOf Server Operators&lt;/code&gt; membership appears in a different report section. The &lt;code&gt;Server Operators&lt;/code&gt; group&apos;s logon rights on the Domain Controller appear in the Domain Controller&apos;s own report. Three findings in three places, with no machinery to compose them. The data model cannot represent the question.&lt;/p&gt;

A reader trained on Phillips and Swiler, Sheyner et al., MulVAL, NetSPA, and TVA might object that *the field already had* graph-based attack-path analysis a decade before BloodHound. True -- in academia. The academic line solved the scale problem (MulVAL: *&quot;seconds for networks with thousands of machines&quot;*) but spoke the wrong vocabulary. Its atomic attack step was a CVE exploit -- a buffer overflow, a format-string bug, a daemon remote code execution. The dominant AD attack primitive is not a CVE. A user with `WriteDacl` on a group is not exploiting any vulnerability; they are using the system as designed. None of MulVAL, NetSPA, or TVA developed an AD-style privilege-graph input format, and the operator community never adopted them. The academic line was substrate-mismatched and delivered as research-PDF tarballs rather than as `git clone`-able tools.
&lt;p&gt;Two communities, both wrong in different ways. The academic one had the right algorithm with the wrong substrate. The operator one had the right substrate with no algorithm at all. The fix was to fuse them. That happened on August 6, 2016.&lt;/p&gt;
&lt;h2&gt;5. The breakthrough -- BloodHound and Six Degrees of Domain Admin&lt;/h2&gt;
&lt;p&gt;Saturday, August 6, 2016. 1:00 PM. DEF CON 24, Track 2, Paris and Bally&apos;s hotel-casinos in Las Vegas [@defcon-24-archive]. Three speakers from Veris Group&apos;s adaptive threat division step on stage: Andy Robbins, Rohan Vazarkar, Will Schroeder. The talk is titled &lt;em&gt;Six Degrees of Domain Admin: Using Graph Theory to Accelerate Red Team Operations&lt;/em&gt; [@defcon24-bloodhound-slides]. The Veris Group team would spin out as SpecterOps the following year, but the August 2016 attribution -- Robbins (&lt;code&gt;@_wald0&lt;/code&gt;), Vazarkar (&lt;code&gt;@CptJesus&lt;/code&gt;), and Schroeder (&lt;code&gt;@harmj0y&lt;/code&gt;) -- is the canonical one [@bloodhound-legacy-repo].&lt;/p&gt;
&lt;p&gt;The talk demonstrated three design decisions that in retrospect look obvious and at the time were not.&lt;/p&gt;
&lt;p&gt;First, &lt;strong&gt;model Active Directory as a directed property graph&lt;/strong&gt;. Nodes are typed security principals (User, Computer, Group, Domain, OU, GPO). Edges are typed privilege relationships (MemberOf, AdminTo, HasSession, GenericAll, GenericWrite, WriteDacl, ForceChangePassword, and others). This was Lambert&apos;s framing made concrete: every ACE that grants a dangerous right becomes an edge from the trustee to the target.&lt;/p&gt;
&lt;p&gt;Second, &lt;strong&gt;reuse Neo4j as the engine&lt;/strong&gt;. Do not build a custom graph database; piggyback on Cypher&apos;s pattern-matching query language. The cost of building a path-finding engine from scratch was non-trivial; the cost of standing up Neo4j was a single Docker container.&lt;/p&gt;
&lt;p&gt;Third, &lt;strong&gt;ship a collector that emits typed JSON edges, not raw NTSecurityDescriptors&lt;/strong&gt;. The collector&apos;s value is the &lt;em&gt;interpretation&lt;/em&gt; of an ACE as a graph edge -- the mapping from a binary security descriptor to the typed edge that says &quot;trustee X has GenericWrite on object Y&quot; is the hard part, and a defender re-creating that mapping per query would lose. SharpHound (initially &lt;code&gt;SharpHound.ps1&lt;/code&gt;, then a C# binary) does the interpretation once at collection time and writes the edges to disk [@bloodhound-ce-repo].&lt;/p&gt;

SharpHound&apos;s enumeration calls are visibly descended from PowerView. The November 2020 SpecterOps blog announcing BloodHound 4.0 acknowledges the lineage explicitly, naming Schroeder&apos;s joint authorship of both projects and crediting PowerView as the data-collection precursor [@specterops-2020-bloodhound-4]. PowerView&apos;s August 2014 release was the substrate that made BloodHound&apos;s August 2016 synthesis possible. The chain is unbroken: enumeration in 2014, framing in April 2015, graph synthesis in August 2016.
&lt;p&gt;The five-day-of-whiteboard-work figure comes from the SpecterOps team&apos;s own internal benchmark from the original DEF CON 24 talk. The 200 ms query latency is the typical 2024 figure on a mid-size enterprise forest of roughly 10^5 nodes and 10^6 edges, retained as the company&apos;s marketing framing across subsequent blog posts.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; BloodHound&apos;s breakthrough was neither an algorithm nor an architecture. It was the decision to &lt;em&gt;interpret&lt;/em&gt; Active Directory&apos;s access-control data as a typed graph and ship that interpretation as a tool the operator community could actually run.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Crucially, the choice to use Neo4j&apos;s free &lt;code&gt;shortestPath()&lt;/code&gt; function rather than building a custom path-finder was a &lt;em&gt;delivery&lt;/em&gt; decision as much as a &lt;em&gt;technical&lt;/em&gt; one. Neo4j already did breadth-first shortest paths. The team did not need to invent anything. The hard work was in the edge taxonomy and the collector, not in the graph database.&lt;/p&gt;
&lt;p&gt;The talk made a promise the rest of the article must now cash: that there is a real algorithm under the hood, that the algorithm has a name, and that the name is not Dijkstra.&lt;/p&gt;
&lt;h2&gt;6. The algorithmic core -- property graphs, Cypher, and shortest paths&lt;/h2&gt;
&lt;p&gt;If you have never written a Cypher query in your life, the next ninety seconds is the entirety of the syntax you need.&lt;/p&gt;

A graph in which both nodes and edges are typed and can carry key-value properties. A node might have type `User` and properties `name=&apos;BOB@CORP.LOCAL&apos;`, `enabled=true`, `pwdlastset=1719234234`. An edge might have type `GenericWrite` and properties `source=&apos;ACE&apos;`, `isacl=true`. This is the data model Neo4j implements and the model BloodHound uses.
&lt;p&gt;A Cypher pattern is a parenthesised node, a bracketed edge, and a parenthesised node, with arrows showing direction. &lt;code&gt;(u:User)-[:MemberOf]-&amp;gt;(g:Group)&lt;/code&gt; reads &quot;find a node &lt;code&gt;u&lt;/code&gt; of type User connected by a MemberOf edge to a node &lt;code&gt;g&lt;/code&gt; of type Group.&quot; A full query has four parts: &lt;code&gt;MATCH&lt;/code&gt; for the pattern, optional &lt;code&gt;WHERE&lt;/code&gt; for filters, &lt;code&gt;RETURN&lt;/code&gt; for the output. That&apos;s it.Cypher patterns visually mimic ASCII graph drawings: parentheses are nodes, square brackets are edges, and the arrow direction matches the edge direction. The syntax was deliberately designed to look like the diagram you would sketch on a whiteboard.&lt;/p&gt;

The pattern-matching query language originally created for the Neo4j graph database. Cypher&apos;s syntax is declarative: you describe the shape of the data you want, and the engine plans the traversal. Since April 2024 Cypher has been the basis of the ISO/IEC 39075:2024 GQL standard -- the first ISO-standardised graph query language [@iso-39075-2024-gql] [@opencypher-home].
&lt;p&gt;Here is the canonical BloodHound query, with annotations:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cypher&quot;&gt;MATCH p = shortestPath(
  (u:User {name:&apos;BOB@CORP.LOCAL&apos;})       // start node: Bob
    -[*1..]-&amp;gt;                            // any number of typed edges
  (g:Group {name:&apos;DOMAIN ADMINS@CORP.LOCAL&apos;})  // end node: Domain Admins
)
RETURN p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;shortestPath()&lt;/code&gt; wrapper tells Neo4j to short-circuit at the first solution. The variable-length quantifier &lt;code&gt;[*1..]&lt;/code&gt; says &quot;one or more edges of any type.&quot; The &lt;code&gt;p =&lt;/code&gt; binds the entire matched path to the variable &lt;code&gt;p&lt;/code&gt;, which the &lt;code&gt;RETURN&lt;/code&gt; then emits as a sequence of node-edge-node triples that the BloodHound frontend renders as an SVG.&lt;/p&gt;
&lt;p&gt;What does &lt;code&gt;shortestPath()&lt;/code&gt; actually run? Here is where the misconception that BloodHound uses Dijkstra needs to die. The current Neo4j Cypher manual is explicit that &lt;code&gt;shortestPath()&lt;/code&gt; runs an unweighted &lt;strong&gt;bidirectional traversal&lt;/strong&gt; -- BFS in the classical sense -- between the source and target nodes [@neo4j-cypher-shortest-paths]. Not Dijkstra. Not A*. BFS.&lt;/p&gt;

A graph-traversal algorithm that explores all nodes at the current depth before proceeding to the next depth. Starting from the source, it visits all 1-hop neighbours, then all 2-hop neighbours, and so on. For unweighted graphs, BFS is guaranteed to find a shortest path (in number of edges) the first time it reaches the target. Worst-case time is O(V + E) where V is the node count and E is the edge count -- the trivial information-theoretic lower bound for any algorithm that must read the input.
&lt;p&gt;Cypher does support weighted shortest paths via the Neo4j Graph Data Science library, but the BloodHound CE distribution does not enable it. There is no natural cost metric on Active Directory privilege edges in 2026; every edge is treated as one hop.&lt;/p&gt;
&lt;p&gt;Why BFS rather than Dijkstra? Dijkstra is BFS&apos;s generalisation to weighted graphs. If your edges have natural costs -- road distances, link latencies, dollar prices -- Dijkstra (with a Fibonacci heap, $O(E + V\log V)$) gives you shortest paths under that cost metric. Active Directory privilege edges do not have a natural cost metric. &lt;code&gt;MemberOf&lt;/code&gt;, &lt;code&gt;GenericAll&lt;/code&gt;, and &lt;code&gt;CanRDP&lt;/code&gt; are all &quot;the attacker can take this step.&quot; Some are easier than others, but quantifying &lt;em&gt;how much&lt;/em&gt; easier is itself an unsolved problem (see Section 11). Treating every edge as one hop is the load-bearing simplification that makes the model tractable.&lt;/p&gt;

Of a binary relation R: the relation R+ that contains the pair (a, c) whenever there is a chain a R b R ... R c. For a graph, the transitive closure tells you, for every pair of nodes, whether one is reachable from the other. BloodHound&apos;s `shortestPath()` queries can be thought of as on-demand evaluation of the transitive closure restricted to one source-target pair.
&lt;p&gt;The per-query complexity is $O(V + E)$, the standard BFS bound from any algorithms textbook. On a mid-size enterprise forest -- roughly 10^5 nodes and 10^6 edges -- a single user-to-group shortest path returns in sub-second wall-clock time.&lt;/p&gt;
&lt;p&gt;The variable-length quantifier &lt;code&gt;[*1..N]&lt;/code&gt; for general path enumeration is a different matter. Cyclic graphs admit exponentially many paths in N, and Neo4j&apos;s documentation explicitly warns that quantified path patterns can return exponentially many results in the worst case [@neo4j-cypher-variable-length]. The &lt;code&gt;shortestPath()&lt;/code&gt; short-circuit avoids this by returning on the first hit; &lt;code&gt;allShortestPaths()&lt;/code&gt; enumerates only paths tied for shortest; unbounded enumeration is intractable on any non-trivial graph.&lt;/p&gt;
&lt;p&gt;A concrete demonstration is in order. The runnable snippet below is a 35-line implementation of unweighted BFS over a six-node toy graph. It returns the shortest path from a &lt;code&gt;helpdesk&lt;/code&gt; user to the &lt;code&gt;domain-admin&lt;/code&gt; group. This is, structurally, the same algorithm Neo4j&apos;s &lt;code&gt;shortestPath()&lt;/code&gt; runs. The numerical answer (&quot;path of length 4&quot;) is the same number BloodHound would report on the same graph.&lt;/p&gt;
&lt;p&gt;{`
// Edges modelled as a typed adjacency list.
const edges = {
  helpdesk:        [{ to: &apos;carol&apos;,          via: &apos;ForceChangePassword&apos; }],
  carol:           [{ to: &apos;serverops&apos;,      via: &apos;MemberOf&apos; }],
  serverops:       [{ to: &apos;dc01&apos;,           via: &apos;CanRDP&apos; }],
  dc01:            [{ to: &apos;krbtgt&apos;,         via: &apos;DCSync&apos; }],
  krbtgt:          [{ to: &apos;domain-admin&apos;,   via: &apos;GoldenTicket&apos; }],
  domain_admin:    []
};&lt;/p&gt;
&lt;p&gt;function shortestPath(start, goal) {
  const queue = [[start]];           // queue holds candidate paths
  const seen  = new Set([start]);    // each node enqueued at most once&lt;/p&gt;
&lt;p&gt;  while (queue.length) {
    const path = queue.shift();      // BFS = FIFO
    const node = path[path.length - 1];
    if (node === goal) return path;
    for (const e of (edges[node] || [])) {
      if (!seen.has(e.to)) {
        seen.add(e.to);
        queue.push([...path, e.to]);
      }
    }
  }
  return null;                       // unreachable
}&lt;/p&gt;
&lt;p&gt;const path = shortestPath(&apos;helpdesk&apos;, &apos;domain-admin&apos;);
console.log(&apos;Path:&apos;, path.join(&apos; -&amp;gt; &apos;));
console.log(&apos;Length:&apos;, path.length - 1, &apos;hops&apos;);
`}&lt;/p&gt;
&lt;p&gt;The algorithm fits on a single screen. The hard work of BloodHound is not in this loop. The hard work is in deciding &lt;em&gt;which edges to insert into the graph in the first place&lt;/em&gt;. That decision -- the edge taxonomy -- is what makes BloodHound a security tool rather than a graph-database demo.&lt;/p&gt;

sequenceDiagram
    participant Client as Cypher client
    participant Planner as Cypher planner
    participant Engine as BFS engine
    participant Graph as Property graph
    Client-&amp;gt;&amp;gt;Planner: MATCH shortestPath(u to g)
    Planner-&amp;gt;&amp;gt;Engine: plan(start=u, end=g, bidirectional=true)
    Engine-&amp;gt;&amp;gt;Graph: expand 1-hop frontier from u
    Engine-&amp;gt;&amp;gt;Graph: expand 1-hop frontier from g
    Graph--&amp;gt;&amp;gt;Engine: neighbours of u, neighbours of g
    Engine-&amp;gt;&amp;gt;Graph: expand 2-hop frontier (both sides)
    Engine-&amp;gt;&amp;gt;Graph: expand 3-hop frontier (both sides)
    Graph--&amp;gt;&amp;gt;Engine: frontiers intersect at node m
    Engine--&amp;gt;&amp;gt;Planner: reconstruct path u to m to g
    Planner--&amp;gt;&amp;gt;Client: return path
&lt;h2&gt;7. The edge taxonomy -- what Active Directory actually looks like as a graph&lt;/h2&gt;
&lt;p&gt;The BloodHound graph is not &lt;em&gt;every privilege relationship in Active Directory.&lt;/em&gt; It is the set of relationships that the SpecterOps team has decided -- by iterative discovery, often in response to specific community-reported abuse primitives -- to model. The taxonomy has grown roughly monotonically since 2016; the rate has accelerated since the BloodHound CE 5.0 reboot in August 2023 [@specterops-2023-bloodhound-ce].&lt;/p&gt;
&lt;p&gt;Eight families dominate the 2026 graph. They map, family by family, onto the substrates of a modern hybrid enterprise.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Group membership.&lt;/strong&gt; &lt;code&gt;MemberOf&lt;/code&gt; is the simplest edge. Cypher&apos;s variable-length quantifier (&lt;code&gt;[:MemberOf*1..]&lt;/code&gt;) walks transitive memberships in one expression, which is why nested-group reachability is a one-liner.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. ACL write-equivalents.&lt;/strong&gt; &lt;code&gt;GenericAll&lt;/code&gt;, &lt;code&gt;GenericWrite&lt;/code&gt;, &lt;code&gt;WriteDacl&lt;/code&gt;, &lt;code&gt;WriteOwner&lt;/code&gt;, &lt;code&gt;Owns&lt;/code&gt;, &lt;code&gt;AllExtendedRights&lt;/code&gt;, &lt;code&gt;ForceChangePassword&lt;/code&gt;, &lt;code&gt;AddSelf&lt;/code&gt;, &lt;code&gt;AddMember&lt;/code&gt;, and &lt;code&gt;AddKeyCredentialLink&lt;/code&gt; (the shadow-credentials primitive). Each names a specific dangerous-right pattern on a directory object&apos;s security descriptor. SharpHound&apos;s interpreter scans the &lt;code&gt;nTSecurityDescriptor&lt;/code&gt; attribute and emits one typed edge per matching ACE.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Sessions.&lt;/strong&gt; &lt;code&gt;HasSession&lt;/code&gt; is the dynamic edge that goes stale fastest. SharpHound enumerates active sessions via &lt;code&gt;NetSessionEnum&lt;/code&gt; and &lt;code&gt;SAMR&lt;/code&gt;; the resulting edges describe &quot;user U is currently logged into computer C.&quot; The graph is whatever the most recent collection captured.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Remote execution rights.&lt;/strong&gt; &lt;code&gt;AdminTo&lt;/code&gt;, &lt;code&gt;CanRDP&lt;/code&gt;, &lt;code&gt;ExecuteDCOM&lt;/code&gt;, &lt;code&gt;CanPSRemote&lt;/code&gt;, &lt;code&gt;SQLAdmin&lt;/code&gt;. Each describes a code-execution primitive granted to a principal on a computer object.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos delegation&lt;/a&gt;.&lt;/strong&gt; &lt;code&gt;AllowedToDelegate&lt;/code&gt; (constrained delegation), &lt;code&gt;AllowedToAct&lt;/code&gt; (resource-based constrained delegation, via &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt;), unconstrained delegation surfaced as node properties on Computer objects, and -- from BloodHound CE v6.3 in December 2024 [@bloodhound-v6-3-release] -- a &lt;code&gt;CoerceToTGT&lt;/code&gt; edge that replaces the older &lt;code&gt;UnconstrainedDelegation&lt;/code&gt; finding for BHE customers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;ADCS&lt;/a&gt; edges (early-access January 2024).&lt;/strong&gt; &lt;code&gt;ADCSESC1&lt;/code&gt; through &lt;code&gt;ADCSESC10&lt;/code&gt;, plus the &lt;strong&gt;&lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge for ESC8&lt;/strong&gt; [@specterops-2024-adcs-bloodhound]. These edges land in BloodHound roughly thirty months after Will Schroeder and Lee Christensen first published the ESC1 to ESC8 catalog in &lt;em&gt;Certified Pre-Owned: Abusing Active Directory Certificate Services&lt;/em&gt; [@specterops-2021-certified-preowned]. Each ADCS edge in BloodHound is the most complex in the taxonomy because each is composed from multiple raw facts (see the traversable / non-traversable discussion below).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. Azure / Entra ID edges&lt;/strong&gt; (via AzureHound, November 20, 2020) [@specterops-2020-bloodhound-4]. &lt;code&gt;AZGlobalAdmin&lt;/code&gt;, &lt;code&gt;AZRoleAssignment&lt;/code&gt;, &lt;code&gt;AZContains&lt;/code&gt;, &lt;code&gt;AZOwns&lt;/code&gt;, &lt;code&gt;AZUserAccessAdministrator&lt;/code&gt;, &lt;code&gt;AZAddSecret&lt;/code&gt;, &lt;code&gt;AZMGAddOwner&lt;/code&gt;, plus AzureRM-side resource roles. Microsoft Entra &lt;a href=&quot;https://paragmali.com/blog/privileged-identity-management-how-a-two-state-role-assignme/&quot; rel=&quot;noopener&quot;&gt;Privileged Identity Management (PIM)&lt;/a&gt; role coverage was added in BloodHound v8.0 in July 2025 [@specterops-2025-opengraph].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;8. OpenGraph custom edges (v8.0, July 29, 2025).&lt;/strong&gt; User-defined edges for arbitrary substrates: GitHub, Snowflake, Microsoft SQL Server, ServiceNow, Tailscale, Duo. The schema is intentionally generic so that a community contributor can ship edges for any system whose privilege model can be drawn as a graph [@bloodhound-opengraph-library].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Family&lt;/th&gt;
&lt;th&gt;Representative edges&lt;/th&gt;
&lt;th&gt;Underlying AD mechanism&lt;/th&gt;
&lt;th&gt;What it gives the attacker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Group membership&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MemberOf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;member&lt;/code&gt; attribute on group object&lt;/td&gt;
&lt;td&gt;Inherits all permissions held by the group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ACL write-equivalents&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GenericAll&lt;/code&gt;, &lt;code&gt;GenericWrite&lt;/code&gt;, &lt;code&gt;WriteDacl&lt;/code&gt;, &lt;code&gt;WriteOwner&lt;/code&gt;, &lt;code&gt;ForceChangePassword&lt;/code&gt;, &lt;code&gt;AddKeyCredentialLink&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Specific dangerous-right ACE patterns in &lt;code&gt;nTSecurityDescriptor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Take control of the target principal (reset password, modify object, plant shadow credentials)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sessions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HasSession&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NetSessionEnum&lt;/code&gt; and &lt;code&gt;SAMR&lt;/code&gt; enumeration on member computers&lt;/td&gt;
&lt;td&gt;Pivot via credential theft from the logged-in user&apos;s memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote execution&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AdminTo&lt;/code&gt;, &lt;code&gt;CanRDP&lt;/code&gt;, &lt;code&gt;ExecuteDCOM&lt;/code&gt;, &lt;code&gt;CanPSRemote&lt;/code&gt;, &lt;code&gt;SQLAdmin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local-admin membership, RDP / DCOM / WinRM / SQL group rights&lt;/td&gt;
&lt;td&gt;Run arbitrary code as the target principal on the target host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kerberos delegation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AllowedToDelegate&lt;/code&gt;, &lt;code&gt;AllowedToAct&lt;/code&gt;, &lt;code&gt;CoerceToTGT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Constrained and resource-based delegation attributes&lt;/td&gt;
&lt;td&gt;Forge service tickets and impersonate other accounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ADCS composite&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ADCSESC1&lt;/code&gt; through &lt;code&gt;ADCSESC10&lt;/code&gt;, &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Certificate template misconfigurations plus CA trust plus enrollment ACEs&lt;/td&gt;
&lt;td&gt;Obtain a certificate usable for authentication as a privileged account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure / Entra&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AZGlobalAdmin&lt;/code&gt;, &lt;code&gt;AZRoleAssignment&lt;/code&gt;, &lt;code&gt;AZAddSecret&lt;/code&gt;, &lt;code&gt;AZOwns&lt;/code&gt;, &lt;code&gt;AZMGAddOwner&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Entra role assignments, AzureRM RBAC&lt;/td&gt;
&lt;td&gt;Cross the on-prem to cloud boundary; pivot via tenant or subscription privileges&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenGraph&lt;/td&gt;
&lt;td&gt;User-defined&lt;/td&gt;
&lt;td&gt;Any substrate the contributor models&lt;/td&gt;
&lt;td&gt;Anything the contributed schema encodes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The ADCS family deserves a closer look because it introduced an important new modelling vocabulary.&lt;/p&gt;

A *traversable* edge is one the shortest-path query can step through directly: `MemberOf`, `ForceChangePassword`, `CanRDP`. A *non-traversable* edge is a precondition relationship that is only exploitable when several others appear together. A certificate template&apos;s `Enroll` ACE is non-traversable on its own; combined with eight other facts about the template, the issuing CA, and the domain&apos;s trust posture, it composes into `ADCSESC1`. The post-processor scans for the full pattern and synthesises a single traversable edge that the BFS can then treat as one hop [@specterops-2024-adcs-bloodhound].
&lt;p&gt;For ESC1 the pattern has nine numbered prerequisites: six template and CA requirements, two enterprise-CA trust facts, and one implicit constraint. None of the nine raw facts is exploitable in isolation. All nine together are. The post-processor&apos;s job is to walk the candidate sub-graphs, check every requirement, and write the composed &lt;code&gt;ADCSESC1&lt;/code&gt; edge when the pattern holds.&lt;/p&gt;
&lt;p&gt;This is a non-trivial graph-modelling contribution because it gives the field a vocabulary for &quot;an edge that is real only as a join over several facts.&quot; It also generalises beyond ADCS: any future attack primitive composed from a fixed pattern of raw facts can be modelled the same way.&lt;/p&gt;
&lt;p&gt;ESC8 -- the &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM relay&lt;/a&gt; primitive against an HTTP-enrollment certificate authority -- is the most delicate case, and the one most commonly mis-modelled in early secondary writeups.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge is a &lt;strong&gt;Group(&lt;code&gt;Authenticated Users&lt;/code&gt;) to Computer(coerced target)&lt;/strong&gt; edge, not a Computer to Computer edge as some early secondary writeups described. The relay-target CA and the certificate template are carried as &lt;em&gt;edge metadata&lt;/em&gt;, not as additional graph nodes. The canonical edge documentation is explicit: &lt;em&gt;Source: Authenticated Users [Group] / Destination: Computer / Traversable: Yes&lt;/em&gt; [@bloodhound-coerce-relay-edge].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The schema correction matters because the source-principal choice affects every shortest-path query that crosses ESC8. If the edge is mis-modelled as Computer to Computer, queries that begin from a low-privilege user account miss the path entirely. The Group-to-Computer schema correctly captures that &lt;em&gt;any authenticated principal&lt;/em&gt; can coerce.&lt;/p&gt;
&lt;p&gt;What the graph does not yet model is also worth naming. The &lt;code&gt;SpecterOps/TierZeroTable&lt;/code&gt; README states it verbatim: &lt;em&gt;&quot;DISCLAIMER: The table does not include all Tier Zero assets yet.&quot;&lt;/em&gt; [@specterops-tier-zero-table] Several edge classes remain partially or fully out of scope; the full enumeration appears in Section 11 (open problems). Coverage expansion is iterative and community-fed; OpenGraph (Section 9) is the structural answer to &quot;where does the graph end?&quot;&lt;/p&gt;

flowchart TD
    subgraph OnPrem[&quot;On-prem Active Directory&quot;]
        Members[&quot;MemberOf, Owns&quot;]
        ACL[&quot;ACL write-equivalents&lt;br /&gt;GenericAll, WriteDacl, ForceChangePassword,&lt;br /&gt;AddKeyCredentialLink&quot;]
        Sessions[&quot;HasSession&quot;]
        Exec[&quot;AdminTo, CanRDP, ExecuteDCOM,&lt;br /&gt;CanPSRemote, SQLAdmin&quot;]
        Krb[&quot;Kerberos delegation&lt;br /&gt;AllowedToDelegate, AllowedToAct, CoerceToTGT&quot;]
    end
    subgraph Entra[&quot;Entra ID and AzureRM&quot;]
        EntraRoles[&quot;AZGlobalAdmin, AZRoleAssignment,&lt;br /&gt;AZAddSecret, AZUserAccessAdministrator,&lt;br /&gt;PIM roles&quot;]
        AzureRM[&quot;AZContains, AZOwns,&lt;br /&gt;AzureRM resource roles&quot;]
    end
    subgraph ADCS[&quot;ADCS composite edges&quot;]
        ESC[&quot;ADCSESC1 to ADCSESC10,&lt;br /&gt;CoerceAndRelayNTLMToADCS&quot;]
    end
    subgraph Open[&quot;OpenGraph user-defined&quot;]
        Custom[&quot;GitHub, Snowflake, SQL Server,&lt;br /&gt;ServiceNow, Tailscale, Duo, custom&quot;]
    end
    OnPrem --&amp;gt; Cypher((Cypher query layer))
    Entra --&amp;gt; Cypher
    ADCS --&amp;gt; Cypher
    Open --&amp;gt; Cypher
&lt;p&gt;If this is what one community modelled, the natural question is: what did Microsoft model? And when?&lt;/p&gt;
&lt;h2&gt;8. The defender adoption -- Microsoft catches up, 2018 to 2024&lt;/h2&gt;
&lt;p&gt;The defender vendor whose product BloodHound was mapping is also a defender vendor with a graph product of its own. Three of them, in fact, shipped in three different years for three different substrates. They are easy to confuse; press releases sometimes do.&lt;/p&gt;
&lt;p&gt;The first arrived on November 27, 2018, when Tali Ash (then a Program Manager on the Azure Advanced Threat Protection team) announced a preview feature called &lt;em&gt;Lateral Movement Paths&lt;/em&gt; (LMPs) in a Microsoft tech-community post [@ms-azure-atp-lmp-2018]. LMPs were a graph-shaped visualisation, but a constrained one: restricted to &quot;sensitive accounts&quot; (a configurable set defaulting to Domain Admins and similar) plus non-sensitive accounts that had shared a session on the same host as a sensitive account.&lt;/p&gt;
&lt;p&gt;The portal rendered one- and two-hop credential-theft pivots as a static SVG. There was no Cypher equivalent, no LMP-export API, and no way to write a custom query. Azure ATP was rebranded &lt;strong&gt;Microsoft Defender for Identity&lt;/strong&gt; in 2020, and the LMP feature came along under the new name [@ms-mdi-lmp-docs].&lt;/p&gt;
&lt;p&gt;Several secondary sources date Lateral Movement Paths to &quot;June 2019,&quot; which corresponds to the general-availability and rebrand window rather than the original preview announcement. The primary Microsoft tech-community post is November 27, 2018; treat the year-not-month for any third-party claim and prefer the November 2018 preview date as the canonical first ship.&lt;/p&gt;
&lt;p&gt;The second arrived in October 2022, when Microsoft Defender for Cloud&apos;s Defender CSPM plan added a &lt;em&gt;cloud security graph&lt;/em&gt; with attack-path analysis (public preview at Ignite October 2022; generally available March 28, 2023) [@ms-defender-cloud-attack-path]. This product is a &lt;em&gt;cloud&lt;/em&gt; attack-path graph: Azure plus AWS plus GCP asset inventory, with inferred edges for permissions, network reachability, vulnerability presence, and internet exposure. It is explicitly &lt;em&gt;not&lt;/em&gt; the Active Directory identity graph; it covers the multi-cloud workload surface.&lt;/p&gt;
&lt;p&gt;A common mistake conflates this 2022-2023 product (Defender for &lt;em&gt;Cloud&lt;/em&gt;) with Microsoft Defender for &lt;em&gt;Identity&lt;/em&gt; (the LMP product from November 2018). The substrate, the team, and the year are all different. Worth flagging here because secondary writeups repeat the confusion often.&lt;/p&gt;

The Microsoft Defender XDR product family is a naming minefield. *Defender for Identity* (MDI) is the on-prem AD identity-threat product; LMPs are its graph view. *Defender for Cloud* (MDC) is the multi-cloud workload-protection product; its CSPM plan ships cloud-security-graph attack-path analysis. *Defender for Endpoint* (MDE) is the EDR product; it does not ship its own attack-path graph but feeds telemetry into MSEM. *Microsoft Security Exposure Management* (MSEM, GA November 19, 2024) is the unified exposure-graph layer that subsumes the others. Four products, four substrates, four ship dates. The naming overlap is unfortunate but the distinctions are real.
&lt;p&gt;The third arrived on November 19, 2024, at the Ignite 2024 keynote in Chicago. Satya Nadella, in the opening keynote, announced that &lt;strong&gt;Microsoft Security Exposure Management&lt;/strong&gt; (MSEM) had reached general availability [@ms-ignite-2024-msem]. MSEM is the product whose attack-path model is &lt;em&gt;structurally equivalent&lt;/em&gt; to BloodHound&apos;s: cross-substrate (identity plus endpoint plus multi-cloud), first-class attack-path objects with choke-point and blast-radius dashboards, and continuous data feed via the Defender XDR signal plane.&lt;/p&gt;

Microsoft&apos;s unified exposure-graph product, generally available November 19, 2024, at Ignite 2024 in Chicago. MSEM ingests telemetry from Defender for Endpoint, Defender for Identity, Defender for Cloud, Entra ID, and the Defender XDR plane into a single graph. Attack paths are first-class objects with three dashboard views: an attack-path list, choke-point analysis (small sets of nodes whose compromise enables disproportionately many downstream paths), and blast-radius (downstream reach of a selected node) [@ms-msem-attack-paths].
&lt;p&gt;The MSEM docs page introduces the model verbatim: &lt;em&gt;&quot;Attack paths in Microsoft Security Exposure Management help you to proactively identify and visualize potential routes that attackers can exploit using vulnerabilities, gaps, and misconfigurations across endpoints, cloud environments, and hybrid infrastructures.&quot;&lt;/em&gt; And, on choke points: &lt;em&gt;&quot;By focusing on these choke points, you can reduce risk by addressing high-impact assets.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The query interface is the Defender XDR portal plus KQL (Kusto Query Language), not Cypher. The graph engine is proprietary; Microsoft does not publish per-query latency numbers or the underlying algorithms. But the model -- nodes, typed edges, attack paths as the unit of analysis, choke-point and blast-radius views -- is the model BloodHound shipped at DEF CON 24 in August 2016.&lt;/p&gt;
&lt;p&gt;The arc takes eight years. From the August 6, 2016 BloodHound talk to the November 19, 2024 MSEM general-availability announcement is eight years and three months. The defender vendor whose product the original BloodHound was mapping ships a defender product whose attack-path model is structurally equivalent to the one a red-team consultancy shipped in a conference talk eight years earlier.&lt;/p&gt;
&lt;p&gt;Microsoft adopted the model. The community kept extending it. By 2026 the frontier is no longer &lt;em&gt;&quot;does the graph exist?&quot;&lt;/em&gt; It is &lt;em&gt;&quot;how do we make the graph weighted, complete, and substrate-independent?&quot;&lt;/em&gt; That is the state of the art.&lt;/p&gt;
&lt;h2&gt;9. State of the art -- Tier Zero, ADCS edges, and OpenGraph, 2023 to 2026&lt;/h2&gt;
&lt;p&gt;By the time MSEM shipped, SpecterOps had already moved past &lt;em&gt;&quot;is there a graph?&quot;&lt;/em&gt; and was asking three sharper questions. Where does the graph end? How do we model attack primitives that compose from raw facts? And does the AD-specific schema even matter?&lt;/p&gt;
&lt;p&gt;The first question is what &lt;em&gt;&quot;Tier Zero&quot;&lt;/em&gt; means. On June 22, 2023, Jonas Bülow Knudsen, Elad Shamir, and Justin Kohler at SpecterOps published &lt;em&gt;What is Tier Zero -- Part 1&lt;/em&gt;, which reframed Microsoft&apos;s tiered-administration concept -- introduced in the 2012-2014 Securing Privileged Access guidance and renamed the Enterprise Access Model with the &quot;Control Plane&quot; vocabulary in December 2020 [@ms-enterprise-access-model] -- as a property &lt;em&gt;of the graph&lt;/em&gt; [@specterops-2023-tier-zero].&lt;/p&gt;
&lt;p&gt;A Tier Zero asset (see Definition below) reframes Microsoft&apos;s tiered concept from &lt;em&gt;the set of things in the high-privilege tier&lt;/em&gt; to &lt;em&gt;the set of things from which the high-privilege tier is reachable&lt;/em&gt;. Microsoft&apos;s own Tier 0 definition -- &lt;em&gt;&quot;Direct Control of enterprise identities... and all the assets in it&quot;&lt;/em&gt; -- becomes a graph property. The two formulations are equivalent if and only if the graph is complete. If the graph is incomplete (which it is), the Tier Zero set computed from the graph is the floor, not the ceiling.&lt;/p&gt;

Any node in the attack-path graph whose compromise lets an attacker reach an administrative privilege in the forest. The companion `SpecterOps/TierZeroTable` GitHub project is the community-maintained inventory; the README discloses that the table is the floor, not the ceiling [@specterops-tier-zero-table].
&lt;p&gt;The Tier Zero definition is the answer to &lt;em&gt;&quot;shortest path to what?&quot;&lt;/em&gt; -- the target side of every BloodHound shortest-path query. Without a defined Tier Zero set, the question has no endpoint.&lt;/p&gt;
&lt;p&gt;The second question is how to model attack primitives that compose. The January 24, 2024 SpecterOps blog by Knudsen formalised this with the traversable / non-traversable edge distinction discussed in Section 7. The mechanism generalises: any attack primitive whose exploitability is a conjunction of raw facts can be encoded as a composed edge that the post-processor synthesises when the pattern is present.&lt;/p&gt;
&lt;p&gt;ESC1, walked through in Section 7, is the canonical example: nine numbered prerequisites that the post-processor checks before writing the composed &lt;code&gt;ADCSESC1&lt;/code&gt; edge [@specterops-2024-adcs-bloodhound]. Subsequent posts in the series extended the same machinery to ESC3, ESC4, ESC6, ESC7, ESC8 (the &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge), ESC9, ESC10, and -- on February 14, 2024 -- ESC13 [@specterops-2024-esc13].&lt;/p&gt;
&lt;p&gt;In December 2024 BloodHound v6.3 introduced an early-access &quot;improved analysis algorithm&quot; internally referred to as &lt;strong&gt;Butterfly&lt;/strong&gt; [@bloodhound-v6-3-release]. Butterfly is the first production attempt at &lt;em&gt;bi-directional impact&lt;/em&gt; analysis. Pre-v6.3 BloodHound Enterprise quantified risk as &quot;&lt;em&gt;who can reach this node?&lt;/em&gt;&quot; (incoming attack-path count). v6.3 also quantifies &quot;&lt;em&gt;who can this node reach if compromised?&lt;/em&gt;&quot; (outgoing blast radius).&lt;/p&gt;
&lt;p&gt;The release notes describe the outcome but not the algorithm: &lt;em&gt;&quot;Improve risk scoring fidelity for all finding types... Measure risk at each individual finding... Support the inclusion of hybrid paths in risk scoring (Azure assets will now contribute to measured risk in AD and vice versa).&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The same release also announced that BloodHound Enterprise had begun migrating off Neo4j onto PostgreSQL as the &lt;em&gt;graph&lt;/em&gt; database, with the release notes reporting &lt;em&gt;&quot;&amp;gt;50% improvement in the time it takes to perform post-processing during the Analysis process.&quot;&lt;/em&gt; Cypher continues to be the query language; the engine underneath changed.&lt;/p&gt;
&lt;p&gt;The third question -- whether the AD-specific schema matters -- got its answer on July 29, 2025, when SpecterOps released BloodHound v8.0 with &lt;strong&gt;OpenGraph&lt;/strong&gt; [@specterops-2025-opengraph]. OpenGraph decouples the graph engine from the AD-specific schema. Users (and SpecterOps partners) define their own node and edge kinds and ingest attack-path data from arbitrary substrates. The initial release included GitHub organisations, Snowflake role hierarchies, Microsoft SQL Server logins, ServiceNow groups, and Tailscale ACLs. Subsequent community contributions extended the library.&lt;/p&gt;

BloodHound OpenGraph is a foundational shift toward... identity risk management across the entire enterprise. -- Justin Kohler, SpecterOps Chief Product Officer, July 29, 2025.
&lt;p&gt;OpenGraph is the closing observation of an arc that began with Phillips and Swiler in 1998: &lt;em&gt;the model is the abstraction; the substrate is whatever your enterprise runs.&lt;/em&gt; The same &lt;code&gt;shortestPath()&lt;/code&gt; that finds Active Directory attack paths now finds attack paths over a GitHub organisation, a Snowflake role hierarchy, or a Microsoft SQL Server login graph, with no engine change. The 2026 BloodHound release (v9.1.0, May 6, 2026, per the public release-notes index [@bloodhound-release-notes-index]) extends OpenGraph and adds incremental edge updates -- the first step toward a streaming graph rather than a snapshot.&lt;/p&gt;
&lt;h2&gt;10. Competing approaches -- BloodHound versus Microsoft versus the alternatives&lt;/h2&gt;
&lt;p&gt;In 2026 no single product covers every substrate. The field is plural.&lt;/p&gt;
&lt;p&gt;A practitioner choosing among attack-path tools answers four questions, in order. What substrate do you need to cover? Self-host or SaaS? Snapshot or continuous? Open query language or vendor portal? The table below assembles the answers on the dimensions a 2026 practitioner actually uses.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Substrate&lt;/th&gt;
&lt;th&gt;Engine&lt;/th&gt;
&lt;th&gt;Query language&lt;/th&gt;
&lt;th&gt;Deployment&lt;/th&gt;
&lt;th&gt;Licensing&lt;/th&gt;
&lt;th&gt;Edge weighting&lt;/th&gt;
&lt;th&gt;ADCS coverage&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;BloodHound CE 9.x&lt;/td&gt;
&lt;td&gt;AD + Entra + AzureRM + OpenGraph&lt;/td&gt;
&lt;td&gt;Neo4j + Postgres app DB&lt;/td&gt;
&lt;td&gt;Cypher&lt;/td&gt;
&lt;td&gt;Self-hosted Docker Compose&lt;/td&gt;
&lt;td&gt;Apache-2.0&lt;/td&gt;
&lt;td&gt;No (unweighted BFS)&lt;/td&gt;
&lt;td&gt;Yes -- ESC1 through ESC10 + ESC8 composite&lt;/td&gt;
&lt;td&gt;Authorised offensive testing + DIY blue team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BloodHound Enterprise&lt;/td&gt;
&lt;td&gt;Same as CE&lt;/td&gt;
&lt;td&gt;PostgreSQL-as-graph (in-progress migration off Neo4j)&lt;/td&gt;
&lt;td&gt;Cypher&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Commercial&lt;/td&gt;
&lt;td&gt;Bi-directional (Butterfly v6.3+); weighting function not public&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Continuous AD/Entra attack-surface management at enterprise scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Adalanche&lt;/td&gt;
&lt;td&gt;AD (on-prem; LDIF or live LDAP)&lt;/td&gt;
&lt;td&gt;In-memory Go&lt;/td&gt;
&lt;td&gt;AQL (GQL-like)&lt;/td&gt;
&lt;td&gt;Single Go binary&lt;/td&gt;
&lt;td&gt;Open source&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (per README)&lt;/td&gt;
&lt;td&gt;Offline / air-gapped analysis from LDIF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Security Exposure Management&lt;/td&gt;
&lt;td&gt;Defender XDR signal: identity + endpoint + multi-cloud + Entra&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;KQL + portal&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Microsoft licensing&lt;/td&gt;
&lt;td&gt;Implicit (filter against exploitability oracle)&lt;/td&gt;
&lt;td&gt;Indirect via MDI signals&lt;/td&gt;
&lt;td&gt;Hybrid Microsoft-substrate unified exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDI Lateral Movement Paths&lt;/td&gt;
&lt;td&gt;On-prem AD (sensitive-account paths only)&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;None -- portal only&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Microsoft licensing&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Implicit via separate MDI alerts&lt;/td&gt;
&lt;td&gt;Default-on credential-hopping detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender for Cloud CSPM attack-path analysis&lt;/td&gt;
&lt;td&gt;Multi-cloud (Azure + AWS + GCP)&lt;/td&gt;
&lt;td&gt;Proprietary&lt;/td&gt;
&lt;td&gt;Cloud Security Explorer + KQL&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Microsoft licensing&lt;/td&gt;
&lt;td&gt;Implicit&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Multi-cloud workload protection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PingCastle / Semperis DSP / ADAudit Plus&lt;/td&gt;
&lt;td&gt;On-prem AD (+ limited Entra)&lt;/td&gt;
&lt;td&gt;None -- list-of-findings&lt;/td&gt;
&lt;td&gt;None -- HTML / portal&lt;/td&gt;
&lt;td&gt;Self-hosted or SaaS&lt;/td&gt;
&lt;td&gt;Commercial / mixed&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Single-finding hygiene only&lt;/td&gt;
&lt;td&gt;Compliance auditing and change tracking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A few rows deserve commentary.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; BloodHound CE ships under &lt;strong&gt;Apache-2.0&lt;/strong&gt; per the current repository [@bloodhound-ce-repo]. The GPL-3.0 license you may see in older treatments applies only to the deprecated BloodHound Legacy v4 repository [@bloodhound-legacy-repo], which was last updated in 2023 and is no longer maintained. The licensing difference is material: GPL-3.0 is copyleft, Apache-2.0 is permissive. Downstream use cases that need permissive licensing should rely on the current CE.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Older blog posts and conference talks frequently call BloodHound CE GPL-3.0. The CE-Legacy LICENSE block does carry the GPL-3.0 copyright header, which is the source of the confusion. The &lt;em&gt;current&lt;/em&gt; CE codebase at github.com/SpecterOps/BloodHound is Apache-2.0; the GPL-3.0 LICENSE applies only to the deprecated Legacy v4 repository.&lt;/p&gt;
&lt;p&gt;Adalanche, by Lars Karlslund, is the load-bearing counter-example to the claim that &quot;the graph model requires Neo4j&quot; [@adalanche-repo]. Adalanche reads AD data from an LDIF dump or live LDAP, builds the graph entirely in process memory, and exposes a web GUI plus an Adalanche Query Language (AQL) -- described in the README as &lt;em&gt;&quot;a GQL-like language that allows for complex queries.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The README&apos;s headline claim is verbatim: &lt;em&gt;&quot;Adalanche gives instant results, showing you what permissions users and groups have in an Active Directory.&quot;&lt;/em&gt; The trade is no continuous monitoring, no multi-user web app, and a smaller community in exchange for zero deployment friction. The model is identical; the engine is replaceable.&lt;/p&gt;
&lt;p&gt;MSEM is the closest Microsoft analogue to BloodHound (see Section 8 for substrate and query interface). Reasonable defenders run &lt;em&gt;both&lt;/em&gt; MSEM and BloodHound (CE or Enterprise) on the same forest. The tools are complementary rather than substitutionary: MSEM brings the EDR plus workload-protection telemetry that BloodHound does not natively ingest, while BloodHound brings the precise AD edge semantics that SpecterOps&apos;s research community has validated. Running both is not double-counting.&lt;/p&gt;
&lt;p&gt;The hygiene scanners -- PingCastle [@pingcastle], Semperis DSP [@semperis-dsp], ManageEngine ADAudit Plus [@manageengine-adaudit-plus] -- are the surviving descendants of the per-object ACL-inspection generation, with risk-scoring layered on top. They are valuable for compliance auditing and change tracking. They do not expose a queryable attack-path graph. The compliance auditor and the attack-path analyst are different personas with different tools.&lt;/p&gt;
&lt;p&gt;If the field is plural and every tool has a gap, what is the shape of the problem that no tool yet solves? The next section is the honest answer.&lt;/p&gt;
&lt;h2&gt;11. Theoretical limits and open problems&lt;/h2&gt;
&lt;p&gt;Some of the gaps in attack-path analysis are engineering gaps. Others are not.&lt;/p&gt;
&lt;p&gt;The single most consequential open problem is &lt;strong&gt;edge weighting&lt;/strong&gt;. BloodHound&apos;s BFS treats every edge as one hop. In reality, &lt;code&gt;MemberOf&lt;/code&gt; is effectively free; &lt;code&gt;ForceChangePassword&lt;/code&gt; requires the attacker to log in as the changed principal afterwards; &lt;code&gt;AddKeyCredentialLink&lt;/code&gt; requires shadow-credential infrastructure; &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; requires an active SMB-coercion primitive, NTLM relay tooling, and an ESC8-vulnerable certificate authority. A shortest-&lt;em&gt;hop&lt;/em&gt; path is not in general the shortest-&lt;em&gt;exploitation-cost&lt;/em&gt; path.&lt;/p&gt;
&lt;p&gt;BloodHound Enterprise v6.3 shipped the Butterfly analysis as the first production attempt to relax this assumption. As the v6.3 release notes acknowledge (see Section 9), Butterfly&apos;s weighting function is not publicly documented [@bloodhound-v6-3-release].&lt;/p&gt;
&lt;p&gt;Academic intuition suggests weighting edges by an exploitation-success probability and computing &lt;em&gt;most-likely-exploited&lt;/em&gt; paths via shortest paths under negative-log-probability weights. The complexity ceiling is well-known: Dijkstra (with non-negative weights) runs in $O(E + V\log V)$ time with a Fibonacci heap; Bellman-Ford handles negative weights at $O(VE)$. Either fits comfortably inside the per-query budget BloodHound already operates within.&lt;/p&gt;
&lt;p&gt;The unsolved part is the &lt;em&gt;empirical calibration&lt;/em&gt;: what numerical weight is the right weight on a &lt;code&gt;ForceChangePassword&lt;/code&gt; edge versus a &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge? There is no published peer-reviewed answer.&lt;/p&gt;
&lt;p&gt;The second open problem is &lt;strong&gt;coverage&lt;/strong&gt;. The &lt;code&gt;TierZeroTable&lt;/code&gt; README is the authoritative self-disclosure: file-system ACLs on member servers, fine-grained GPO delegation, on-host service-account permissions, some Entra conditional-access logic, and cross-tenant Entra B2B trust paths remain partially or fully out of scope [@specterops-tier-zero-table]. This is an &lt;em&gt;engineering&lt;/em&gt; problem -- more collectors, more edge definitions -- rather than an algorithmic one. OpenGraph is the structural answer: shift coverage from &quot;what edges has SpecterOps modelled?&quot; to &quot;what edges has the community contributed to the shared library?&quot; [@bloodhound-opengraph-library].&lt;/p&gt;
&lt;p&gt;The third is &lt;strong&gt;graph privacy&lt;/strong&gt;. A continuously-collected, complete AD privilege graph shipped to a third-party SaaS backend is, in adversarial hands, a pre-computed attack plan for the customer&apos;s forest. Tenant isolation, encryption at rest, SOC 2 and FedRAMP attestation, and customer-managed key encryption do not eliminate the structural risk: a compromised SaaS backend yields the customer&apos;s graph regardless of compliance posture.&lt;/p&gt;
&lt;p&gt;Cryptographic approaches -- homomorphic graph queries, secure multi-party computation for path enumeration -- exist in the theoretical literature but are not in production attack-path products at time of writing. Adalanche and self-hosted BloodHound CE remain the privacy-preserving options at the cost of forgoing continuous monitoring.&lt;/p&gt;
&lt;p&gt;The fourth is the &lt;strong&gt;the graph is alive&lt;/strong&gt; problem. Session edges (&lt;code&gt;HasSession&lt;/code&gt;) go stale in hours. New ACEs, new group memberships, new sessions appear continuously. SharpHound&apos;s snapshot model is yesterday&apos;s view; continuous collectors (BloodHound Enterprise, MSEM agent streams) trade stealth for freshness. The May 6, 2026 release notes describe BloodHound CE&apos;s first move toward a streaming model: &lt;em&gt;&quot;incremental edge updates that reduce unnecessary writes during post-processing&quot;&lt;/em&gt; [@bloodhound-release-notes-index]. No production attack-path tool yet ships a fully streaming graph.&lt;/p&gt;
&lt;p&gt;The fifth is &lt;strong&gt;combinatorial intractability&lt;/strong&gt;. These are not engineering gaps; they are complexity-theoretic facts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Counting all attack paths is #P-complete.&lt;/strong&gt; Leslie Valiant&apos;s 1979 result on the complexity of counting solutions to combinatorial problems applies directly: counting the simple paths between two nodes in a general graph cannot be done in polynomial time unless P = #P [@valiant-1979-permanent]. BloodHound&apos;s path-count UI is necessarily an approximation or a length-truncation; this is the theoretical reason why.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The minimum-edge-cut &quot;defender hardening&quot; problem is NP-hard.&lt;/strong&gt; Choose the smallest set of edges whose removal disconnects the attacker from the goal. Sheyner et al. 2002 proved the result is NP-hard but admits an $O(\log n)$ approximation [@sheyner-et-al-2002-attack-graphs]. BHE choke-point ranking and MSEM choke-point analysis necessarily implement heuristic approximations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Finding regular simple paths is NP-complete.&lt;/strong&gt; Mendelzon and Wood 1995 proved that finding a simple path matching a regular expression over edge labels in a graph database is NP-complete [@mendelzon-wood-1995-dblp]. Cypher&apos;s &lt;code&gt;shortestPath()&lt;/code&gt; does not enforce simple-path semantics, which is why it remains in P; quantified path patterns with &lt;code&gt;DIFFERENT RELATIONSHIPS&lt;/code&gt; semantics (available since Neo4j 5.x and documented in the current Cypher manual [@neo4j-cypher-variable-length]) do enforce simple paths and so cross into the NP-complete regime.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; BloodHound&apos;s per-query algorithm (BFS, $O(V + E)$) is optimal up to constants. The frontier of the field is no longer the algorithm. It is what &lt;em&gt;question&lt;/em&gt; we ask the algorithm: weighted? regular-path? simple-path? bi-directional? cross-substrate? Each open question is a different model, not a different implementation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Three further honest framings deserve a mention.&lt;/p&gt;
&lt;p&gt;First, the &lt;strong&gt;standardisation of OpenGraph edge taxonomies&lt;/strong&gt; is unsettled. Without community convergence on edge naming, different contributors may model the same substrate with incompatible schemas. Historical precedent (MITRE ATT&amp;amp;CK technique IDs, CVE identifiers) suggests that convergence happens when a single high-trust curator becomes the de-facto registry; whether SpecterOps will operate OpenGraph as a vendor-neutral standards body or as a SpecterOps-owned artefact is a governance question, not an algorithmic one.&lt;/p&gt;
&lt;p&gt;Second, the &lt;strong&gt;adversarial robustness of the collector&lt;/strong&gt; is an open question: SharpHound runs as an authenticated principal, and an attacker with prior compromise can poison the collection. There is no closed-form defence.&lt;/p&gt;
&lt;p&gt;Third, the &lt;strong&gt;absence of any public head-to-head benchmark&lt;/strong&gt; of BloodHound CE versus BHE versus Adalanche versus MSEM on the same forest under controlled conditions is structural: Microsoft does not publish per-query latency, SpecterOps publishes only relative improvement claims, and the academic line uses 2005-era hardware figures that are not comparable.&lt;/p&gt;
&lt;h2&gt;12. Practical guide -- running BloodHound today&lt;/h2&gt;
&lt;p&gt;If the previous sections sold you on the model, the next few paragraphs are the minimum you need to stand it up.&lt;/p&gt;
&lt;p&gt;Stand up BloodHound CE with the Docker Compose file in the repository [@bloodhound-ce-repo]. The stack is four containers: a PostgreSQL application database (users, roles, sessions, audit logs, saved queries); a Neo4j graph database holding the property graph; a Go REST API; and a React plus Sigma.js single-page frontend. Five minutes to first boot on a developer laptop. The repository README is the authoritative deployment reference.&lt;/p&gt;
&lt;p&gt;Run &lt;strong&gt;SharpHound&lt;/strong&gt; on a domain-joined Windows host as the collection identity. The default invocation -- &lt;code&gt;SharpHound.exe --CollectionMethods all,GPOLocalGroup&lt;/code&gt; -- enumerates every group membership, every recognised ACL pattern, every active session, every local-admin relationship, and every Kerberos delegation. Run &lt;strong&gt;AzureHound&lt;/strong&gt; with appropriate Entra ID credentials for Entra and AzureRM coverage. Both emit JSON dumps in the same envelope; the BloodHound CE upload tab in the web UI ingests both.&lt;/p&gt;
&lt;p&gt;Open the web UI. The stock pre-built queries are a reasonable starting palette: &lt;em&gt;Find Shortest Paths to Domain Admins&lt;/em&gt;, &lt;em&gt;Find Principals with DCSync Rights&lt;/em&gt;, &lt;em&gt;Find Computers with Unsupported Operating Systems&lt;/em&gt;, and &lt;em&gt;Shortest Paths from Owned Principals to High-Value Targets&lt;/em&gt; (after marking some accounts as owned). Custom Cypher goes in the Cypher tab at the top right; the Section 6 query is a good template.&lt;/p&gt;
&lt;p&gt;The most important interpretation discipline: treat the result as a &lt;em&gt;risk register&lt;/em&gt;, not a vulnerability list. A finding is &quot;Bob can reach Domain Admins via a four-hop path.&quot; The &lt;em&gt;edge&lt;/em&gt; is &quot;Bob has &lt;code&gt;GenericWrite&lt;/code&gt; on Carol.&quot; Closing the edge breaks the finding &lt;em&gt;and&lt;/em&gt; every other path that passed through it. Edges are the unit of remediation, not findings. SpecterOps&apos;s own 2021 customer-anonymous essay &lt;em&gt;Active Directory Attack Paths -- Is It Always This Bad?&lt;/em&gt; reports findings from hundreds of engagements, and the recurring observation across forests is that a small number of high-blast-radius edges explain most of the discovered paths [@specterops-2021-ad-attack-paths].&lt;/p&gt;
&lt;p&gt;A few pitfalls are worth naming. &lt;code&gt;HasSession&lt;/code&gt; collection generates measurable LDAP and SAMR traffic that Microsoft Defender for Identity alerts on; coordinate with the blue team or expect detections. The stealth collection mode trades coverage for traffic volume.&lt;/p&gt;
&lt;p&gt;Unconstrained variable-length Cypher queries (&lt;code&gt;MATCH p=(a)-[*]-&amp;gt;(b)&lt;/code&gt;) can pin Neo4j&apos;s heap; CE&apos;s &quot;protected Cypher&quot; cost limits help but do not eliminate the problem, so prefer &lt;code&gt;shortestPath()&lt;/code&gt; or bound the path length explicitly. The wildcard-principal post-processing for &lt;code&gt;Authenticated Users&lt;/code&gt; and &lt;code&gt;Everyone&lt;/code&gt; requires v6.0 or later to be correct; older versions miscount these edges [@bloodhound-v6-0-release]. And the &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge is Group to Computer, not Computer to Computer, as discussed in Section 7.&lt;/p&gt;

```cypher
MATCH (n)
WHERE n.system_tags CONTAINS &apos;admin_tier_0&apos;
WITH collect(n) AS tier_zero
MATCH p = shortestPath((u:User {enabled:true})-[*1..6]-&amp;gt;(t))
WHERE t IN tier_zero AND NOT u.system_tags CONTAINS &apos;admin_tier_0&apos;
RETURN u.name AS source, t.name AS target, length(p) AS hops
ORDER BY hops ASC
LIMIT 25
```&lt;p&gt;This returns up to 25 enabled non-Tier-Zero users with the shortest paths into Tier Zero. The &lt;code&gt;[*1..6]&lt;/code&gt; bound prevents the pathological cyclic-graph cost explosion. Bound length aggressively until you have indexed your graph.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

BloodHound is dual-use. Authorised defensive use on your own forest, or contracted penetration testing within written scope, is the standard legal posture. Running it against a directory you are not authorised to assess is unlawful in most jurisdictions: the Computer Fraud and Abuse Act in the United States; the Computer Misuse Act 1990 in the United Kingdom; equivalents in most EU jurisdictions. The dual-use posture is fundamental to the tool; the legal posture depends on you.
&lt;p&gt;The tool is the easy part. The hard part is what you do with the answer.&lt;/p&gt;
&lt;h2&gt;13. Frequently asked questions&lt;/h2&gt;
&lt;p&gt;The misconceptions worth disposing of, in order of how often they recur.&lt;/p&gt;

No. BloodHound is the SpecterOps-maintained, evolving set of edge families. File-system ACLs on member servers, fine-grained GPO delegation, on-host service-account permissions, and some Entra conditional-access logic remain partially or fully out of scope. The `SpecterOps/TierZeroTable` README is explicit about this limitation [@specterops-tier-zero-table]. Coverage expansion is iterative and community-fed; OpenGraph is the structural answer to scope generalisation.

The original BloodHound (2016) shipped Neo4j only. The modern BloodHound CE uses *both*: PostgreSQL as the application database (users, roles, sessions, audit logs) and Neo4j as the graph layer [@bloodhound-ce-repo]. BloodHound Enterprise has begun migrating entirely off Neo4j onto PostgreSQL-as-graph (announced in v6.3, December 2024) [@bloodhound-v6-3-release]; Cypher continues to be the query language on the new backend. The model is engine-independent; Adalanche proves the same point by doing it all in process memory in Go [@adalanche-repo].

Authorised defensive use on your own forest, yes. Contracted penetration testing within written scope, yes. Running it against a directory you are not authorised to assess is unlawful in most jurisdictions: the Computer Fraud and Abuse Act in the United States, the Computer Misuse Act 1990 in the United Kingdom, and equivalents in most EU jurisdictions. The dual-use posture is fundamental to the tool; legal compliance is the operator&apos;s responsibility.
&lt;h2&gt;Epilogue&lt;/h2&gt;
&lt;p&gt;The 2014 analyst with the whiteboard and the 2024 analyst with the Cypher query are doing the same work. The unit of analysis has shifted, and once the unit shifts, the field does not go back.&lt;/p&gt;
&lt;p&gt;John Lambert diagnosed it in two sentences in April 2015 [@lambert-2015-defenders-lists-attackers-graphs]. Andy Robbins, Rohan Vazarkar, and Will Schroeder shipped it as BloodHound in August 2016 [@bloodhound-legacy-repo]. SpecterOps extended it through AzureHound in 2020, the CE 5.0 web architecture in 2023, the Tier Zero formalisation in 2023, ADCS composed edges in 2024, Butterfly bi-directional analysis in 2024, and OpenGraph in 2025 [@specterops-2025-opengraph].&lt;/p&gt;
&lt;p&gt;Microsoft validated the model with Lateral Movement Paths in 2018, cloud security graph attack-path analysis in 2022 to 2023, and Microsoft Security Exposure Management at Ignite in 2024 [@ms-msem-attack-paths]. The community that shipped the graph won; the community that kept shipping lists is selling compliance reports to the auditors.&lt;/p&gt;
&lt;p&gt;The frontier in 2026 is not whether to model attacks as a graph -- that argument is settled. The frontier is how to make the graph weighted (so the shortest path approximates the easiest), how to make it complete (so the unmodelled edges shrink toward zero), and how to make it substrate-independent (so the next enterprise primitive worth modelling -- whatever it turns out to be -- can be ingested without changing the engine). Each of these is a research direction with its own asymptotic ceiling, its own engineering practice, and its own community of contributors.&lt;/p&gt;
&lt;p&gt;What started as a sentence in a 1,100-word essay on a personal GitHub repository is now an ISO-standardised query language [@iso-39075-2024-gql], a shipped Microsoft product family, an open-source repository with hundreds of thousands of downloads, and a discipline taught at most major security conferences. The graph wins because the graph is the right model. The right model wins because, eventually, the right model always does.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;bloodhound-attack-path-graph&quot; keyTerms={[
  { term: &quot;Attack-path graph&quot;, definition: &quot;A directed graph whose nodes are security principals and resources and whose edges are privilege relationships an attacker can traverse. Reachability in the graph models multi-hop privilege escalation.&quot; },
  { term: &quot;Directed property graph&quot;, definition: &quot;A graph in which both nodes and edges have types and can carry key-value properties. The data model BloodHound uses.&quot; },
  { term: &quot;Cypher&quot;, definition: &quot;The pattern-matching query language for Neo4j and now the basis of the ISO/IEC 39075:2024 GQL standard.&quot; },
  { term: &quot;Bidirectional BFS&quot;, definition: &quot;Breadth-first search executed simultaneously from source and target, meeting in the middle. The algorithm Neo4j&apos;s shortestPath() runs and the algorithm BloodHound inherits.&quot; },
  { term: &quot;Tier Zero&quot;, definition: &quot;Any node in the attack-path graph whose compromise lets an attacker reach an administrative privilege in the forest. The endpoint of every BloodHound shortest-path query.&quot; },
  { term: &quot;Traversable / non-traversable edge&quot;, definition: &quot;A traversable edge can be stepped through directly by a path query; a non-traversable edge is a precondition fact that, with others, composes into a traversable edge during post-processing. ADCS edges are the canonical example.&quot; },
  { term: &quot;OpenGraph&quot;, definition: &quot;BloodHound&apos;s v8.0 (July 2025) generalisation that decouples the graph engine from the AD-specific schema, admitting user-defined node and edge kinds for arbitrary substrates.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>active-directory</category><category>bloodhound</category><category>graph-theory</category><category>attack-paths</category><category>specterops</category><category>identity-security</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Certified Pre-Owned: AD CS and Active Directory&apos;s Second Trust Root</title><link>https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/</link><guid isPermaLink="true">https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/</guid><description>AD CS ESC1-ESC16: how Microsoft shipped Certificate Services in 2000, what SpecterOps named in 2021, and why the catalog grows faster than the patches.</description><pubDate>Mon, 25 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Microsoft Certificate Services shipped in Windows 2000 Server on February 17, 2000 and was renamed Active Directory Certificate Services in Windows Server 2008.** Its misconfigurations remained admin-tunable knobs without numbered names for twenty-one years. In June 2021, Will Schroeder and Lee Christensen at SpecterOps published *Certified Pre-Owned* and named eight of them ESC1 through ESC8. Through 2025 the community extended the catalog to ESC16 across IFCR, Compass Security, SpecterOps, TrustedSec, and independent researchers, each one abusing one of six primitives: the template, the issuing authority, the transport, the mapping, the authentication step, or the persistence substrate. Two ESCs have cleanly received CVE-class Microsoft patches (EKUwu / ESC15 -&amp;gt; CVE-2024-49019; ESC8 received KB5005413 *hardening guidance* rather than a CVE, and the adjacent Certifried CVE-2022-26923 patches the dNSHostName impersonation chain on the Machine template rather than a numbered ESC); the rest are administrative hardening matters per Microsoft&apos;s Windows Security Servicing Criteria. The KB5014754 strong-mapping rollout closed ESC9 and ESC10 but is bypassed by ESC16. The architectural property -- that every CA in NTAuth is a key parallel to krbtgt that can mint a Domain Admin authenticator -- is not closable by any patch. The operational playbook is to run Locksmith, BloodHound CE, MDI, PSPKIAudit, and Certipy in parallel, ingest CA logs, and prepare a Lane-3 CA rebuild before you need it.
&lt;h2&gt;1. Two Hours, No KRBTGT, No Touch on Tier Zero&lt;/h2&gt;
&lt;p&gt;The operator&apos;s stopwatch reads two hours and seven minutes when the SOCKS proxy lights up with a Ticket-Granting Ticket for the Domain Administrator account. No service was crashed. No LSASS process was touched. No Tier-Zero principal had its password reset. The &lt;a href=&quot;https://paragmali.com/blog/krbtgt-the-account-that-owns-active-directory/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;krbtgt&lt;/code&gt; account hash&lt;/a&gt; from last quarter&apos;s rotation is still good. The certificate that minted the ticket was issued, signed, and logged by the enterprise&apos;s own Certificate Authority -- the one the IT director&apos;s slide deck calls &quot;internal PKI&quot; -- against a template the help desk uses to enroll Wi-Fi clients.&lt;/p&gt;
&lt;p&gt;Walk the chain backwards. The operator joined &lt;code&gt;Domain Users&lt;/code&gt; four hours ago via a phishing payload that never escalated past medium integrity. They ran one tool. Certipy &lt;code&gt;find&lt;/code&gt; enumerated every certificate template the foothold account was permitted to enroll in [@certipy-gh]. One of those templates -- call it &lt;code&gt;WiFi-Auth&lt;/code&gt; -- had three properties: low-privilege enrollment open to &lt;code&gt;Authenticated Users&lt;/code&gt;, the Client Authentication Extended Key Usage attached, and the &lt;code&gt;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&lt;/code&gt; bit flipped on. Certipy &lt;code&gt;req&lt;/code&gt; produced a Certificate Signing Request that supplied &lt;code&gt;DOMAIN\Administrator&lt;/code&gt; as the Subject Alternative Name. The Enterprise CA, doing exactly what its template configured it to do, issued the certificate. Certipy &lt;code&gt;auth -pfx&lt;/code&gt; exchanged the certificate for a TGT via the Public Key Cryptography for Initial Authentication extension to Kerberos. Mimikatz &lt;code&gt;ptt&lt;/code&gt; loaded the TGT into the operator&apos;s session. Domain Admin.&lt;/p&gt;
&lt;p&gt;What did not fire is the part that frustrates the incident response team. There was no Windows Event 4624 for the Administrator account anywhere on the domain. Microsoft Defender for Identity raised no lateral-movement alert. No Pass-the-Ticket detection triggered, because the ticket was minted as fresh PKINIT authentication, not replayed. The only artifact in the entire chain was a single Event ID 4886 in the CA&apos;s issuance log -- the event the SOC&apos;s SIEM does not ingest, because the SOC&apos;s SIEM was built to follow &lt;code&gt;krbtgt&lt;/code&gt; and not to follow PKI.&lt;/p&gt;

RFC 4556&apos;s Public Key Cryptography for Initial Authentication in Kerberos. The protocol extension that lets a Kerberos client present a certificate to a Key Distribution Center and receive a Ticket-Granting Ticket in return. Authored by L. Zhu (Microsoft) and B. Tung (Aerospace), published in June 2006 [@rfc4556]. PKINIT is the authentication step that converts an issued certificate into a TGT, and therefore the step every ESC must cross to convert a misconfigured template into Domain Admin.
&lt;p&gt;The TGT in this scenario is produced by Active Directory&apos;s Key Distribution Center after it validates the certificate against its trusted certificate stores. The KDC does not call back to the CA -- it trusts any certificate signed by a CA published into the forest&apos;s &lt;code&gt;NTAuthCertificates&lt;/code&gt; container. That trust relationship is the load-bearing detail; we will return to it in section eight.&lt;/p&gt;
&lt;p&gt;So how is any of this possible? The operator&apos;s organization rotated krbtgt twice last quarter, runs a top-quartile EDR product, and bought Microsoft Defender for Identity with the AD CS sensor add-on. The simple answer is: rotating krbtgt closes one of the keys that can mint a Domain Admin authenticator in this forest. It does not close the others. The forest has more than one such key, and nobody told the IR plan.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Every domain whose CA can issue authentication certificates has two trust roots that can mint a Domain Admin authenticator, not one. The first is the &lt;code&gt;krbtgt&lt;/code&gt; account hash. The second is the private key of any Certificate Authority published into the forest&apos;s &lt;code&gt;NTAuthCertificates&lt;/code&gt; container. Rotating one does not touch the other. The catalog this article walks through is the community&apos;s attempt to enumerate the misconfigurations that turn the second trust root into a path low-privilege users can walk.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The vocabulary for this surface -- the named techniques, the numbered identifiers, the tool that enumerates them in eleven seconds -- did not exist until June 2021. The misconfigurations did. They had been shipping as customer-tunable knobs in Microsoft&apos;s identity stack since Windows Server 2003. If this surface has been available for twenty-one years, why did it take twenty-one years for someone to give the misconfigurations names?&lt;/p&gt;
&lt;h2&gt;2. Twenty-One Years of Unnamed Knobs&lt;/h2&gt;
&lt;p&gt;February 17, 2000. Windows 2000 Server reaches general availability. Microsoft Certificate Services -- the AD-integrated CA role -- ships as an optional server component on day one [@wikipedia-w2k]. The role is &lt;em&gt;not yet&lt;/em&gt; called Active Directory Certificate Services; that rename arrives with Windows Server 2008. The shipping defaults that the operator in section one just exploited were already buildable on the 2000 release.&lt;/p&gt;

You will see both anchor dates in the literature. Semperis&apos;s CVE-2022-26923 retrospective writes that &quot;In Windows Server 2008, Microsoft introduced AD CS&quot; [@semperis-cve]. The Microsoft Learn current overview describes AD CS as a &quot;Windows Server role for issuing and managing public key infrastructure (PKI) certificates&quot; [@msl-adcs-current] without distinguishing the ship date from the rename date. This article uses the dual anchor: the role *shipped* in 2000 as Microsoft Certificate Services, and was *renamed* Active Directory Certificate Services in 2008. The misconfigurations the ESC catalog enumerates were enabled by Windows Server 2003&apos;s V2 templates and have not been default-off since.
&lt;p&gt;The misconfigurations the catalog later attacks did not all arrive at once. Three Microsoft releases between 2000 and 2008 built the surface piece by piece.&lt;/p&gt;
&lt;p&gt;Windows Server 2003 (general availability April 24, 2003 [@wikipedia-ws2003]) shipped Version 2 (V2) certificate templates, user and computer autoenrollment over the V2 schema, and the AD-stored template store [@msl-ws2003-ca]. Most of the surface ESC1 and ESC4 later attack first appears in this release: &lt;code&gt;msPKI-Certificate-Name-Flag&lt;/code&gt;, the &lt;code&gt;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&lt;/code&gt; bit, per-template DACLs editable in Active Directory Sites and Services, and the modifiable Extended Key Usage list. The Enrollee-Supplies-Subject flag, in particular, is a customer-tunable bit; it ships off by default on the stock templates but is a one-click enable in &lt;code&gt;certtmpl.msc&lt;/code&gt; [@msl-adcs-2012r2]. Microsoft&apos;s documentation warned against it on sensitive templates. It did not warn against it as a numbered identifier.&lt;/p&gt;
&lt;p&gt;Certificate templates have version numbers tied to the Active Directory schema. V1 templates ship with Windows 2000 and are non-modifiable from the GUI. V2 templates ship with Windows Server 2003 and are fully modifiable; they introduce the per-template DACL and the editable &lt;code&gt;msPKI-Certificate-Name-Flag&lt;/code&gt; properties the catalog attacks. V3 templates ship with Windows Server 2008 and add Suite B cryptography support. The catalog mostly attacks V2 templates; ESC15 specifically attacks the residual V1 templates that ship pre-installed and cannot be removed.&lt;/p&gt;
&lt;p&gt;Windows Server 2008 (general availability February 27, 2008 [@wikipedia-ws2008]) renamed the role to Active Directory Certificate Services and added new role services: Online Certificate Status Protocol Responder, Network Device Enrollment Service, Certificate Enrollment Web Service, and Certificate Enrollment Policy Web Service. These role services expanded the transport surface that ESC8 and ESC11 later attack. The Windows Server 2012 R2 documentation page &lt;code&gt;hh831740&lt;/code&gt; became the canonical reference SpecterOps later linked from the 2021 paper [@msl-adcs-2012r2].&lt;/p&gt;
&lt;p&gt;Between 2008 and 2021 Microsoft published hardening guidance for AD CS in several places -- Test Lab Guides, PKI design pages, role-service deployment docs [@msl-pki-design]. The guidance covered template ACLs, manager approval, least-privilege enrollment, and the Enrollee-Supplies-Subject bit. It did not assign numbered identifiers to specific dangerous combinations. It did not appear in MSRC&apos;s vulnerability pipeline. It did not get a Common Vulnerabilities and Exposures registration. The configurations were &lt;em&gt;documented but unnamed&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In 2019, two seeds for the named class appeared. Géraud de Drouas at the French ANSSI published a brief GitHub note that the Active Directory &lt;code&gt;Public-Information&lt;/code&gt; property set includes &lt;code&gt;altSecurityIdentities&lt;/code&gt;, which lets an attacker with that permission map their own certificate onto a privileged user [@dedrouas-altsec]. The note ends with a striking line: &quot;This issue has been responsibly disclosed to MSRC and received a &apos;won&apos;t fix&apos; response.&quot; The same year Microsoft began documenting the &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt; extension in certificate-related KBs, though without making it default-on. The substrate for what would become ESC9, ESC10, and ESC14 was already in place; nobody had named it yet.&lt;/p&gt;
&lt;p&gt;Twenty-one years from the role&apos;s ship date, then. Twenty-one years of admin-tunable knobs. No numbered identifiers, no patch cadence, no scanner enumeration, no MSRC pipeline. Microsoft documented every one of these settings individually, often well; what was missing was the &lt;em&gt;catalog&lt;/em&gt;. Hardening guidance without numbered identifiers produces no defensive prioritization in real enterprises, because enterprise security programs prioritize against catalogs, not against documentation pages [@bollinger-ekuwu]. So what happened in June 2021 that turned a documentation pattern into a catalog?&lt;/p&gt;

flowchart LR
    A[2000&lt;br /&gt;Microsoft Certificate Services&lt;br /&gt;ships in Windows 2000 Server] --&amp;gt; B[2003&lt;br /&gt;V2 templates&lt;br /&gt;and autoenrollment]
    B --&amp;gt; C[2008&lt;br /&gt;Role renamed&lt;br /&gt;Active Directory&lt;br /&gt;Certificate Services]
    C --&amp;gt; D[2019&lt;br /&gt;de Drouas notes&lt;br /&gt;altSecurityIdentities abuse]
    D --&amp;gt; E[June 2021&lt;br /&gt;SpecterOps catalog&lt;br /&gt;ESC1 through ESC8]
    E --&amp;gt; F[2021 to 2022&lt;br /&gt;KB5005413&lt;br /&gt;CVE-2022-26923&lt;br /&gt;KB5014754]
    F --&amp;gt; G[2022 to 2023&lt;br /&gt;ESC9 to ESC12&lt;br /&gt;from Lyak Heiniger Knobloch]
    G --&amp;gt; H[2024&lt;br /&gt;ESC13 to ESC15&lt;br /&gt;Knudsen and Bollinger&lt;br /&gt;CVE-2024-49019]
    H --&amp;gt; I[2025&lt;br /&gt;ESC16&lt;br /&gt;strong-mapping full enforcement]
&lt;h2&gt;3. Six Primitives Every ESC Abuses&lt;/h2&gt;
&lt;p&gt;Before opening the catalog, install the vocabulary. Every ESC -- without exception -- abuses one of six primitives: the template, the issuing authority, the enrollment transport, the certificate mapping, the authentication bridge, and the persistence substrate. Once you have these six names in your head, the sixteen ESCs compose into a small grid.&lt;/p&gt;
&lt;h3&gt;The Template&lt;/h3&gt;
&lt;p&gt;A certificate template is an Active Directory object stored in the &lt;code&gt;CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration&lt;/code&gt; partition that tells an Enterprise CA what kind of certificate to issue and to whom. Templates carry their own DACL controlling who can enroll, who can write, and who can autoenroll. They carry a &lt;code&gt;msPKI-Certificate-Name-Flag&lt;/code&gt; attribute whose bits control how the Subject and Subject Alternative Name fields are populated. They carry an Extended Key Usage list that names what the certificate is permitted to do. And they carry a Manager Approval bit that gates whether issuance is automatic or whether a CA officer must approve each request [@msl-adcs-2012r2].&lt;/p&gt;

The Active Directory-stored object specifying who can request what kind of certificate from an Enterprise CA. Templates carry per-object DACLs (enrollment, autoenrollment, write), a `msPKI-Certificate-Name-Flag` controlling Subject and SAN behavior, an Extended Key Usage list, and a Manager Approval bit. V1 templates (Windows 2000) are non-modifiable; V2 templates (Windows Server 2003) are fully modifiable; V3 templates (Windows Server 2008) add Suite B cryptography.
&lt;p&gt;ESC1, ESC2, ESC3, ESC4, and ESC15 all attack the template. They differ only in which template property is misconfigured. (ESC9 also begins on a template flag, &lt;code&gt;CT_FLAG_NO_SECURITY_EXTENSION&lt;/code&gt;, but its effect lives in the mapping layer; we file it under mapping below, matching SpecterOps&apos;s own Certify taxonomy [@specterops-certify-docs-index].)&lt;/p&gt;
&lt;h3&gt;The Issuing Authority&lt;/h3&gt;
&lt;p&gt;An Enterprise CA is a Windows Server role service that signs certificate requests against published templates. To be trusted for authentication, the CA must be published into the forest&apos;s &lt;code&gt;NTAuthCertificates&lt;/code&gt; container. That container is the single list of CA certificates the Key Distribution Center trusts for PKINIT. The CA carries its own security descriptor controlling who can enroll, who can manage certificates, and who can manage the CA itself. It carries two registry flags that change its issuance behavior: &lt;code&gt;EDITF_ATTRIBUTESUBJECTALTNAME2&lt;/code&gt;, which permits requesters to specify arbitrary Subject Alternative Names, and &lt;code&gt;IF_ENFORCEENCRYPTICERTREQUEST&lt;/code&gt;, which controls whether RPC enrollment requires packet privacy [@compass-esc11]. The 2022 KB5014754 patch introduced &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt;, a Microsoft-specific extension carrying the requester&apos;s Security Identifier; that extension is the load-bearing artifact of the strong-mapping enforcement track [@kb5014754].&lt;/p&gt;

The AD-integrated certificate authority role in AD CS. Publishes certificate templates into Active Directory, processes certificate requests against those templates, and signs issued certificates with its private key. To be trusted for Windows authentication, the CA&apos;s certificate must be present in the forest-wide `NTAuthCertificates` container.

The AD-published container `CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration` listing CA certificates trusted by the Key Distribution Center for client authentication. Any certificate signed by a CA in this container can, given a valid mapping, mint a Kerberos Ticket-Granting Ticket. Publishing a CA into NTAuth is the moment that CA&apos;s private key becomes a trust root parallel to krbtgt.
&lt;p&gt;ESC5, ESC6, ESC7, and ESC16 attack the issuing authority itself -- its DACL, its registry flags, its extension policy. (ESC11&apos;s RPC packet-privacy gap is a CA-side configuration, but its abuse is an NTLM relay; we group it with ESC8 under transport, matching the §5 diagram.)&lt;/p&gt;
&lt;h3&gt;The Enrollment Transport&lt;/h3&gt;
&lt;p&gt;A certificate is requested over a network protocol. The default transport is DCOM/MS-WCCE -- the Windows Client Certificate Enrollment protocol, an RPC-based interface that ships enabled on every Enterprise CA [@ms-icpr-spec]. Additional transports ship as separate role services: HTTP Web Enrollment (IIS-based, with NTLM auth by default), the Certificate Enrollment Web Service (web service, supports basic and Kerberos), the Network Device Enrollment Service (the SCEP gateway), and the Certificate Enrollment Policy Web Service. Each transport is a network attack surface for relay primitives that route a coerced NTLM authentication into a certificate request.&lt;/p&gt;
&lt;p&gt;ESC8 attacks the HTTP Web Enrollment transport. ESC11 attacks the RPC transport. Both are &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM-relay attacks&lt;/a&gt;; they differ only in which transport the relayed authentication targets.&lt;/p&gt;
&lt;p&gt;The CA&apos;s security model distinguishes two rights that look similar but differ in scope. &lt;em&gt;Issue and Manage Certificates&lt;/em&gt; permits the holder to approve pending requests, revoke issued certificates, and read the request store. &lt;em&gt;Manage CA&lt;/em&gt; permits the holder to edit the CA&apos;s own configuration -- including its registry-controlled extension policy and its DACL. ESC7 attacks the latter. The escalation chain that follows ESC7 typically pivots to ESC4 (edit a template) or to issuing a certificate directly via a CA officer&apos;s request-approval right.&lt;/p&gt;
&lt;h3&gt;The Certificate Mapping&lt;/h3&gt;
&lt;p&gt;When a CA issues an authentication certificate, the certificate identifies a principal -- a user or a computer. The Key Distribution Center has to decide which Active Directory principal that certificate represents. Two mappings exist. &lt;em&gt;Implicit mapping&lt;/em&gt; reads the Subject Alternative Name (or the Subject, on older templates) and looks up the principal by User Principal Name. &lt;em&gt;Explicit mapping&lt;/em&gt; reads the AD principal&apos;s own &lt;code&gt;altSecurityIdentities&lt;/code&gt; attribute, which holds one or more X.509 issuer/serial expressions [@dedrouas-altsec]. The May 2022 KB5014754 patch redefined which mappings the KDC accepts: explicit mappings using &lt;code&gt;X509IssuerSerialNumber&lt;/code&gt;, &lt;code&gt;X509SKI&lt;/code&gt;, or &lt;code&gt;X509SHA1PublicKey&lt;/code&gt; are &lt;em&gt;strong&lt;/em&gt;; everything else is &lt;em&gt;weak&lt;/em&gt; and will be rejected once Full Enforcement is active [@kb5014754].&lt;/p&gt;

OID 1.3.6.1.4.1.311.25.2. The Microsoft certificate extension introduced by KB5014754 that embeds the SID of the requesting Active Directory principal directly into the issued certificate. When present, the KDC matches the certificate against the principal whose SID is embedded, defeating SAN-supply attacks like ESC1. The extension is the load-bearing mechanism of strong mapping enforcement.

Per KB5014754, explicit `altSecurityIdentities` entries using the `X509IssuerSerialNumber`, `X509SKI`, or `X509SHA1PublicKey` formats are *strong*. All other formats -- including implicit UPN and SAN matching -- are *weak* and rejected once Full Enforcement mode is active (February 11, 2025 default; legacy-mapping registry override removed September 9, 2025) [@kb5014754]. The strong-mapping track was the single largest Microsoft mitigation of the ESC era.
&lt;p&gt;ESC9, ESC10, ESC13, and ESC14 all attack the mapping. They abuse the gap between what a certificate asserts and which AD principal the KDC binds it to.&lt;/p&gt;
&lt;h3&gt;The Authentication Step&lt;/h3&gt;
&lt;p&gt;This component is the part of Windows that turns a certificate into an authenticator. For &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos&lt;/a&gt;, the protocol is PKINIT (RFC 4556 [@rfc4556]): client presents a cert, KDC validates the cert and the mapping, KDC issues a TGT. For TLS-based services -- LDAPS, RDP with smart card, IIS with client cert -- the protocol is Schannel. For the legacy smart-card pipeline, the path is the combination of the Smart Card Resource Manager and PKINIT.&lt;/p&gt;
&lt;p&gt;No ESC attacks this step directly. Every ESC must &lt;em&gt;cross&lt;/em&gt; it to convert a misconfigured template, ACL, or mapping into a usable authenticator. The authentication step is the choke point; it is also the point Microsoft has reshaped most heavily with KB5014754.&lt;/p&gt;
&lt;h3&gt;The Persistence Substrate&lt;/h3&gt;
&lt;p&gt;An issued certificate is not a transient credential. It is a signed authenticator with a configurable validity period (one year is common, ten years is permitted). The certificate authenticates the embedded principal as long as the certificate is valid and not revoked. That property is what the SpecterOps paper&apos;s &lt;code&gt;DPERSIST&lt;/code&gt; and &lt;code&gt;THEFT&lt;/code&gt; classes attack [@cpo-blog]. UnPAC-the-Hash recovers the NTLM hash from a PKINIT-issued TGT, giving the attacker a password-equivalent credential they did not previously have. The Golden Certificate attack steals the CA&apos;s own private key, granting forever-issuance against the entire forest.&lt;/p&gt;
&lt;p&gt;This article scopes those attacks to a sidebar; the body walks the ESC1 to ESC16 escalation catalog. But every ESC ends in the persistence substrate: the certificate the attacker walks out with is the receipt that survives password rotation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A &lt;em&gt;primitive&lt;/em&gt; is a Microsoft-shipped knob, flag, ACL, or protocol that, when misconfigured, becomes part of an escalation. An &lt;em&gt;exploitation chain&lt;/em&gt; is the specific sequence of operator actions that turns one or more misconfigured primitives into a Domain Admin authenticator. ESCs are exploitation chains, not primitives. ESC1, for example, abuses the &lt;em&gt;template&lt;/em&gt; primitive&apos;s &lt;code&gt;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&lt;/code&gt; bit, combined with the &lt;em&gt;bridge&lt;/em&gt; primitive (PKINIT), to produce the authenticator. The catalog enumerates chains; the six categories above enumerate the substrate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now that the vocabulary is in place, sixteen named attacks compose neatly onto a 6 by 16 grid. Here is the moment they did.&lt;/p&gt;

flowchart TD
    T[Template&lt;br /&gt;per-template DACL&lt;br /&gt;Name-Flag bits&lt;br /&gt;EKU list&lt;br /&gt;Manager Approval]
    A[Issuing Authority&lt;br /&gt;NTAuth membership&lt;br /&gt;CA security descriptor&lt;br /&gt;EDITF flags&lt;br /&gt;extension policy]
    X[Enrollment Transport&lt;br /&gt;RPC/MS-WCCE&lt;br /&gt;HTTP Web Enrollment&lt;br /&gt;CES/CEP&lt;br /&gt;NDES/SCEP]
    M[Certificate Mapping&lt;br /&gt;implicit UPN/SAN&lt;br /&gt;explicit altSecurityIdentities&lt;br /&gt;strong vs weak&lt;br /&gt;SID extension]
    B[Authentication Bridge&lt;br /&gt;PKINIT for Kerberos&lt;br /&gt;Schannel for TLS&lt;br /&gt;smart-card pipeline]
    P[Persistence Substrate&lt;br /&gt;validity period&lt;br /&gt;UnPAC-the-Hash&lt;br /&gt;Golden Certificate&lt;br /&gt;CRL bypass]
    T --&amp;gt; A
    A --&amp;gt; X
    X --&amp;gt; B
    A --&amp;gt; M
    M --&amp;gt; B
    B --&amp;gt; P
&lt;h2&gt;4. Certified Pre-Owned&lt;/h2&gt;
&lt;p&gt;Will Schroeder pushes the SpecterOps Medium post live on June 17, 2021. (A revision tagged &lt;code&gt;[EDIT 06/22/21]&lt;/code&gt; follows the next week; the literature settles on &quot;June 2021&quot; as the canonical date [@cpo-blog].) The whitepaper PDF drops in the same window and is rehosted on the SpecterOps domain the following year [@cpo-whitepaper]. Seven weeks later, on August 5, Schroeder and Christensen present &lt;em&gt;Certified Pre-Owned: Abusing Active Directory Certificate Services&lt;/em&gt; at Black Hat USA 2021. Three GhostPack tools ship to GitHub on schedule: PSPKIAudit for defense [@pspkiaudit-gh], Certify for offense [@certify-gh], and ForgeCert for Golden Certificate work.&lt;/p&gt;
&lt;p&gt;The paper names eight escalation paths and three persistence and theft prefixes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESC1 through ESC8&lt;/strong&gt; -- &lt;em&gt;escalation&lt;/em&gt; paths from a low-privilege foothold to Domain Admin&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DPERSIST&lt;/strong&gt; -- &lt;em&gt;domain persistence&lt;/em&gt; via forged certificates after CA private-key compromise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;THEFT&lt;/strong&gt; -- &lt;em&gt;certificate and credential theft&lt;/em&gt; primitives, including the UnPAC-the-Hash technique&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DETECT&lt;/strong&gt; -- &lt;em&gt;defensive detection&lt;/em&gt; primitives the team mapped to each abuse&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The contribution was not the &lt;em&gt;discovery&lt;/em&gt; of new individual primitives. Most of the individual misconfigurations had appeared in Microsoft&apos;s hardening guidance or in scattered community posts well before the paper. ENROLLEE_SUPPLIES_SUBJECT had been a documented warning for a decade. NTLM relay to IIS had been a known attack class since at least 2008. The &lt;code&gt;EDITF_ATTRIBUTESUBJECTALTNAME2&lt;/code&gt; flag was a documented option in &lt;code&gt;certutil&lt;/code&gt; since Windows Server 2008 R2. What the paper contributed was the &lt;em&gt;unified catalog&lt;/em&gt; -- numbered identifiers, reproducible exploitation, a tool that enumerated each path, and a single document tying every abuse to its primitive and its mitigation.&lt;/p&gt;

While AD CS is not installed by default for Active Directory environments, from our experience in enterprise environments it is widely deployed, and the security ramifications of misconfigured certificate service instances are enormous. -- Will Schroeder and Lee Christensen, *Certified Pre-Owned* (June 2021) [@cpo-blog]
&lt;p&gt;Microsoft&apos;s response was uncharacteristically fast. KB5005413 published in late July 2021 -- roughly six weeks after the blog -- recommending Extended Protection for Authentication and &quot;Require SSL&quot; on the AD CS Web Enrollment and Certificate Enrollment Web Service role services [@kb5005413]. The KB closes ESC8 over HTTPS when EPA is enabled. It does not close ESC1 through ESC7, and it does not close ESC11 (which had not yet been named).&lt;/p&gt;
&lt;p&gt;The &quot;ESC&quot; prefix is an acronym for &lt;em&gt;escalation&lt;/em&gt;. The catalog uses three sibling prefixes from the same paper: &lt;code&gt;DPERSIST&lt;/code&gt; for &lt;em&gt;domain persistence&lt;/em&gt;, &lt;code&gt;THEFT&lt;/code&gt; for credential and certificate theft, and &lt;code&gt;DETECT&lt;/code&gt; for defensive detection identifiers. ESC numbering is consecutive but not contiguous in time -- ESC12 (a hardware substrate attack) was disclosed by Knobloch in October 2023 [@knobloch-esc12] [@knobloch-esc12-archive], four months before Knudsen disclosed ESC13 and ESC14 from SpecterOps. The numbering tracks the order of community disclosure, not a planned roadmap.&lt;/p&gt;
&lt;p&gt;Here is the observation that this article will load-bear: the breakthrough was &lt;em&gt;naming&lt;/em&gt;, not discovery. Until SpecterOps named the eight configurations, every one of them had been documented somewhere in Microsoft Learn or in a community blog. The hardening documentation had existed for years and had produced essentially no defensive prioritization in real enterprises. Microsoft Defender for Identity did not flag ESC1 templates. BloodHound did not graph ESC4-shaped DACLs. SIEMs did not ingest CA Event ID 4886. No commercial scanner shipped a rule for the Enrollee-Supplies-Subject bit. The reason was not that the information was inaccessible. The reason was that the &lt;em&gt;configurations had no names&lt;/em&gt; -- and an enterprise security program cannot prioritize against an unnamed configuration.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Naming is itself a defensive primitive. The 2021 SpecterOps catalog converted twenty-one years of unnamed admin-tunable knobs into a numbered backlog that scanners could enumerate, BloodHound could path-find, MSRC could patch, and operators could prioritize. Every subsequent mitigation generation -- KB5005413, CVE-2022-26923, KB5014754, CVE-2024-49019, BloodHound CE ADCS edges, Locksmith, Microsoft Defender for Identity&apos;s posture assessments -- builds on the catalog rather than on the underlying hardening documentation. The catalog is the security primitive; the patches are downstream of the catalog.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Eight ESCs in 2021. Within fifteen months, two researchers extended the catalog past the original boundary: Oliver Lyak at the Institute For Cyber Risk added ESC9 and ESC10 in August 2022 [@lyak-certipy-4-archive]; Sylvain Heiniger at Compass Security added ESC11 in November 2022 [@compass-esc11]. Hans-Joachim Knobloch added ESC12 in October 2023 [@knobloch-esc12]. SpecterOps&apos;s Jonas Bülow Knudsen added ESC13 in February 2024 [@knudsen-esc13] and ESC14 two weeks later [@knudsen-esc14]. Justin Bollinger at TrustedSec added ESC15 in October 2024 [@bollinger-ekuwu]. Lyak named ESC16 in 2025 against a workaround Schroeder himself had documented in 2022 [@specterops-esc16-docs]. Sixteen ESCs by the time you read this. Here is what each one does.&lt;/p&gt;
&lt;h2&gt;5. The Catalog: ESC-1 through ESC-16&lt;/h2&gt;
&lt;p&gt;Of the sixteen named ESCs, the original eight name the surface; ESC9 through ESC16 name the residual after every Microsoft mitigation shipped to date. We walk them in primitive-grouped order, following the same taxonomy the SpecterOps Certify documentation uses: template misconfigurations, access-control vulnerabilities, CA configuration issues, certificate mapping issues, and one hardware-substrate sidebar [@specterops-certify-docs-index].&lt;/p&gt;
&lt;h3&gt;Template misconfigurations: ESC1, ESC2, ESC3&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;ESC1 -- Misconfigured Certificate Template.&lt;/strong&gt; A V2 template that lets a low-privilege principal enroll, has Client Authentication in its Extended Key Usage list, has &lt;code&gt;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&lt;/code&gt; set, and does &lt;em&gt;not&lt;/em&gt; require Manager Approval. The attacker requests a certificate naming the target principal in the Subject Alternative Name; the CA issues; the certificate maps via UPN to the target; PKINIT produces a TGT as the target. One operator chain: &lt;code&gt;certipy req -u user -p pass -ca CA -template VulnTemplate -upn administrator@domain.local&lt;/code&gt;. First disclosed by SpecterOps in June 2021 [@cpo-blog]. BloodHound CE edge: &lt;code&gt;ADCSESC1&lt;/code&gt; [@bh-esc1-edge].&lt;/p&gt;

The `CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT` bit in `msPKI-Certificate-Name-Flag`. When set, the requester is allowed to supply the Subject or Subject Alternative Name in the CSR rather than having the CA build the Subject from the requester&apos;s own AD attributes. This is the load-bearing primitive of ESC1.

```powershell
Get-ADObject -SearchBase &quot;CN=Certificate Templates,CN=Public Key Services,CN=Services,$((Get-ADRootDSE).configurationNamingContext)&quot; -Filter * -Properties msPKI-Certificate-Name-Flag, pKIExtendedKeyUsage, msPKI-Enrollment-Flag |
  Where-Object {
    ($_.&apos;msPKI-Certificate-Name-Flag&apos; -band 0x1) -ne 0 -and
    ($_.&apos;msPKI-Enrollment-Flag&apos; -band 0x2) -eq 0 -and
    ($_.pKIExtendedKeyUsage -contains &apos;1.3.6.1.5.5.7.3.2&apos;)
  } | Select-Object Name
```
The query lists templates with ESS set, no manager approval, and Client Authentication EKU. Locksmith, PSPKIAudit, and Certipy all run a logically equivalent check; this is the smallest reproducible form for an audit script that does not depend on a vendor tool.
&lt;p&gt;&lt;strong&gt;ESC2 -- Any-Purpose or Subordinate CA EKU.&lt;/strong&gt; A template that grants the Any-Purpose EKU (&lt;code&gt;2.5.29.37.0&lt;/code&gt;) or the Subordinate CA EKU permits the certificate to be used for arbitrary purposes, including subordinate CA work. The attacker enrolls and then forges new certificates against the issued certificate&apos;s keypair. First disclosed by SpecterOps, June 2021 [@cpo-blog]. No BloodHound CE edge; the abuse pattern lives in Certify and Certipy [@certipy-wiki-priv].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC3 -- Enrollment Agent Template.&lt;/strong&gt; A template with the &lt;em&gt;Certificate Request Agent&lt;/em&gt; EKU lets the holder enroll certificates &lt;em&gt;on behalf of other users&lt;/em&gt;. Combined with a second template flagged &quot;Enrollment Agent&quot; the attacker can request a certificate naming any principal. The chain is two requests rather than one. SpecterOps, June 2021 [@cpo-blog]. BloodHound CE edge: &lt;code&gt;ADCSESC3&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Access-control vulnerabilities: ESC4, ESC5, ESC7&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;ESC4 -- Vulnerable Certificate Template ACL.&lt;/strong&gt; Any principal with &lt;code&gt;GenericAll&lt;/code&gt;, &lt;code&gt;GenericWrite&lt;/code&gt;, &lt;code&gt;WriteOwner&lt;/code&gt;, or &lt;code&gt;WriteDacl&lt;/code&gt; on a template can modify the template into an ESC1-shaped configuration and then enroll. This converts a write right on a template object into Domain Admin. SpecterOps, June 2021 [@cpo-blog]. BloodHound CE edge: &lt;code&gt;ADCSESC4&lt;/code&gt;.The ADCSESC4 edge composes with BloodHound&apos;s general DACL graph, so a &lt;code&gt;Domain Users&lt;/code&gt; principal that holds &lt;code&gt;WriteDacl&lt;/code&gt; on a sensitive template inherits the path automatically without a hand-written query. The edge composes naturally with the rest of BloodHound&apos;s principal-DACL graph -- a &lt;code&gt;Domain Users&lt;/code&gt; principal with &lt;code&gt;WriteDacl&lt;/code&gt; on the template inherits the path.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC5 -- Vulnerable PKI Object ACL.&lt;/strong&gt; The same class of write rights on the CA computer object, the &lt;code&gt;NTAuthCertificates&lt;/code&gt; container, or the AIA container. Compromising any of these gates the entire AD CS substrate. SpecterOps, June 2021 [@cpo-blog]. No BloodHound CE edge today; the surface is wide and the operator chain depends on the specific object compromised.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC7 -- Vulnerable CA ACL.&lt;/strong&gt; A principal with the &lt;em&gt;Manage CA&lt;/em&gt; right on the Enterprise CA can edit its registry-controlled configuration (including the &lt;code&gt;EDITF_ATTRIBUTESUBJECTALTNAME2&lt;/code&gt; flag, which converts the CA into a global ESC6 condition). A principal with &lt;em&gt;Issue and Manage Certificates&lt;/em&gt; can approve their own otherwise-blocked certificate requests. SpecterOps, June 2021 [@cpo-blog]. No BloodHound CE edge; the abuse is a CA-side write rather than an AD principal-graph relationship.&lt;/p&gt;
&lt;h3&gt;CA configuration issues: ESC6, ESC8, ESC11&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;ESC6 -- &lt;code&gt;EDITF_ATTRIBUTESUBJECTALTNAME2&lt;/code&gt; on the CA.&lt;/strong&gt; When this CA-wide flag is set, &lt;em&gt;every&lt;/em&gt; certificate request can specify an arbitrary Subject Alternative Name regardless of the template&apos;s Name-Flag bits. The CA becomes globally ESC1-shaped against any template the attacker can enroll into. SpecterOps, June 2021 [@cpo-blog]. BloodHound CE edges: &lt;code&gt;ADCSESC6a&lt;/code&gt; and &lt;code&gt;ADCSESC6b&lt;/code&gt; (the latter for cases where the CA also disables the SID extension).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC8 -- NTLM Relay to AD CS HTTP Web Enrollment.&lt;/strong&gt; The AD CS Web Enrollment role service ships with NTLM authentication enabled and, by default, no Extended Protection for Authentication. An attacker who can coerce a target computer to authenticate (PetitPotam, PrinterBug, DFSCoerce) can relay that authentication to the CA&apos;s &lt;code&gt;/certsrv/&lt;/code&gt; endpoint, request a certificate naming the relayed principal, and walk away with a certificate impersonating the coerced computer -- including Domain Controllers. SpecterOps, June 2021 [@cpo-blog]. BloodHound CE graphs this as the &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge [@bh-coerce-adcs-edge]: a Group-to-Computer edge whose source is &lt;code&gt;Authenticated Users&lt;/code&gt; and whose destination is the coerced target computer, with the edge&apos;s evaluation conditioned on at least one ESC8-vulnerable Web Enrollment endpoint being reachable on the network.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; ESC8 needs no template misconfiguration. It needs a CA with HTTP Web Enrollment role service installed -- common in environments that ever provisioned smart cards or did web-based renewal -- and at least one computer account the attacker can coerce. Microsoft mitigated it with KB5005413 in July 2021 [@kb5005413], but the mitigation is configuration guidance (EPA on, &quot;Require SSL&quot; on, Web Enrollment disabled if unused), not a binary patch. Environments that never enabled EPA on /certsrv/ remain exploitable today. The &quot;Domain Users to Domain Admin in eight minutes&quot; demos that pepper conference talks are usually ESC8 demos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;ESC11 -- NTLM Relay to ICPR/RPC.&lt;/strong&gt; The ICertPassage RPC interface (the default enrollment transport on every Enterprise CA) enforces packet privacy when the &lt;code&gt;IF_ENFORCEENCRYPTICERTREQUEST&lt;/code&gt; flag is set; that flag has been on by default since Windows Server 2012. However, because the flag breaks certificate enrollment for legacy Windows XP clients, Compass Security observed real-world environments where administrators had explicitly &lt;em&gt;removed&lt;/em&gt; the flag for compatibility, leaving the RPC enrollment surface unencrypted. When packet privacy is not enforced, an attacker can relay a coerced NTLM authentication into the CA&apos;s RPC interface and obtain a certificate impersonating the coerced principal. Disclosed by Sylvain Heiniger at Compass Security, November 2022 [@compass-esc11]. The SpecterOps Certify documentation describes the misconfiguration as &quot;an insufficiently protected certificate authority RPC interface&quot; [@specterops-esc11-docs]. No BloodHound CE edge; the RPC transport is below the principal-graph model.&lt;/p&gt;
&lt;h3&gt;Certificate mapping issues: ESC9, ESC10, ESC13, ESC14, ESC15, ESC16&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;ESC9 -- No Security Extension.&lt;/strong&gt; A template flagged &lt;code&gt;CT_FLAG_NO_SECURITY_EXTENSION&lt;/code&gt; instructs the CA to issue certificates &lt;em&gt;without&lt;/em&gt; the &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt; SID embedding. KB5014754&apos;s strong-mapping enforcement then falls back to weak UPN mapping, and the attacker can rename a controlled user account to match a privileged user&apos;s UPN, enroll, and authenticate as that privileged user. Disclosed by Oliver Lyak at IFCR on August 4, 2022, twelve weeks after KB5014754 [@lyak-certipy-4-archive]. BloodHound CE edges: &lt;code&gt;ADCSESC9a&lt;/code&gt; and &lt;code&gt;ADCSESC9b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC10 -- Weak Certificate Mapping.&lt;/strong&gt; The registry values &lt;code&gt;StrongCertificateBindingEnforcement&lt;/code&gt; (on KDCs) and &lt;code&gt;CertificateMappingMethods&lt;/code&gt; (on Schannel servers) control whether weak mappings are accepted. In Compatibility mode (the KB5014754 staged-rollout default through February 11, 2025), weak mappings still pass. An attacker who can write &lt;code&gt;altSecurityIdentities&lt;/code&gt; on a target, or who can engineer a weak UPN match, authenticates as the target. Same disclosure: Lyak, August 4, 2022 [@lyak-certipy-4-archive]. BloodHound CE edges: &lt;code&gt;ADCSESC10a&lt;/code&gt; and &lt;code&gt;ADCSESC10b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC13 -- Issuance Policy linked to AD Group via msDS-OIDToGroupLink.&lt;/strong&gt; Active Directory issuance-policy OIDs can be linked to a security group via the &lt;code&gt;msDS-OIDToGroupLink&lt;/code&gt; attribute. When a certificate carries that issuance-policy OID, the issued PAC includes the linked group. A template configured with such an issuance policy effectively grants its enrollees membership in the linked group at authentication time. Disclosed by Jonas Bülow Knudsen at SpecterOps on February 14, 2024; discovery credit goes to Adam Burford, who brought the technique to Knudsen and Stephen Hinck [@knudsen-esc13]. BloodHound CE edge: &lt;code&gt;ADCSESC13&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC14 -- Explicit altSecurityIdentities Write.&lt;/strong&gt; A principal with write access to a privileged user&apos;s &lt;code&gt;altSecurityIdentities&lt;/code&gt; attribute can add their own certificate&apos;s X.509 expression to that attribute, then authenticate as the privileged user. The prior art goes back to Géraud de Drouas in 2019 [@dedrouas-altsec] and Jean Marsault at Wavestone in June 2021 [@marsault-wavestone]; Knudsen catalogued it as ESC14 in February 2024 [@knudsen-esc14]. No BloodHound CE edge today; the abuse traces through a write right on a single AD attribute and is in scope for future BloodHound coverage.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC15 -- V1 Template Application Policies Override (EKUwu).&lt;/strong&gt; The pre-installed V1 &lt;code&gt;WebServer&lt;/code&gt; template -- which ships on every CA, cannot be deleted, and is enrollable by &lt;code&gt;Authenticated Users&lt;/code&gt; by default -- accepts &lt;code&gt;Application Policies&lt;/code&gt; extensions in the request. Application Policies, a Microsoft extension parallel to standard EKU, are honored by the KDC. An attacker submits a CSR adding the Client Authentication Application Policy to a WebServer certificate, gets it signed, and authenticates as the requester. Disclosed by Justin Bollinger at TrustedSec on October 8, 2024 [@bollinger-ekuwu]. Microsoft assigned CVE-2024-49019 and patched it on November 12, 2024 [@cve-2024-49019-msrc]. No BloodHound CE edge.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ESC16 -- CA-wide SID Extension Disabled.&lt;/strong&gt; The CA&apos;s &lt;code&gt;DisableExtensionList&lt;/code&gt; registry value can list OIDs the CA will &lt;em&gt;omit&lt;/em&gt; from issued certificates. If &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt; (1.3.6.1.4.1.311.25.2) is on that list, the CA stops embedding the SID extension globally, and the strong-mapping enforcement of KB5014754 collapses into weak mapping for every certificate the CA issues. The SpecterOps Certify documentation records the punchline: &quot;The configuration was first described in 2022 by Will Schroeder in this blogpost as a temporary workaround for the interaction between ESC7 and ESC6, but was later tagged ESC16 by Oliver Lyak&quot; [@specterops-esc16-docs]. No BloodHound CE edge.&lt;/p&gt;

ESC12 lives in a different primitive category from every other ESC: it attacks the CA&apos;s HSM, not its software configuration. Hans-Joachim Knobloch&apos;s October 2023 disclosure (earliest Wayback snapshot dated October 24, 2023) observes that the YubiHSM2 Key Storage Provider on AD CS stores the HSM authentication key in cleartext under `HKEY_LOCAL_MACHINE\SOFTWARE\Yubico\YubiHSM\AuthKeysetPassword` [@knobloch-esc12] [@knobloch-esc12-archive]. A non-administrative user with shell access to the CA and read on that registry key can recover the HSM password and forge certificates against the HSM-backed CA key. Out of body scope for this article; readers running YubiHSM-backed CAs should read Knobloch&apos;s primary source.
&lt;p&gt;By the time you reach ESC10 here, a pattern is visible without anyone naming it: every Microsoft mitigation in this class is followed by a new ESC that side-steps it. KB5005413 closes ESC8 over HTTPS; ESC11 routes around it via RPC. KB5014754 closes ESC9 and ESC10 under Full Enforcement; ESC16 disables the underlying SID extension. CVE-2024-49019 closes ESC15 on V1 templates; the V1 templates themselves remain on every CA. The catalog grows faster than the patches.&lt;/p&gt;
&lt;p&gt;Of the sixteen entries above, BloodHound CE ships eleven principal-graph edges covering eight distinct ESCs: &lt;code&gt;ADCSESC1&lt;/code&gt;, &lt;code&gt;ADCSESC3&lt;/code&gt;, &lt;code&gt;ADCSESC4&lt;/code&gt;, &lt;code&gt;ADCSESC6a/b&lt;/code&gt;, &lt;code&gt;ADCSESC9a/b&lt;/code&gt;, &lt;code&gt;ADCSESC10a/b&lt;/code&gt;, &lt;code&gt;ADCSESC13&lt;/code&gt;, plus the &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge that graphs ESC8 [@bh-llms]. The remaining eight ESCs (ESC2, ESC5, ESC7, ESC11, ESC12, ESC14, ESC15, ESC16) are out of edge coverage today -- some because their primitive lives below the principal graph (ESC11&apos;s RPC transport), some because their abuse is a CA-side write rather than a domain principal relationship (ESC7, ESC5), and some because they are too new to have been edge-modeled (ESC14, ESC15, ESC16). The gap is structural and operationally significant; section eight explores why.&lt;/p&gt;

flowchart TD
    subgraph TEMPLATE[Template]
        E1[ESC1 ESS+ClientAuth+LowPriv&lt;br /&gt;SpecterOps 2021]
        E2[ESC2 AnyPurpose/SubCA&lt;br /&gt;SpecterOps 2021]
        E3[ESC3 Enrollment Agent&lt;br /&gt;SpecterOps 2021]
        E15[ESC15 V1 AppPolicy&lt;br /&gt;TrustedSec 2024]
    end
    subgraph ACL[Access Control]
        E4[ESC4 Template DACL&lt;br /&gt;SpecterOps 2021]
        E5[ESC5 PKI Object DACL&lt;br /&gt;SpecterOps 2021]
        E7[ESC7 CA DACL&lt;br /&gt;SpecterOps 2021]
    end
    subgraph CA[CA Configuration]
        E6[ESC6 EDITF SAN2&lt;br /&gt;SpecterOps 2021]
        E16[ESC16 Disable SID Ext&lt;br /&gt;tagged Lyak 2025]
    end
    subgraph TRANSPORT[Transport]
        E8[ESC8 Relay to HTTP&lt;br /&gt;SpecterOps 2021]
        E11[ESC11 Relay to RPC&lt;br /&gt;Compass 2022]
    end
    subgraph MAP[Mapping]
        E9[ESC9 No SID Ext&lt;br /&gt;IFCR 2022]
        E10[ESC10 Weak Mapping&lt;br /&gt;IFCR 2022]
        E13[ESC13 OIDToGroupLink&lt;br /&gt;SpecterOps 2024]
        E14[ESC14 altSecurityIdentities&lt;br /&gt;SpecterOps 2024]
    end
    subgraph HW[Hardware]
        E12[ESC12 YubiHSM Substrate&lt;br /&gt;Knobloch 2023]
    end
&lt;p&gt;The static rules that Certipy, Certify, Locksmith, and PSPKIAudit all run to decide whether a template is ESC1-shaped are simpler than the catalog above might suggest. Three boolean inputs, three conjunctive conditions, one output label.&lt;/p&gt;
&lt;p&gt;{`
function classifyTemplate(t) {
  const ess = t.flags.includes(&apos;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&apos;);
  const clientAuth = t.eku.includes(&apos;1.3.6.1.5.5.7.3.2&apos;);
  const lowPriv = t.enroll.some(p =&amp;gt; [&apos;Authenticated Users&apos;, &apos;Domain Users&apos;].includes(p));
  const noApproval = !t.flags.includes(&apos;CT_FLAG_PEND_ALL_REQUESTS&apos;);
  if (ess &amp;amp;&amp;amp; clientAuth &amp;amp;&amp;amp; lowPriv &amp;amp;&amp;amp; noApproval) return &apos;ESC1&apos;;
  return &apos;safe-for-now&apos;;
}&lt;/p&gt;
&lt;p&gt;const wifi = {
  flags: [&apos;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&apos;],
  eku:   [&apos;1.3.6.1.5.5.7.3.2&apos;],
  enroll:[&apos;Authenticated Users&apos;]
};
console.log(classifyTemplate(wifi));
`}&lt;/p&gt;
&lt;h2&gt;6. The 2026 Toolchain&lt;/h2&gt;
&lt;p&gt;Sixteen ESCs is too many for one tool. The 2026 state of the art is a stack: defenders run Locksmith, PSPKIAudit, BloodHound CE, and Microsoft Defender for Identity in parallel; offense runs Certipy and Certify. No single tool covers every ESC, prioritizes its findings, &lt;em&gt;and&lt;/em&gt; produces forensic primitives for response. Coverage gaps are structural, not accidental.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Certify&lt;/strong&gt; is the original offense-side tool from the SpecterOps team that wrote &lt;em&gt;Certified Pre-Owned&lt;/em&gt;. A C# Windows binary that enumerates and abuses AD CS misconfigurations using the operator&apos;s in-process credentials [@certify-gh]. Released at Black Hat 2021, built against .NET 4.7.2. Certify covers the ESC1 through ESC16 enumeration surface via its documentation pages [@specterops-certify-docs-index]; abuse implementations exist for the catalog&apos;s most operator-friendly entries, with ESC11 documented as enumeration-only at the most recent docs revision [@specterops-esc11-docs].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Certipy&lt;/strong&gt; is the Linux-side sibling, written in Python by Oliver Lyak at IFCR (now an independent project) [@certipy-gh]. The README carries the strongest coverage claim in the tool community: &quot;full support for identifying and exploiting all known ESC1-ESC16 attack paths.&quot; Certipy ships its own NTLM relay (&lt;code&gt;certipy relay&lt;/code&gt;), embedded BloodHound output, certificate forging, and PKINIT-to-TGT exchange. The Certipy wiki&apos;s privilege-escalation page is the best walking reference for the entire catalog [@certipy-wiki-priv].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BloodHound Community Edition&lt;/strong&gt; is the only tool in the stack that integrates AD CS findings into the broader Active Directory attack graph. SharpHound CE collects AD CS objects -- CAs, templates, NTAuth membership, per-template DACLs -- and the BloodHound server computes ten &lt;code&gt;ADCSESC*N*&lt;/code&gt; edges (ESC1, ESC3, ESC4, ESC6a/b, ESC9a/b, ESC10a/b, ESC13) plus the &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge that graphs ESC8 via coercion [@bh-llms]. BloodHound CE 7.x added Privilege Zones, which let defenders tag NTAuth CAs and their templates as Tier-Zero objects and surface paths to them in the analysis UI.&lt;/p&gt;

The principal-graph model treats each AD object as a node and each access right or trust as an edge. The graph then path-finds from a starting principal to a Tier-Zero target. This model works elegantly for template DACLs (ESC4) and CA DACLs (ESC7) and for issuance-policy group linkage (ESC13). It struggles with attacks where the abuse is a transport-level interaction rather than a principal-to-principal relationship.&lt;p&gt;ESC8 used to be considered uncatchable in this model. The &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge solved that: BloodHound CE now models the SMB-coercion-plus-NTLM-relay-to-ESC8 chain as a Group-to-Computer edge whose source is &lt;code&gt;Authenticated Users&lt;/code&gt; and whose destination is the coerced target computer; the relay target CA and the template are encoded in the edge&apos;s metadata, not as graph nodes [@bh-coerce-adcs-edge]. The edge exists because coercion has a stable shape -- an unauthenticated principal class, a target computer, and an ESC8-vulnerable CA endpoint reachable on the network -- that the graph can express.&lt;/p&gt;
&lt;p&gt;ESC11 remains harder. The RPC enrollment transport does not have a stable coercion model (the trigger is &lt;code&gt;ICertPassage&lt;/code&gt; packet privacy not being enforced, not a coercion gadget like &lt;code&gt;MS-EFSR&lt;/code&gt;), and the BloodHound graph today does not ship an &lt;code&gt;ADCSESC11&lt;/code&gt; edge. The model limit is partial, not total. The conventional &quot;BloodHound cannot graph transport attacks&quot; framing -- which was the prevailing folklore through 2024 -- is wrong; ESC8 is in the graph. ESC11 is the open structural case.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Locksmith&lt;/strong&gt; is a PowerShell defender tool by Jake Hildreth (with Spencer Alessi) [@locksmith-gh]. It runs locally on a domain-joined host and reports template, CA, and NTAuth-container findings against the catalog. Modes 0 through 4: identify-and-report, auto-remediate where safe, produce a CSV, and so on. The lowest-friction defender tool in the stack -- a single &lt;code&gt;Invoke-Locksmith&lt;/code&gt; cmdlet returns a triage list against the published ESC range.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PSPKIAudit&lt;/strong&gt; is the SpecterOps team&apos;s own defender baseline, built on top of PKI Solutions&apos; PSPKI module [@pspkiaudit-gh]. Its &lt;code&gt;Invoke-PKIAudit&lt;/code&gt; and &lt;code&gt;Get-CertRequest&lt;/code&gt; cmdlets cover ESC1 through ESC8 plus the &quot;Explicit Mappings&quot; surface for ESC14. The README is marked beta; PSPKIAudit predates Locksmith and ships fewer remediation primitives, but it is the canonical reference for what the original SpecterOps team thinks the defensive audit should do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Defender for Identity&lt;/strong&gt; ships the ADCS posture assessment suite when the MDI sensor is installed on the CA itself [@mdi-certs]. The current product surface assesses nine ESCs by name: ESC1 (Preview), ESC2, ESC3, ESC4 (split across two separate assessments -- template owner and template ACL), ESC6 (Preview), ESC7, ESC8, ESC11, and ESC15. The product page is explicit: &quot;This assessment is available only to customers who have installed a sensor on an AD CS server.&quot; MDI&apos;s coverage is &lt;em&gt;broad and operationally integrated&lt;/em&gt; -- the same SOC console that surfaces Pass-the-Hash detections now surfaces the largest named-ESC posture-assessment suite of any non-Certipy tool in the stack, with the ESC1 and ESC6 assessments shipped in Preview state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The KB5014754 strong-mapping track&lt;/strong&gt; is Microsoft&apos;s runtime mitigation rather than a tool, but operationally it belongs in the stack discussion because it is the largest single thing Microsoft has shipped for this class [@kb5014754]. Strong mapping closes ESC9 and ESC10 (plus Certifried CVE-2022-26923) under Full Enforcement, defaults to Compatibility through February 11, 2025, and removes the legacy-mapping registry override on September 9, 2025. Operationally this is a deployment decision more than a &quot;tool to run&quot;, but every defender stack has to plan for it; the Microsoft Tech Community Intune blog is the cross-reference for environments using SCEP or PKCS [@ms-tc-intune].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Hacker Recipes AD CS chapter&lt;/strong&gt; is a community reference catalog rather than a runnable tool; it serves as the canonical operator-facing summary of every ESC and is worth bookmarking. (Network reachability of the canonical URL has been inconsistent in late 2025 / 2026.)&lt;/p&gt;
&lt;p&gt;Here is a single-table comparison of the practical stack. The right answer for a real enterprise is roughly &quot;all of them in parallel&quot;; the table makes the coverage gaps explicit.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool / track&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;ESC enumeration coverage&lt;/th&gt;
&lt;th&gt;Abuse capable&lt;/th&gt;
&lt;th&gt;Graph capable&lt;/th&gt;
&lt;th&gt;Best deployed for&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Certify&lt;/td&gt;
&lt;td&gt;C# (Windows)&lt;/td&gt;
&lt;td&gt;ESC1 to ESC16 (per docs)&lt;/td&gt;
&lt;td&gt;Yes (most)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Operator chains, Windows offense&lt;/td&gt;
&lt;td&gt;[@certify-gh]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Certipy&lt;/td&gt;
&lt;td&gt;Python (Linux)&lt;/td&gt;
&lt;td&gt;ESC1 to ESC16 (README claim)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Embedded&lt;/td&gt;
&lt;td&gt;Operator chains, Linux offense&lt;/td&gt;
&lt;td&gt;[@certipy-gh]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BloodHound CE ADCS edges&lt;/td&gt;
&lt;td&gt;Cypher&lt;/td&gt;
&lt;td&gt;8 of 16 ESCs (11 edges: ten ADCSESC&lt;em&gt;N&lt;/em&gt; + CoerceAndRelayNTLMToADCS)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Prioritization, attack-path analysis&lt;/td&gt;
&lt;td&gt;[@bh-llms]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Locksmith&lt;/td&gt;
&lt;td&gt;PowerShell&lt;/td&gt;
&lt;td&gt;Published ESC catalog&lt;/td&gt;
&lt;td&gt;Identify and fix&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Operational scans on each CA&lt;/td&gt;
&lt;td&gt;[@locksmith-gh]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PSPKIAudit&lt;/td&gt;
&lt;td&gt;PowerShell&lt;/td&gt;
&lt;td&gt;ESC1 to ESC8 plus Explicit Mappings&lt;/td&gt;
&lt;td&gt;No (read-only)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Defender baseline, audit&lt;/td&gt;
&lt;td&gt;[@pspkiaudit-gh]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDI ADCS posture&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;ESC1 (Preview), ESC2, ESC3, ESC4, ESC6 (Preview), ESC7, ESC8, ESC11, ESC15&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Inside MDI console&lt;/td&gt;
&lt;td&gt;SOC integration, posture scoring&lt;/td&gt;
&lt;td&gt;[@mdi-certs]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KB5014754 strong mapping&lt;/td&gt;
&lt;td&gt;Windows runtime&lt;/td&gt;
&lt;td&gt;ESC9, ESC10, Certifried (mitigation)&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Domain Controllers (deploy)&lt;/td&gt;
&lt;td&gt;[@kb5014754]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For most enterprises the realistic configuration is: Locksmith scheduled monthly on every CA; BloodHound CE with the ADCS collector enabled in SharpHound CE; Microsoft Defender for Identity sensor on every AD CS server (for the nine-ESC SOC visibility surface that now includes ESC1 and ESC6 in Preview); PSPKIAudit run once a quarter as the SpecterOps-blessed baseline; Certipy in the red-team or purple-team kit; and the KB5014754 rollout staged to land at Full Enforcement before February 11, 2025 (legacy-mapping removal September 9, 2025). The remaining gap items -- ESC5, ESC12, ESC14, and ESC16 (neither in BloodHound&apos;s principal graph nor in MDI&apos;s posture-assessment surface) -- are caught by Locksmith plus PSPKIAudit plus Certipy plus careful template review.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If no single tool covers everything, what is Microsoft actually doing about it?&lt;/p&gt;
&lt;h2&gt;7. What Microsoft Has Actually Shipped&lt;/h2&gt;
&lt;p&gt;Of sixteen named ESCs, Microsoft has shipped three CVE-class patches. The rest are hardening guidance. The asymmetry is not accidental; it tracks the boundary Microsoft draws in its &lt;a href=&quot;https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/&quot; rel=&quot;noopener&quot;&gt;Windows Security Servicing Criteria&lt;/a&gt; between &lt;em&gt;default-state vulnerabilities&lt;/em&gt; (which receive CVEs and binary patches) and &lt;em&gt;admin-configurable misconfigurations&lt;/em&gt; (which receive documentation). Most ESCs sit on the configurable side of that boundary.&lt;/p&gt;
&lt;p&gt;Four Microsoft mitigation tracks define the response, in order of when they shipped.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KB5005413 (late July 2021) -- NTLM Web Enrollment hardening.&lt;/strong&gt; Published roughly six weeks after &lt;em&gt;Certified Pre-Owned&lt;/em&gt; in response to PetitPotam plus the SpecterOps ESC8 disclosure [@kb5005413]. Recommends enabling Extended Protection for Authentication, requiring SSL on the &lt;code&gt;/certsrv/&lt;/code&gt; virtual directories of AD CS Web Enrollment and the Certificate Enrollment Web Service, and disabling NTLM where Kerberos is available. Crucially: KB5005413 is &lt;em&gt;guidance&lt;/em&gt;, not a binary patch. Environments that never enabled EPA on &lt;code&gt;/certsrv/&lt;/code&gt; remain exploitable today. The KB closes ESC8 over HTTPS when fully applied; it does not affect ESC11 (RPC), ESC1 through ESC7, or anything in the ESC9-plus range.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CVE-2022-26923 (May 10, 2022) -- Certifried.&lt;/strong&gt; The single MSRC-acknowledged CVE in the original ESC1 through ESC8 design space [@cve-2022-26923-nvd] [@cve-2022-26923-msrc]. Disclosed by Oliver Lyak at IFCR [@lyak-certifried], the vulnerability lets any Authenticated User (because the default &lt;code&gt;ms-DS-MachineAccountQuota&lt;/code&gt; is 10 [@semperis-cve]) create a computer account, write its &lt;code&gt;dNSHostName&lt;/code&gt; to match a Domain Controller, request a certificate from the default Machine template, and PKINIT as the DC. Microsoft patched it on the May 10, 2022 Patch Tuesday. Semperis&apos;s retrospective documents the chain in detail [@semperis-cve]. The patch closes &lt;em&gt;that specific path&lt;/em&gt; -- the &lt;code&gt;dNSHostName&lt;/code&gt; impersonation race -- and is part of the same Patch Tuesday that shipped KB5014754. It does not close any other ESC.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KB5014754 (May 10, 2022 -- present) -- the strong-mapping rollout.&lt;/strong&gt; The largest single Microsoft mitigation in the entire class [@kb5014754]. SpecterOps&apos;s own analysis -- &quot;Certificates and Pwnage and Patches, Oh My!&quot; -- remains the canonical walkthrough of how the new behavior interacts with the existing catalog [@specterops-pwnage].&lt;/p&gt;
&lt;p&gt;The mechanics: KB5014754 introduces the &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt; extension (OID 1.3.6.1.4.1.311.25.2), embeds the requester&apos;s SID into every issued certificate by default, and redefines which &lt;code&gt;altSecurityIdentities&lt;/code&gt; mappings the KDC will accept. Deployment is staged across three modes -- Disabled, Compatibility, and Full Enforcement -- with the Full Enforcement transition originally planned for November 2023, then repeatedly delayed in response to customer compatibility issues with SCEP, Intune PKCS, and non-Microsoft PKIs. The KB&apos;s current text states that Full Enforcement becomes the default on February 11, 2025, and the legacy compatibility-mode registry override is removed by the September 9, 2025 Windows security update [@kb5014754].&lt;/p&gt;
&lt;p&gt;What it closes: ESC9 (because Full Enforcement rejects certificates lacking the SID extension), ESC10 (because weak mappings are rejected), and Certifried even on unpatched templates. It is &lt;em&gt;bypassed&lt;/em&gt; by ESC16, which disables the SID extension at the CA level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CVE-2024-49019 (EKUwu / ESC15) -- November 12, 2024.&lt;/strong&gt; Patched thirty-five days after Bollinger&apos;s October 8, 2024 disclosure [@bollinger-ekuwu]. The November 12, 2024 Patch Tuesday addressed the V1 WebServer template Application-Policies override [@cve-2024-49019-nvd] [@cve-2024-49019-msrc]. The patch hardens the KDC&apos;s interpretation of Application Policies in V1 certificates; it does not close ESC16, ESC11, or anything in the template DACL space.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Microsoft&apos;s Windows Security Servicing Criteria reserves CVEs for vulnerabilities in default product state [@msrc-servicing-criteria]. Misconfigurations that require administrator action to introduce are treated as hardening matters and receive documentation rather than CVEs. The 2019 ANSSI altSecurityIdentities report received a &quot;won&apos;t fix&quot; response on exactly these grounds [@dedrouas-altsec]. The boundary explains the catalog&apos;s CVE asymmetry: ESC1 (template flag) is configuration; Certifried (a default-template behavior on an account-creation-default-permission interaction) is a CVE. ESC15 sat on the boundary -- the affected template is shipped pre-installed and cannot be uninstalled, so its default-state could be argued either way -- and Microsoft chose to issue a CVE. The boundary is operational policy, not technical bound; it can move.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The single most useful table in this article is the cross-reference of which Microsoft mitigation closes which ESC. Read row by row to understand which ESCs are runtime-closed in a hardened environment and which remain dependent on the customer&apos;s administrative hardening discipline.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ESC&lt;/th&gt;
&lt;th&gt;KB5005413 (2021)&lt;/th&gt;
&lt;th&gt;CVE-2022-26923 (2022)&lt;/th&gt;
&lt;th&gt;KB5014754 (2022-2025)&lt;/th&gt;
&lt;th&gt;CVE-2024-49019 (2024)&lt;/th&gt;
&lt;th&gt;Hardening only&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;ESC1&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Partial (SID ext defeats SAN supply for cert-authn)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Primary mitigation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC2&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC3&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Partial (SID ext binds the cert to the agent)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC4&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC5&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC6&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Partial (SID ext defeats requested SAN)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Primary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC7&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC8 (HTTP)&lt;/td&gt;
&lt;td&gt;Closed when EPA + SSL deployed&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Continues if EPA off&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC9&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Closed at Full Enforcement&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Until Feb 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC10&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Closed at Full Enforcement&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Until Feb 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC11 (RPC)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Primary (&lt;code&gt;IF_ENFORCEENCRYPTICERTREQUEST&lt;/code&gt; flag)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC12&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Primary (HSM hardening)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC13&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC14&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC15&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Closed (Nov 12, 2024)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC16&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Bypassed (this attack disables the extension)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Primary&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Of sixteen ESCs, three have CVE-class binary patches (Certifried, EKUwu, and -- if you count it -- the KB5005413 NTLM-relay hardening track), two are runtime-closed under KB5014754 Full Enforcement, and the remaining eleven are administrative hardening matters. If only three of sixteen have CVEs, what stops the catalog from growing forever?&lt;/p&gt;
&lt;h2&gt;8. The Two-Trust-Roots Problem&lt;/h2&gt;
&lt;p&gt;What stops the catalog from growing forever is the architectural property the catalog enumerates around but cannot eliminate. The catalog grows because the property is structural, not because the engineering is sloppy. Four pieces of theory anchor the limit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Two trust roots.&lt;/strong&gt; Active Directory&apos;s Kerberos KDC will mint a Domain Admin Ticket-Granting Ticket on presentation of any valid certificate signed by a CA in the forest&apos;s &lt;code&gt;NTAuthCertificates&lt;/code&gt; container, provided the certificate maps to the Administrator principal. The &lt;code&gt;krbtgt&lt;/code&gt; key is the symmetric root of trust for password and TGS authentication; an NTAuth CA&apos;s private key is an asymmetric root of trust for PKINIT. There is no architectural relationship between the two. Rotating the &lt;code&gt;krbtgt&lt;/code&gt; key does not invalidate any certificate. Revoking a CA does not invalidate &lt;code&gt;krbtgt&lt;/code&gt;-issued tickets. They are &lt;em&gt;independent authenticator-minting keys&lt;/em&gt;. For a forest with $n$ NTAuth-published CAs, the count of independent keys that can mint a Domain Admin authenticator is $n + 1$.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; For an Active Directory forest with $n$ Certificate Authorities published into &lt;code&gt;NTAuthCertificates&lt;/code&gt;, there are exactly $n + 1$ independent keys that can mint a Domain Admin authenticator: the krbtgt account hash, and the private key of every published CA. Rotating krbtgt closes one root. Revoking one CA closes another. The other $n - 1$ remain. The ESC catalog enumerates &lt;em&gt;how&lt;/em&gt; an attacker can make those keys issue a Domain Admin authenticator with low-privilege materials; the architectural property -- that there are $n + 1$ such keys at all -- is a design property of PKINIT and is not closable by any patch [@rfc4556] [@cpo-whitepaper].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;PKINIT&apos;s binding gap.&lt;/strong&gt; RFC 4556 specifies how a Kerberos client presents a certificate and receives a TGT [@rfc4556]. The RFC does not bind the certificate to a Microsoft SID; the mapping from certificate to AD principal is a Microsoft extension. The KB5014754 strong-mapping track closes the &lt;em&gt;mapping ambiguity&lt;/em&gt; by embedding the requester&apos;s SID into the certificate and matching the SID on the KDC side [@kb5014754]. It does not close the underlying primitive: a certificate is an alternate identity assertion that the KDC honors as long as the signing CA is trusted. Different ESCs find different ways to get a useful certificate; the authentication step is identical across the catalog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The transport-versus-principal split.&lt;/strong&gt; The §6 BloodHound Aside develops this in full: BloodHound&apos;s principal-graph model now expresses ESC8 as the &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; edge, but ESC11 remains the open structural case because the RPC transport has no equivalent coercion gadget [@bh-coerce-adcs-edge]. The model limit is partial, not total -- it applies to RPC, not to all transport attacks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The configuration-versus-CVE boundary.&lt;/strong&gt; The §7 Callout develops this in full. The catalog has accumulated CVEs only when Microsoft judged the configuration was default-state -- Certifried&apos;s machine-account-quota path and ESC15&apos;s pre-installed V1 templates. The architectural property is policy-driven and movable.&lt;/p&gt;

Active Directory has two trust roots that can mint a Domain Admin authenticator: the krbtgt key, and any CA published into NTAuth. Rotating one does not touch the other.
&lt;p&gt;The architectural property reshapes how operators should think about the catalog. The catalog is not an arms race that ends; the catalog is the community mapping the surface of a design property of PKINIT. Each new ESC narrows the description of &lt;em&gt;what surface remains exposed&lt;/em&gt;; no plausible patch removes the underlying $n + 1$ key count. Until PKINIT itself is replaced -- until PKINIT is deprecated, until the KDC stops accepting certificate-based authentication, until NTAuth-published CAs lose their KDC trust -- every NTAuth-published CA in the forest is a key parallel to krbtgt.&lt;/p&gt;
&lt;p&gt;If the architectural limit cannot be closed, what are the open questions in 2026?&lt;/p&gt;

flowchart LR
    K[krbtgt account hash&lt;br /&gt;symmetric KDC key]
    CA1[CA #1 private key&lt;br /&gt;published in NTAuth]
    CA2[CA #2 private key&lt;br /&gt;published in NTAuth]
    CAN[CA #n private key&lt;br /&gt;published in NTAuth]
    KDC[Kerberos KDC&lt;br /&gt;and PKINIT]
    AUTH[Domain Admin&lt;br /&gt;authenticator TGT]
    K --&amp;gt; KDC
    CA1 --&amp;gt; KDC
    CA2 --&amp;gt; KDC
    CAN --&amp;gt; KDC
    KDC --&amp;gt; AUTH
&lt;h2&gt;9. Open Problems and the Catalog&apos;s Closure&lt;/h2&gt;
&lt;p&gt;The catalog has no published closure principle. Here are the five open frontiers in 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No closure principle.&lt;/strong&gt; The catalog has grown every year since 2021: ESC1 through ESC8 in June 2021; ESC9 and ESC10 in August 2022; ESC11 in November 2022; ESC12 in October 2023 [@knobloch-esc12] [@knobloch-esc12-archive]; ESC13 and ESC14 in February 2024; ESC15 in October 2024; ESC16 named in 2025 against a workaround from 2022 [@specterops-esc16-docs]. ESC15 revealed a twenty-four-year-old default behavior on V1 templates -- behavior that had been quietly present since the role&apos;s 2000 shipping date [@bollinger-ekuwu]. The Certify documentation conjectures an upper bound (the six primitive categories times the misconfigurable bits per primitive) but no formal upper bound is published. ESC15 is itself an existence proof that &lt;em&gt;new categories&lt;/em&gt; still emerge: Application Policies as a parallel to standard EKU was not in the original 2021 catalog at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detection asymmetry.&lt;/strong&gt; Most ESCs leave artifacts on the CA -- specifically Event ID 4886 (certificate request submitted) and Event ID 4887 (certificate issued) -- and no artifact in the standard Active Directory event stream. Most SIEMs do not ingest CA logs, because CA logs were never on the standard Tier-Zero ingest checklist. The result is that the CA&apos;s own audit log carries the only reliable forensic primitive for the entire catalog, and that log is in a place the SOC does not look. Locksmith and PSPKIAudit can identify the &lt;em&gt;misconfigurations&lt;/em&gt; but cannot tell you whether they have been &lt;em&gt;exploited&lt;/em&gt;; that signal lives in the CA&apos;s audit log alone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Strong-mapping migration risk.&lt;/strong&gt; The KB5014754 staged rollout enters Full Enforcement on February 11, 2025 and removes the legacy compatibility-mode registry override on September 9, 2025 [@kb5014754]. Environments with legacy SCEP gateways, third-party PKI vendors, Intune PKCS profiles without strong mapping, or smart cards issued by non-Microsoft CAs face a real risk that &lt;em&gt;legitimate&lt;/em&gt; authentication breaks at Full Enforcement. The Microsoft Tech Community Intune guidance is the operational reference for the SCEP/PKCS path [@ms-tc-intune]. The migration is a security upgrade and a deployment minefield in the same package; environments that defer the rollout past September 9, 2025 lose the legacy override and are forced into Full Enforcement by an OS update they did not opt into.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Per the live KB5014754 text on Microsoft Support: &quot;By February 2025, if the StrongCertificateBindingEnforcement registry key is not configured, domain controllers will move to Full Enforcement mode&quot; and &quot;the option to move back to Compatibility mode will remain until the September 9, 2025, Windows security update is installed&quot; [@kb5014754]. Environments that have not finished the strong-mapping rollout by those dates -- particularly those with non-Microsoft PKI in the chain, including legacy SCEP / Intune PKCS / smart-card vendors -- should plan for breakage and have a rollback plan ready.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cloud PKI.&lt;/strong&gt; Entra-managed Cloud PKI changes the substrate: the issuing CA is Microsoft-operated, the template surface is partially exposed to administrators, and the trust relationship between Cloud PKI and on-premises Active Directory is itself a configurable bridge. The community has not yet published an ESC catalog for Cloud PKI; the on-premises catalog is on-prem-specific and does not transfer directly. The open question is whether the Cloud PKI substrate has its own equivalent primitives (a CA-side &quot;this template is configured with ESS-equivalent behavior&quot;) that just have not yet been named.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The NTLM dependency in ESC8 and ESC11.&lt;/strong&gt; Both ESC8 and ESC11 depend on NTLM authentication being available between the coerced computer and the CA host. Microsoft&apos;s stated direction is to disable NTLM by default in future Windows releases (the &quot;NTLM disablement&quot; track) [@ms-ntlm-evolution]. If that direction completes, ESC8 and ESC11&apos;s relay primitives lose their substrate -- not because the AD CS transport hardens, but because there is no NTLM authentication to relay. The rest of the catalog -- the template, ACL, mapping, and CA-configuration ESCs -- does not depend on NTLM and is unaffected by NTLM disablement.&lt;/p&gt;
&lt;p&gt;Taken together, these results suggest the catalog&apos;s growth trajectory is structural. The reason ESC15 surfaced a twenty-four-year-old default is not that the SpecterOps team was lazy in 2021; it is that the surface is so large that systematic enumeration of every cross-product (six primitives multiplied by the configurable bits per primitive) is itself a research program. Knowing the architectural limits and the open problems, here is the operational playbook.&lt;/p&gt;
&lt;h2&gt;10. The Four-Lane Playbook&lt;/h2&gt;
&lt;p&gt;Here is what an enterprise security program actually does, in four lanes. Lane discipline matters because the catalog rewards parallel work: a single quarter spent only on Lane 1 leaves you detection-blind, and a single quarter spent only on Lane 2 leaves you remediation-paralyzed.&lt;/p&gt;
&lt;h3&gt;Lane 1: Preventive hygiene&lt;/h3&gt;
&lt;p&gt;Run Locksmith and PSPKIAudit on every Enterprise CA at least monthly [@locksmith-gh] [@pspkiaudit-gh]. Both tools enumerate the published catalog and produce a triage list. The defender baseline these tools encode is roughly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Template ACL audit. Confirm that no non-Tier-Zero principal holds &lt;code&gt;WriteDacl&lt;/code&gt;, &lt;code&gt;WriteOwner&lt;/code&gt;, &lt;code&gt;WriteProperty&lt;/code&gt;, or &lt;code&gt;GenericAll&lt;/code&gt; on any V2 template.&lt;/li&gt;
&lt;li&gt;CA security descriptor audit. Confirm that &lt;code&gt;Manage CA&lt;/code&gt; and &lt;code&gt;Issue and Manage Certificates&lt;/code&gt; are held only by Tier-Zero principals.&lt;/li&gt;
&lt;li&gt;ESS audit. Confirm that no template enrollable by &lt;code&gt;Authenticated Users&lt;/code&gt; or &lt;code&gt;Domain Users&lt;/code&gt; has &lt;code&gt;CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT&lt;/code&gt; set with Client Authentication EKU and no Manager Approval.&lt;/li&gt;
&lt;li&gt;CA registry audit. Confirm that &lt;code&gt;EDITF_ATTRIBUTESUBJECTALTNAME2&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; set, and &lt;code&gt;IF_ENFORCEENCRYPTICERTREQUEST&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; set.&lt;/li&gt;
&lt;li&gt;SID extension audit. Confirm that &lt;code&gt;szOID_NTDS_CA_SECURITY_EXT&lt;/code&gt; (OID 1.3.6.1.4.1.311.25.2) is &lt;em&gt;not&lt;/em&gt; present in any CA&apos;s &lt;code&gt;DisableExtensionList&lt;/code&gt; registry value -- closing the ESC16 path.&lt;/li&gt;
&lt;li&gt;Manager Approval on sensitive templates. Confirm that any template with privileged EKU sets has Manager Approval.&lt;/li&gt;
&lt;li&gt;Least-privilege Enroll. Confirm that Domain Users-equivalent groups do not hold Enroll or Autoenroll on sensitive templates.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Lane 2: Detection deployment&lt;/h3&gt;
&lt;p&gt;Ingest the CA&apos;s own Security event log into the SIEM. The two load-bearing events are 4886 (&quot;Certificate Services received a certificate request&quot;) and 4887 (&quot;Certificate Services approved a certificate request and issued a certificate&quot;). These events are what fire when an operator chain like the cold-open in section one executes. They are the only AD CS event stream the SOC needs to detect the entire issuance side of the catalog.&lt;/p&gt;
&lt;p&gt;Enable Microsoft Defender for Identity sensors on every AD CS server. MDI now ships nine named ESC posture assessments -- ESC1 (Preview), ESC2, ESC3, ESC4 (template owner and template ACL as two separate assessments), ESC6 (Preview), ESC7, ESC8, ESC11, and ESC15 -- and surfaces them in the same console the SOC uses for the rest of Active Directory [@mdi-certs]. The ADCS-resident sensor is the only MDI sensor that produces these particular assessments; environments running MDI on Domain Controllers only do not get the AD CS surface.&lt;/p&gt;
&lt;p&gt;Run SharpHound CE with the AD CS collection options enabled and ingest the resulting graph into BloodHound CE. Tag NTAuth-published CAs and their pre-installed sensitive templates as Tier Zero in BloodHound&apos;s Privilege Zones. Run the analysis layer&apos;s &lt;code&gt;Shortest Paths to Tier Zero&lt;/code&gt; query weekly; ESC1, ESC3, ESC4, ESC6a/b, ESC9a/b, ESC10a/b, and ESC13 will surface as edges, along with &lt;code&gt;CoerceAndRelayNTLMToADCS&lt;/code&gt; paths for any ESC8-vulnerable HTTP enrollment endpoint [@bh-llms] [@bh-coerce-adcs-edge].&lt;/p&gt;
&lt;p&gt;Schedule Locksmith on a recurring cadence with output to a triage queue. Locksmith is the lowest-friction defender tool; it identifies and (with mode 1) optionally fixes published-catalog findings with a single cmdlet.&lt;/p&gt;
&lt;h3&gt;Lane 3: Confirmed-compromise response&lt;/h3&gt;
&lt;p&gt;This lane carries the article&apos;s load-bearing operational claim. If a CA&apos;s private key is suspected compromised -- whether through ESC12 hardware-substrate compromise, through &lt;code&gt;ntdsutil&lt;/code&gt;-equivalent CA export, or through a vendor compromise of the HSM -- the recovery path is &lt;em&gt;not&lt;/em&gt; &quot;rotate krbtgt&quot; and &lt;em&gt;not&lt;/em&gt; &quot;revoke the affected certificates&quot;. The recovery path is multi-week:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Revoke the CA&apos;s published certificate chain.&lt;/li&gt;
&lt;li&gt;Decommission the CA (remove the role service, delete the CA private key store, retire the host).&lt;/li&gt;
&lt;li&gt;Build a replacement CA on new hardware with a new key.&lt;/li&gt;
&lt;li&gt;Publish the new CA into &lt;code&gt;NTAuthCertificates&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Distrust the old CA&apos;s certificates throughout the forest (CRL update, certificate revocation lists pushed via Group Policy, decommissioning all certificates issued by the compromised CA).&lt;/li&gt;
&lt;li&gt;Re-issue every credential that depended on the compromised CA.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This operation is analogous in scale and duration to a forest rebuild for &lt;code&gt;krbtgt&lt;/code&gt; compromise -- a multi-week IR project, not a one-day patch. The reason is the two-trust-roots property: revoking the CA closes only one of the $n + 1$ keys; if the operator already minted Golden Certificates against the CA&apos;s private key, those certificates outlive the revocation unless every issued serial is on the CRL and every relying party has a fresh CRL fetch policy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Lane-3 CA rebuild operation is the single most important &lt;em&gt;preparatory&lt;/em&gt; deliverable in this entire playbook. Run a tabletop exercise: &quot;the CA private key is compromised; what are the steps to a clean state?&quot; If the answer is unclear in the absence of an incident, the answer will be improvised during one -- typically poorly. Build the runbook, identify the operational owners, pre-stage the replacement CA&apos;s hardware, and document the certificate inventory you will need to re-issue. The two-week recovery becomes a one-week recovery if the prep is done; the two-week recovery becomes a four-week recovery if it is not.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Lane 4: What does not work&lt;/h3&gt;
&lt;p&gt;Five operator myths that the catalog refutes by construction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&quot;Rotating krbtgt closes AD CS.&quot;&lt;/strong&gt; Wrong. Rotating krbtgt closes the symmetric KDC key; it does not touch the asymmetric CA private keys in &lt;code&gt;NTAuthCertificates&lt;/code&gt;. An ESC1 certificate issued against the new krbtgt mints a Domain Admin TGT the same way it would have against the old one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;Credential Guard protects against ESC.&quot;&lt;/strong&gt; Wrong. &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&apos;s LSAISO&lt;/a&gt; isolates LSASS-resident credentials from the rest of the OS. AD CS abuse does not touch LSAISO; the certificate is issued by the CA against a request submitted over a network protocol. The credential never leaves the attacker&apos;s machine in a form Credential Guard could isolate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;Disabling Web Enrollment closes AD CS.&quot;&lt;/strong&gt; Partial. Disabling the AD CS Web Enrollment role service closes ESC8 (the HTTP relay primitive). It does not affect ESC1 through ESC7 (template, ACL, and CA-config attacks), ESC11 (RPC relay), or any of the mapping ESCs. The default RPC enrollment transport on every Enterprise CA is unaffected.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;If we patch CVE-2022-26923 we&apos;re done.&quot;&lt;/strong&gt; Wrong. CVE-2022-26923 closes the specific &lt;code&gt;dNSHostName&lt;/code&gt; machine-account-impersonation chain. It does not close ESC1, ESC4, or any of the configuration ESCs that the same operator chain could have taken.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&quot;Reset krbtgt twice and we have evicted the attacker.&quot;&lt;/strong&gt; Wrong. The double-krbtgt-reset playbook is well-suited for Golden Ticket eviction. It is not effective against an attacker who has issued a long-validity authentication certificate from a CA the attacker controls or has compromised. The issued certificate authenticates against the new krbtgt the same way it did against the old one, because PKINIT does not bind the certificate&apos;s authority to the symmetric krbtgt key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Run Locksmith this week. Tag NTAuth CAs as Tier Zero in BloodHound. Schedule the Lane 3 rebuild playbook before you need it. The catalog grew faster than the patches; the defender&apos;s only working strategy is parallel work in all four lanes.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

The SID extension is on by default for any CA running an OS that has installed KB5014754 or later. The catch is what the *KDC* does with that extension. Switching the KDC to Full Enforcement breaks every certificate that lacks the SID extension, which is why Microsoft built the three-mode staged rollout: the §7 timeline anchors the compatibility window (mechanics and the Feb 11, 2025 / Sep 9, 2025 milestones), and the §9 Callout carries the verbatim KB5014754 dates and the customer compatibility-friction set (legacy SCEP, Intune PKCS, non-Microsoft PKI, third-party smart cards). ESC16 closes the loop in the other direction: an admin (or a compromised admin) can re-disable the extension at the CA level, recreating the weak-mapping condition KB5014754 was designed to close.

Partially. The on-premises ESC catalog enumerates misconfigurations of the on-premises AD CS role. Entra Cloud PKI is a Microsoft-operated SaaS CA whose substrate is not the on-premises AD CS Windows role at all -- so ESCs that abuse on-premises CA registry flags (ESC6, ESC16), on-premises CA DACLs (ESC5, ESC7), or the on-premises transport (ESC8, ESC11) do not transfer directly. But Cloud PKI still issues authentication certificates, still has a template-equivalent administrative surface, and still maps certificates onto AD or Entra principals. The community has not yet published a Cloud PKI ESC catalog; the open question is whether the cross-product of Cloud PKI&apos;s primitive surface and its mapping behavior has its own equivalent class of named misconfigurations.

No. A two-tier hierarchy improves protection of the *root* CA&apos;s private key (the root signs only the subordinate&apos;s certificate and stays offline) but does nothing for the subordinate. The ESC catalog attacks the issuing subordinate, not the root. The misconfigured Enrollee-Supplies-Subject template, the editable `EDITF_ATTRIBUTESUBJECTALTNAME2` registry flag, the per-template DACL, the NTLM-relayable Web Enrollment endpoint -- all live on the subordinate CA. A two-tier hierarchy is the right architecture and is essentially orthogonal to the ESC discussion.

No. Smart cards are *consumers* of certificates issued by AD CS; the smart-card pipeline reads a certificate off the card, presents it to PKINIT, and receives a TGT. AD CS is the *issuing* substrate. Every ESC attacks the issuance side. A smart-card deployment depends on AD CS being correctly configured; it adds no defense against ESC1 through ESC16 and may add complexity in the strong-mapping migration (smart-card-issued certificates may use legacy mappings that break under Full Enforcement).

No. BloodHound CE does not ship a numbered `ADCSESC8` edge. It ships `CoerceAndRelayNTLMToADCS`, an edge representing &quot;a computer can be SMB-coerced to authenticate to an attacker host, and the attacker host can relay that authentication to an ESC8-vulnerable Web Enrollment endpoint on a CA&quot; [@bh-coerce-adcs-edge]. Look for that edge, not for a numbered ESC8 edge. If `CoerceAndRelayNTLMToADCS` paths exist anywhere in the graph, your Web Enrollment endpoint is ESC8-exposed and the operator chain from any coercible computer to a Domain Admin authenticator runs in eight minutes.

ESC12 is treated in the §5 Aside: Knobloch&apos;s October 2023 YubiHSM hardware-substrate disclosure (earliest Wayback snapshot dated October 24, 2023), scoped out of the body because the abuse depends on the specific HSM vendor and on shell access to the CA host [@knobloch-esc12] [@knobloch-esc12-archive]. ESC0 does not exist in the SpecterOps catalog; some operator blogs use &quot;ESC0&quot; informally to describe naive enumeration (no abuse, just &quot;the CA is reachable and the template store is readable&quot;) but it is not a community-named technique.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;ad-cs-esc-catalog&quot; keyTerms={[
  { term: &quot;PKINIT&quot;, definition: &quot;RFC 4556 protocol extension that lets a client authenticate to Kerberos with a certificate and receive a TGT.&quot; },
  { term: &quot;NTAuthCertificates&quot;, definition: &quot;Forest-wide AD container listing CA certificates trusted by the KDC for client authentication. Publication here makes a CA&apos;s key a trust root parallel to krbtgt.&quot; },
  { term: &quot;ENROLLEE_SUPPLIES_SUBJECT&quot;, definition: &quot;msPKI-Certificate-Name-Flag bit (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT) that lets the requester specify the certificate Subject or SAN; primary primitive of ESC1.&quot; },
  { term: &quot;EDITF_ATTRIBUTESUBJECTALTNAME2&quot;, definition: &quot;CA-side registry flag that lets any request include a SAN of choice; primary primitive of ESC6.&quot; },
  { term: &quot;szOID_NTDS_CA_SECURITY_EXT&quot;, definition: &quot;OID 1.3.6.1.4.1.311.25.2; certificate extension carrying the requester SID. Introduced in KB5014754; load-bearing element of strong mapping.&quot; },
  { term: &quot;Strong vs Weak Mapping&quot;, definition: &quot;Per KB5014754: X509IssuerSerialNumber, X509SKI, X509SHA1PublicKey are strong; UPN, SAN, and other formats are weak and rejected under Full Enforcement.&quot; },
  { term: &quot;ADCSESC1&quot;, definition: &quot;BloodHound CE edge representing an ESC1 path: low-priv principal can enroll into a template with ESS + Client Authentication EKU.&quot; },
  { term: &quot;CoerceAndRelayNTLMToADCS&quot;, definition: &quot;BloodHound CE edge representing the ESC8 chain: SMB-coerce a computer, relay NTLM auth to the CA&apos;s Web Enrollment endpoint, get a certificate impersonating the coerced computer.&quot; }
]} questions={[
  { q: &quot;Why does rotating krbtgt not close the AD CS escalation paths?&quot;, a: &quot;Because every NTAuth-published CA&apos;s private key is a separate authenticator-minting trust root parallel to krbtgt. PKINIT honors any valid certificate signed by an NTAuth CA. Rotating krbtgt does not touch those private keys.&quot; },
  { q: &quot;Of the sixteen named ESCs, how many have received CVE-class Microsoft patches and which ones?&quot;, a: &quot;Three: CVE-2022-26923 (Certifried, the dNSHostName impersonation chain, May 2022), CVE-2024-49019 (EKUwu / ESC15, V1 template Application Policies override, November 2024), and the KB5005413 NTLM-relay hardening track for ESC8 (July 2021, configuration guidance rather than a binary patch).&quot; },
  { q: &quot;What is the difference between ESC8 and ESC11, and why does BloodHound CE graph one but not the other?&quot;, a: &quot;Both are NTLM relay attacks against AD CS. ESC8 relays to the HTTP Web Enrollment role service (/certsrv/). ESC11 relays to the default RPC enrollment transport (ICertPassage). BloodHound graphs ESC8 as the CoerceAndRelayNTLMToADCS edge because SMB coercion plus HTTP relay has a stable principal-graph shape; ESC11&apos;s RPC trigger (IF_ENFORCEENCRYPTICERTREQUEST not set) does not have an equivalent coercion gadget that the principal-graph model can express.&quot; },
  { q: &quot;Which ESC bypasses KB5014754&apos;s strong-mapping enforcement?&quot;, a: &quot;ESC16. The CA&apos;s DisableExtensionList registry value can list the szOID_NTDS_CA_SECURITY_EXT OID, instructing the CA to omit the SID extension from every certificate it issues. The KDC then falls back to weak mapping for those certificates, defeating the strong-mapping enforcement.&quot; },
  { q: &quot;What is the recommended Lane 3 response if a CA&apos;s private key is suspected compromised?&quot;, a: &quot;Revoke the CA&apos;s chain, decommission the CA, build a replacement on new hardware, publish the new CA into NTAuthCertificates, distrust the old CA&apos;s certificates throughout the forest, and re-issue every credential that depended on the compromised CA. A multi-week IR operation analogous in scale to a forest rebuild for krbtgt compromise.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>active-directory</category><category>ad-cs</category><category>pkinit</category><category>kerberos</category><category>red-team</category><category>security</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>KRBTGT: The Account That Owns Active Directory</title><link>https://paragmali.com/blog/krbtgt-the-account-that-owns-active-directory/</link><guid isPermaLink="true">https://paragmali.com/blog/krbtgt-the-account-that-owns-active-directory/</guid><description>Active Directory ships with one cryptographic key whose disclosure forges valid TGTs for every principal -- and why rotating it is necessary but not sufficient.</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>
Active Directory&apos;s `krbtgt` account is the one secret in any Windows domain whose disclosure forges valid Ticket-Granting Tickets for every principal -- including ones that do not exist. Twelve years of attacks (Golden, Diamond, Sapphire) and Microsoft&apos;s responses (the MS14-068 patch, KrbtgtFullPacSignature, the two-reset rotation procedure) converge on one fact: krbtgt rotation invalidates forged TGTs but does not recover the systemic compromise that produced them. That distinction is why confirmed krbtgt compromise is a forest-rebuild event in modern incident-response playbooks, not a key-rotation event.
&lt;h2&gt;1. Ninety Seconds to Domain Admin&lt;/h2&gt;
&lt;p&gt;A single &lt;code&gt;mimikatz kerberos::golden&lt;/code&gt; command, with the krbtgt account&apos;s AES-256 long-term key in hand, walks the attacker onto any resource in the domain as Administrator. No Domain Admin password was reset. No Domain Admin account was created. No SACL on a sensitive object fired. No LSASS on any host was dumped. No signature-based IDS rule triggered. The attacker holds exactly one cryptographic key -- the long-term key of the RID-502 service account named &lt;code&gt;krbtgt&lt;/code&gt; -- and the entire Kerberos trust hierarchy of the domain now accepts whatever they sign [@mitre-t1558001]. The section title&apos;s &quot;ninety seconds&quot; is an illustration of how fast the attack is on the wall clock, not a measured demonstration from a published primary.&lt;/p&gt;
&lt;p&gt;The operator sequence is short enough to quote. Earlier in the engagement, the attacker ran &lt;code&gt;lsadump::dcsync /user:contoso\krbtgt&lt;/code&gt; from a member-server foothold and walked off with the krbtgt long-term key material [@mimikatz]. Then they switched tools to forge a ticket from scratch:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mimikatz # kerberos::golden /domain:contoso.local
                            /sid:S-1-5-21-1004336348-1177238915-682003330
                            /aes256:&amp;lt;key&amp;gt;
                            /user:Administrator /id:500
                            /groups:512,513,518,519,520 /ptt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That single command, documented by Sean Metcalf for operators in 2015 [@adsec-1640], does the forgery in process memory, injects the ticket into the local Kerberos cache (&lt;code&gt;/ptt&lt;/code&gt; = pass-the-ticket), and lets the next &lt;code&gt;dir \\dc01\admin&lt;/code&gt; succeed.&lt;/p&gt;
&lt;p&gt;Count the controls that did not fire while the forged ticket was being minted and presented. No Domain Admin password reset, because the attacker never used a Domain Admin password. No new privileged account, because the attacker impersonated an existing one (RID 500). No SACL on a sensitive object, because the ticket was already approved by the Kerberos trust root before any object was touched. No LSASS dump on a writeable DC, because &lt;a href=&quot;https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/&quot; rel=&quot;noopener&quot;&gt;DCSync&lt;/a&gt; is a replication API call, not a memory scrape [@mitre-t1003006]. No IDS hit on a known-malicious payload, because Mimikatz lives in attacker process memory and the wire traffic is, structurally, a TGS-REQ. No anomalous logon time, MFA prompt, or Conditional Access decision, because Kerberos pre-authentication is satisfied by holding a valid TGT and the TGT was minted offline.&lt;/p&gt;
&lt;p&gt;The article&apos;s load-bearing thesis: within the Kerberos trust root of a single domain, the krbtgt key is the unique secret whose disclosure yields valid TGTs for every principal -- including ones that do not exist. The technical recovery (two-reset rotation) is well-documented [@ms-forest-recovery] and does cryptographically invalidate forged tickets. But the operational recovery from a confirmed krbtgt compromise is a forest-rebuild event for reasons that have nothing to do with the krbtgt key itself.&lt;/p&gt;
&lt;p&gt;This produces an apparent contradiction. Microsoft documents a clean two-reset rotation procedure with a ten-hour interval [@ms-forest-recovery]; Mandiant- and SpecterOps-style incident-response playbooks treat confirmed krbtgt compromise as a forest-rebuild event [@specterops-dot2]. Both statements are simultaneously true. The job of the next ten thousand words is to explain why -- starting with what krbtgt actually is. Not the key. Not the protocol. The account itself: RID 502, disabled, indelible.&lt;/p&gt;
&lt;h2&gt;2. The Account: RID 502, Disabled, Indelible&lt;/h2&gt;
&lt;p&gt;Open Active Directory Users and Computers on a fresh Windows Server 2022 domain promoted ten seconds ago. In the &lt;code&gt;Users&lt;/code&gt; container there is an account called &lt;code&gt;krbtgt&lt;/code&gt;. It has no password visible to the admin. It is disabled. Try to enable it -- the checkbox accepts the click, but the next replication cycle puts the account right back into the disabled state. Try to rename it -- the operation appears to succeed, but the &lt;code&gt;objectSID&lt;/code&gt; does not change. Try to delete it -- the operation fails outright. You cannot log in as it; the disabled-for-interactive-logon property is enforced inside the Security Accounts Manager. The account exists exactly because the domain exists; the lifetime of the account and the lifetime of the domain are the same lifetime [@ms-default-accounts].&lt;/p&gt;
&lt;p&gt;Why does Active Directory ship with an account that no admin can use, no attacker can authenticate as interactively, and no operator can remove?&lt;/p&gt;

The Kerberos Ticket-Granting Ticket service account that exists, exactly once per Active Directory domain, to hold the long-term cryptographic key the domain controllers use to encrypt and sign every TGT issued in the domain. The account name itself is the Kerberos principal name (`krbtgt/DOMAIN@DOMAIN`) inherited from MIT&apos;s 1988 Kerberos v4 design.
&lt;p&gt;&lt;strong&gt;Creation.&lt;/strong&gt; The account is created automatically when the first writeable domain controller is promoted in a new domain. The Microsoft Learn default-accounts page lists it alongside &lt;code&gt;Administrator&lt;/code&gt; and &lt;code&gt;Guest&lt;/code&gt; as one of the three default local accounts in the &lt;code&gt;Users&lt;/code&gt; container, with the verbatim note that &quot;the KRBTGT account can&apos;t be enabled in Active Directory&quot; [@ms-default-accounts]. The account&apos;s lifecycle is bound to the domain&apos;s lifecycle; there is no operator-controllable provisioning of a krbtgt account, and no de-provisioning short of demoting the domain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RID 502.&lt;/strong&gt; The relative identifier at the tail of the account&apos;s SID (&lt;code&gt;S-1-5-21-&amp;lt;domain&amp;gt;-502&lt;/code&gt;) is fixed by the well-known SID specification [@ms-sids]. Sean Metcalf&apos;s operator primer confirms the RID-502 binding directly: &quot;Each Active Directory domain has an associated KRBTGT account ... The SID for the KRBTGT account is &lt;code&gt;S-1-5-&amp;lt;domain&amp;gt;-502&lt;/code&gt;&quot; [@adsec-483].RIDs 500 through 1000 are reserved for built-in security principals; 500 is Administrator, 501 is Guest, 502 is krbtgt. Renaming the &lt;code&gt;sAMAccountName&lt;/code&gt; cannot move the RID. The KDC service derives its key lookups from the principal name, which binds to the RID, not from the friendly name shown in ADUC. Renaming krbtgt as a defensive measure is a fallacy that the next section will sharpen further.&lt;/p&gt;
&lt;p&gt;Each Read-Only Domain Controller has its own &lt;code&gt;krbtgt_&amp;lt;rid&amp;gt;&lt;/code&gt; account whose key signs only that RODC&apos;s tickets. The full-domain krbtgt account is read-only from the RODC&apos;s perspective -- the design property that lets RODCs participate in Kerberos without holding the full-domain trust root [@adsec-483].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Container.&lt;/strong&gt; &lt;code&gt;CN=Users,DC=&amp;lt;domain&amp;gt;&lt;/code&gt;. The standard Users container, not a Tier-0 OU or a Protected Users group. The account is privileged by virtue of its RID, not by virtue of its containership. Moving it into a different container does not change its semantic role to the KDC.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disabled for interactive logon.&lt;/strong&gt; Documented verbatim on the Microsoft Learn default-accounts page: &quot;The KRBTGT account can&apos;t be enabled in Active Directory&quot; [@ms-default-accounts]. The account is reserved for the KDC service. There is no interactive logon surface attached, no LSA logon-rights grant, no Kerberos pre-authentication path that produces a TGT &lt;em&gt;for&lt;/em&gt; the krbtgt account itself. The account exists to provide a key, not to authenticate.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Indelible and unrenamable.&lt;/strong&gt; Also from the same Microsoft Learn page: &quot;This account can&apos;t be deleted, and the account name can&apos;t be changed&quot; [@ms-default-accounts]. ADUC will show a renamed display, but the underlying object identity (the RID, the principal name) is fixed by the directory schema and by &lt;code&gt;LsaSrv&lt;/code&gt; enforcement on the writeable DCs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Password.&lt;/strong&gt; System-generated, unknown to operators by design. Resetting it via ADUC produces a value Active Directory immediately replaces with a fresh system-generated value. The mechanism that produces the current key is therefore not operator-controllable; rotation is the only primitive operators have over the key value [@ms-forest-recovery].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Password history equals 2.&lt;/strong&gt; Documented verbatim on the AD Forest Recovery page: &quot;The password history value for the krbtgt account is 2, meaning it includes the two most recent passwords&quot; [@ms-forest-recovery]. This is the mechanical foundation for the two-reset procedure Section 7 will dissect. The KDC keeps both a &lt;em&gt;current&lt;/em&gt; and a &lt;em&gt;previous&lt;/em&gt; key in the krbtgt account; in-flight TGT validation tries both during the brief window after a rotation; one reset retires only the older of the two; a second reset, separated by at least the maximum ticket lifetime, evicts the key the attacker held.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where the key lives.&lt;/strong&gt; The KDC service (&lt;code&gt;kdcsvc.dll&lt;/code&gt;) on every writeable DC reads the krbtgt long-term key from &lt;code&gt;ntds.dit&lt;/code&gt; at startup and holds it in process memory for ticket signing and validation. &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt;&apos;s VBS trustlet -- LSAISO -- does not isolate this read on writeable DCs by design: a DC &lt;em&gt;must&lt;/em&gt; read the key to issue tickets [@ms-credential-guard] (see also §10 Aside on why Credential Guard skips the DC). This is the structural asymmetry that makes the krbtgt key reachable to any attacker who can compromise a writeable DC (or invoke its replication API remotely), even on a system where Credential Guard is otherwise enforced everywhere else.&lt;/p&gt;
&lt;p&gt;We know what the account is now: a non-interactive, indelible, RID-502 service principal with a system-generated, two-slot password history. But the account is just the container. The rest of the article cares about the &lt;em&gt;long-term cryptographic key&lt;/em&gt; it holds.&lt;/p&gt;
&lt;h2&gt;3. The Key: What RFC 4120 and [MS-KILE] Specify&lt;/h2&gt;
&lt;p&gt;Hand a network capture of a Kerberos AS-REP to a Wireshark dissector. The dissector shows the TGT as a sequence of ASN.1 fields. One field is named &lt;code&gt;enc-part&lt;/code&gt; and its content is opaque. The dissector knows the format of what is &lt;em&gt;inside&lt;/em&gt; that opaque blob -- an &lt;code&gt;EncTicketPart&lt;/code&gt; -- but it cannot show the field values because the blob is encrypted [@rfc4120]. Encrypted under what? Under one key: the long-term key of the principal named &lt;code&gt;krbtgt/CONTOSO.LOCAL@CONTOSO.LOCAL&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The Microsoft specification puts it as plainly as is possible to put it. [MS-KILE] specifies that the KDC encrypts every ticket using the long-term cryptographic key of the krbtgt principal, citing RFC 4120 §5.2.2 [@mskile]. That sentence, more than any other in the Microsoft Open Specifications corpus, is the cryptographic foundation of Active Directory authentication. Every TGT issued by every writeable DC in the domain is encrypted under one key. There is no per-account key, no per-DC key, no rolling subkey. One key, one trust scope.&lt;/p&gt;

The credential the Kerberos Key Distribution Center issues at logon, encrypted under the KDC&apos;s own service key (in Windows, the krbtgt account&apos;s long-term key), that the client subsequently presents to request service tickets without re-authenticating with a password. RFC 4120 §5.3 defines its fields; [MS-KILE] specifies the Windows wire profile [@rfc4120][@mskile].

The Kerberos service that issues TGTs (the Authentication Service) and exchanges TGTs for service tickets (the Ticket-Granting Service). In Active Directory the KDC runs as `kdcsvc.dll` on every writeable domain controller; it holds the krbtgt long-term key in process memory for the lifetime of the service [@rfc4120].
&lt;h3&gt;Inside the encrypted blob&lt;/h3&gt;
&lt;p&gt;RFC 4120 §5.3 specifies the fields of the &lt;code&gt;EncTicketPart&lt;/code&gt;: a session key the KDC generates for this TGT, the client&apos;s name, the cross-domain transit path, the timestamps (&lt;code&gt;authtime&lt;/code&gt;, &lt;code&gt;starttime&lt;/code&gt;, &lt;code&gt;endtime&lt;/code&gt;, &lt;code&gt;renew-till&lt;/code&gt;), the optional client-address list, and a final field of &lt;code&gt;authorization-data&lt;/code&gt; that Windows uses to carry the Privilege Attribute Certificate [@rfc4120].&lt;/p&gt;

The Windows-specific data structure embedded inside the `authorization-data` field of every Kerberos ticket. The PAC carries the user&apos;s SID, the SIDs of every group the user belongs to, account restrictions, profile path, logon server, and a small set of cryptographic signatures the KDC computes to bind the structure to the ticket. Defined in [MS-PAC] [@mspac].
&lt;p&gt;The PAC is where the load-bearing security claim of Windows Kerberos lives. RFC 4120 itself does not care about groups; it cares about whether the client can prove identity to a server. The PAC carries the &lt;em&gt;authorization&lt;/em&gt; layer Windows needs on top of authentication: which security principal the ticket represents, which groups confer which permissions, which restrictions apply [@mspac]. The first thing a Windows file server does when it receives a service ticket is decode the PAC, read the SIDs, and run the access-check algorithm.&lt;/p&gt;
&lt;h3&gt;The three signatures inside every PAC&lt;/h3&gt;
&lt;p&gt;The PAC is integrity-protected by a small set of signatures the KDC computes when it issues the ticket. As of the [MS-PAC] revision 26.0 dated June 10, 2024 [@mspac], a TGT-resident PAC carries three of them:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The PAC server signature.&lt;/strong&gt; A keyed HMAC computed under the &lt;em&gt;service&lt;/em&gt; key. For a TGT the service is &lt;code&gt;krbtgt/DOMAIN&lt;/code&gt;, so the server signature is computed under the krbtgt long-term key. For a service ticket the server signature is computed under the service account&apos;s long-term key (the file server&apos;s machine-account key, for example) [@mspac].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The PAC KDC signature.&lt;/strong&gt; A keyed HMAC computed under the krbtgt long-term key, signing the bytes of the server signature. This is the pre-2022 anchor of PAC integrity: even if a service holding only its own key could verify the server signature, only the KDC (or anyone holding the krbtgt key) could compute the matching KDC signature. The &quot;pre-2022&quot; framing tracks the deployment of KB5020805&apos;s Full PAC Signature, documented in §5 Generation 6 [@kb5020805].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Full PAC Signature.&lt;/strong&gt; Added by Microsoft&apos;s response to CVE-2022-37967, deployed via KB5020805 starting November 8, 2022 and enforced by default since July 11, 2023 [@kb5020805][@cve-2022-37967]. Computed by the KDC over the &lt;em&gt;entire&lt;/em&gt; PAC -- including the older two signatures -- and stored alongside them. Also computed under the krbtgt long-term key.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

flowchart TD
    PAC[PAC contents: SIDs, groups, restrictions] --&amp;gt; SSig[Server Signature]
    PAC --&amp;gt; KSig[KDC Signature]
    PAC --&amp;gt; FSig[Full PAC Signature]
    SSig --&amp;gt; KEY[&quot;krbtgt long-term key (TGT)&quot;]
    KSig --&amp;gt; KEY
    FSig --&amp;gt; KEY
    KEY --&amp;gt; TGT[EncTicketPart for TGT]
    TGT --&amp;gt; WIRE[AS-REP / TGS-REP on the wire]
&lt;p&gt;This is the architectural fact the rest of the article will refer back to. The addition of the Full PAC Signature did not relocate the trust to a different key. All three PAC signatures on a TGT terminate at the krbtgt long-term key. An attacker who holds the krbtgt key computes all three correctly in the same step. This is the precise technical observation that motivates the Section 5 attack cascade and the Section 7 rotation analysis.&lt;/p&gt;
&lt;h3&gt;The enctype matrix&lt;/h3&gt;
&lt;p&gt;The krbtgt account does not hold a single key; it holds a set of keys, one per Kerberos encryption type advertised in &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; on the account object. RFC 4120 §5.2.9 defines the enctype numbers; common Windows values are AES-256-CTS-HMAC-SHA1-96 (enctype 18), AES-128 (enctype 17), and the legacy RC4-HMAC (enctype 23) [@rfc4120]. AES-256 has been the recommended default for newly-provisioned krbtgt accounts since the Windows Server 2008 R2 / Windows Server 2012 functional levels, though early Windows Server 2008 deployments often required a krbtgt password reset to materialise the AES keys. The post-2017 AES-SHA2 family (enctypes 19 and 20) is defined by IETF but not deployed in mainline Windows production as of [MS-KILE] revision 47.0 dated April 27, 2026 [@mskile].&lt;/p&gt;

A numeric identifier for the cryptographic algorithm and key length used to encrypt a Kerberos message. RFC 4120 §5.2.9 enumerates them; common Windows values are 17 (AES-128), 18 (AES-256), and 23 (the legacy RC4-HMAC). Each principal&apos;s long-term key is derived per enctype, so the krbtgt account stores multiple key derivations side by side [@rfc4120].
&lt;p&gt;Each derivation is stored in both &lt;em&gt;current&lt;/em&gt; and &lt;em&gt;previous&lt;/em&gt; slots; rotating the krbtgt password rederives the entire set for the new password and shifts the previous derivations into the previous slot.&lt;/p&gt;
&lt;h3&gt;FAST armoring sits next to, not above, the krbtgt key&lt;/h3&gt;
&lt;p&gt;RFC 6113 / [MS-KILE] Flexible Authentication Secure Tunneling adds a second key layer for the client-facing pre-authentication exchange, armoring the AS-REQ under a separate channel key derived from a TGT the client already holds. FAST hardens pre-authentication against offline brute-force. It does not change the fact that the TGT&apos;s &lt;code&gt;enc-part&lt;/code&gt; is encrypted under the krbtgt key on its way back to the client [@mskile]. No Kerberos extension shipped through 2026 moves the TGT&apos;s trust anchor anywhere other than the krbtgt long-term key.&lt;/p&gt;

Within a Kerberos domain, every TGT reduces to the same key, and that key has a name: krbtgt.
&lt;p&gt;That sentence is the load-bearing claim the rest of the article rests on. The next section explains how a 1988 academic design decision became the cryptographic foundation of every Windows domain alive today.&lt;/p&gt;
&lt;p&gt;{`
// Simplified model of the three PAC signatures on a TGT.
// Each signature is a keyed HMAC computed under the krbtgt long-term key.
const pacContents = &quot;SIDs, groups, restrictions&quot;;
const krbtgtKey = &quot;&amp;lt;32-byte AES-256 long-term key&amp;gt;&quot;;&lt;/p&gt;
&lt;p&gt;function hmac(key, data) {
  return key === krbtgtKey
    ? &quot;SIG(&quot; + data + &quot;)&quot;           // attacker-with-key computes valid sigs
    : &quot;INVALID&quot;;                    // attacker-without-key cannot forge them
}&lt;/p&gt;
&lt;p&gt;function buildPACBlock(attackerKey) {
  const serverSig = hmac(attackerKey, pacContents);
  const kdcSig    = hmac(attackerKey, serverSig);
  const fullPAC   = hmac(attackerKey, pacContents + serverSig + kdcSig);
  const validates = [serverSig, kdcSig, fullPAC].every(s =&amp;gt; s !== &quot;INVALID&quot;);
  return { serverSig, kdcSig, fullPAC, validates };
}&lt;/p&gt;
&lt;p&gt;console.log(&quot;with krbtgt key   :&quot;, buildPACBlock(krbtgtKey).validates);
console.log(&quot;without krbtgt key:&quot;, buildPACBlock(&quot;guess-key&quot;).validates);
`}&lt;/p&gt;
&lt;h2&gt;4. Origins: 1988 Athena, RFC 4120, [MS-KILE]&lt;/h2&gt;
&lt;p&gt;Open the bibliography of RFC 4120 and find an entry tagged &lt;code&gt;[Ste88]&lt;/code&gt;: &quot;Steiner, J., Neuman, C., and J. Schiller, &apos;Kerberos: An Authentication Service for Open Network Systems,&apos; USENIX Conference Proceedings, February 1988&quot; [@rfc4120]. The principal name &lt;code&gt;krbtgt&lt;/code&gt; is in that paper. It has been carried forward unchanged through RFC 1510 (1993) [@rfc1510], through Active Directory&apos;s February 2000 release, through RFC 4120 (2005) [@rfc4120], through the first [MS-KILE] revision (2007), and into the current [MS-KILE] revision 47.0 dated April 27, 2026 [@mskile]. Thirty-eight years.&lt;/p&gt;
&lt;p&gt;What did the 1988 design decision look like, and what has changed about its security properties since?&lt;/p&gt;
&lt;h3&gt;MIT Project Athena, 1983-1991&lt;/h3&gt;
&lt;p&gt;Project Athena ran at MIT from 1983 to 1991 as a campus-scale distributed-computing experiment funded primarily by IBM and DEC [@project-athena]. The authentication problem Athena needed to solve was the one every multi-user network has needed to solve since: how do you let thousands of workstations talk to thousands of services without broadcasting cleartext passwords on every connection? Steiner, Neuman, and Schiller presented their answer at the Winter USENIX conference in Dallas in February 1988. Their design introduced the &lt;code&gt;krbtgt&lt;/code&gt; principal name and the trust property that one key encrypts every TGT in the Kerberos domain [@athena1988].&lt;/p&gt;
&lt;p&gt;The principal name &lt;code&gt;krbtgt&lt;/code&gt; predates Active Directory by twelve years. MIT&apos;s 1988 USENIX paper used the name, RFC 1510 standardised it in 1993 [@rfc1510], and Windows 2000 inherited it unchanged. There is no Microsoft-specific Kerberos principal naming convention; the convention is IETF.&lt;/p&gt;
&lt;p&gt;The design property that one key encrypts every TGT was not framed in 1988 as a security risk. It was framed as a &lt;em&gt;simplification&lt;/em&gt;: by giving the TGS one stable identity that issues every TGT, the protocol does not need to negotiate per-session KDC identities or per-server validation paths. The protocol reduces, mathematically, to two questions: did the KDC issue this TGT, and did the TGT permit the subsequent TGS-REQ for this service? Both reduce to &quot;does this signature validate under the krbtgt key?&quot;&lt;/p&gt;
&lt;h3&gt;From RFC 1510 to [MS-KILE]&lt;/h3&gt;
&lt;p&gt;John Kohl and Clifford Neuman published RFC 1510 in September 1993, standardising Kerberos version 5 [@rfc1510]. The &lt;code&gt;krbtgt/DOMAIN@DOMAIN&lt;/code&gt; principal-name convention carried forward unchanged from Athena. RFC 1510 is the document Microsoft engineers read when they chose Kerberos v5 as the Windows 2000 default authentication protocol; the krbtgt account became part of the AD schema at the Windows 2000 ship date (RTM December 15, 1999; general availability February 17, 2000) [@windows-2000]. The Microsoft Learn default-accounts page binds the two specifications to the same account: &quot;KRBTGT is also the security principal name used by the KDC for a Windows Server domain, as specified by RFC 4120&quot; [@ms-default-accounts].&lt;/p&gt;
&lt;p&gt;RFC 4120, published in July 2005 by Neuman, Yu, Hartman, and Raeburn, obsoleted RFC 1510 [@rfc4120]. The principal name carried forward unchanged again. Section 5.3 defines the wire format of a ticket; §6.2 defines the principal-name convention. Microsoft Open Specifications then published the first [MS-KILE] revision in March 2007, documenting the Windows wire profile on top of RFC 4120. The current revision -- 47.0, dated April 27, 2026 -- still says the same thing: the krbtgt long-term key encrypts every TGT [@mskile]. The Microsoft overlay on top of the IETF specification is the AD-account-management surface: RID 502 fixed, password system-generated, password-history-of-2, disabled-for-interactive-logon, automatic provisioning at first-DC promotion [@ms-default-accounts][@ms-forest-recovery].&lt;/p&gt;
&lt;p&gt;Every Kerberos domain on the public Internet today has a &lt;code&gt;krbtgt&lt;/code&gt; principal in it. The name has not moved in thirty-eight years. Only the AD-specific overlay is what gives this article its Windows-specific subject; the protocol substrate is older than the attack surface by twenty-six years.&lt;/p&gt;
&lt;p&gt;The principal name and the trust property are nearly forty years old. The exploit chain that targets them is twelve. The interesting question is what happened in the twelve years that turned an academic design decision into the most consequential single key in enterprise computing. That story has a beginning at Black Hat USA on August 7, 2014.&lt;/p&gt;
&lt;h2&gt;5. The Attack Cascade, 2014 to 2024&lt;/h2&gt;
&lt;p&gt;Six generations of attack span ten years. None of them found a way to forge a TGT &lt;em&gt;without&lt;/em&gt; the krbtgt key; the search space is mathematically closed in that direction. What they did instead is get progressively better at hiding the forgery inside genuine-looking wire traffic. By 2022, the forgery and the legitimate TGT are wire-indistinguishable. Here is how that arc unfolded.&lt;/p&gt;

gantt
    title Attack and defence generations
    dateFormat YYYY-MM-DD
    axisFormat %Y
    section Attack
    Gen 0 Academic baseline       :done, g0, 2000-02-01, 2014-08-05
    Gen 1 MS14-068 PAC forgery    :crit, g1, 2014-11-18, 90d
    Gen 2 Golden Ticket           :crit, g2, 2014-08-07, 2920d
    Gen 3 Silver Ticket           :       g3, 2015-01-01, 4000d
    Gen 4 Diamond Ticket          :crit, g4, 2022-06-21, 1700d
    Gen 5 Sapphire Ticket         :crit, g5, 2022-10-15, 1300d
    section Defence
    MS14-068 patch                :done, d1, 2014-11-18, 30d
    MDI alert family              :done, d2, 2016-01-01, 800d
    Full PAC Signature audit      :done, d3, 2022-12-13, 210d
    Full PAC Signature enforce    :done, d4, 2023-07-11, 90d
    Compatibility removed         :done, d5, 2023-10-10, 30d
&lt;h3&gt;Generation 0 (pre-November 2014): the academic baseline&lt;/h3&gt;
&lt;p&gt;Two assumptions held for fourteen years between Windows 2000 RTM and Black Hat USA 2014. First, the PAC&apos;s two signatures -- the Server Signature and the KDC Signature -- were treated as adequate; the [MS-PAC] specification required the KDC Signature to be a keyed HMAC under the krbtgt key, but Windows KDCs in practice accepted weaker non-keyed checksums on it (CRC32, RSA-MD5) [@mspac][@ms14068]. Second, the long-term krbtgt key was held only on writeable DCs and was considered unreachable to remote attackers because no remote primitive existed to extract it. Both assumptions failed within months of each other. The MS14-068 disclosure broke the first; the productionised DCSync primitive in Mimikatz broke the second.&lt;/p&gt;
&lt;h3&gt;Generation 1 (November 18, 2014): MS14-068 and CVE-2014-6324&lt;/h3&gt;
&lt;p&gt;On November 18, 2014, Microsoft published security bulletin MS14-068, &quot;Vulnerability in Kerberos Could Allow Elevation of Privilege (3011780)&quot; [@ms14068]. The disclosure: the KDC validated PACs using a checksum algorithm that did not actually depend on the krbtgt key. Any authenticated domain user could forge a PAC asserting Domain Admin group membership, attach it to an otherwise-valid AS-REQ exchange, and the KDC would accept the forgery. The NVD entry for CVE-2014-6324 records that the bug &quot;allows remote authenticated domain users to obtain domain administrator privileges via a forged signature in a ticket, as exploited in the wild in November 2014, aka &apos;Kerberos Checksum Vulnerability&apos;&quot; [@cve-2014-6324]. CVSS 9.0. Critical for every supported Windows Server SKU. Exploited in the wild within hours of the bulletin.&lt;/p&gt;
&lt;p&gt;Discovery credit for MS14-068 appears across Metasploit module authorship, AttackerKB, and several practitioner write-ups as Tom Maddock. The MSRC bulletin verbatim says only &quot;privately reported&quot; and does not name the reporter publicly [@ms14068]. The Maddock attribution is folk knowledge; the MSRC primary does not confirm it.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s patch replaced the weak checksum with a real keyed HMAC under the krbtgt key, the same construction the [MS-PAC] document specifies today. The patch was correct: it restored PAC integrity to actual dependence on a real secret. It also, as a side-effect, elevated the krbtgt key from &quot;an important secret in the directory&quot; to &quot;the load-bearing secret of every authentication decision in the domain.&quot; From November 18, 2014 onward, an attacker who held the krbtgt key did not just hold a useful credential; the attacker held the &lt;em&gt;only&lt;/em&gt; credential the KDC could not check above.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The MS14-068 patch was correct -- it restored PAC integrity to dependence on the krbtgt key. Its side-effect was to elevate the krbtgt key from &quot;important&quot; to &quot;load-bearing for every authentication decision in the domain.&quot; From November 18, 2014 onward, the krbtgt key was the single secret worth attacking directly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Generation 2 (August 7, 2014): Golden Ticket&lt;/h3&gt;
&lt;p&gt;Skip Duckwall and Benjamin Delpy presented &quot;Abusing Microsoft Kerberos: Sorry you guys don&apos;t get it&quot; at Black Hat USA on August 7, 2014 [@infocondb-bh2014]. The technique they demonstrated is what Sean Metcalf later popularised as the Golden Ticket: with the krbtgt key in hand, an attacker forges a TGT from scratch for any principal SID with any group memberships [@adsec-1640]. The KDC validates the TGT by decrypting &lt;code&gt;enc-part&lt;/code&gt; with the krbtgt key. There is no upstream authority to check, because krbtgt &lt;em&gt;is&lt;/em&gt; the authority. MITRE T1558.001 codifies the technique [@mitre-t1558001]; Benjamin Delpy&apos;s Mimikatz &lt;code&gt;kerberos::golden&lt;/code&gt; command operationalises it [@mimikatz].&lt;/p&gt;

sequenceDiagram
    participant A as Attacker (holds krbtgt key)
    participant L as Local Kerberos cache
    participant K as KDC on a DC
    participant S as Target service
    A-&amp;gt;&amp;gt;A: Choose target SID and groups
    A-&amp;gt;&amp;gt;A: Build EncTicketPart locally
    A-&amp;gt;&amp;gt;A: HMAC PAC signatures under krbtgt key
    A-&amp;gt;&amp;gt;A: AES-encrypt enc-part under krbtgt key
    A-&amp;gt;&amp;gt;L: kerberos::ptt -- inject ticket
    L-&amp;gt;&amp;gt;K: TGS-REQ presenting forged TGT
    K-&amp;gt;&amp;gt;K: Decrypt TGT with krbtgt key -- valid
    K-&amp;gt;&amp;gt;L: TGS-REP for target service
    L-&amp;gt;&amp;gt;S: Present service ticket -- access granted
&lt;p&gt;The Golden Ticket works because of the single-key trust property the 1988 design chose. There is nothing in the protocol that asks &quot;is this TGT in the KDC&apos;s issuance log?&quot; The TGT is self-verifying. If it decrypts and its signatures validate under the key, it is, by definition, a TGT.&lt;/p&gt;
&lt;p&gt;Why, then, does Golden Ticket sometimes get caught? Because the default Mimikatz invocation leaves four observable artefacts that Microsoft Defender for Identity ships dedicated alerts for, under the umbrella of the Suspected-Golden-Ticket alert family [@mdi-classic][@mdi-credential]. Mimikatz historically defaulted to RC4-HMAC encryption (enctype 23), which is anomalous on a modern AD where AES is standard. Mimikatz historically defaulted to a ten-year ticket lifetime, against the AD &lt;code&gt;MaxTicketAge&lt;/code&gt; default of ten hours. The attacker frequently asserts groups the user does not actually hold, which produces a &quot;forged authorization data&quot; anomaly. And the attacker sometimes forges a ticket for an account that does not exist in the directory at all, which produces a &quot;nonexistent account&quot; anomaly. Microsoft&apos;s live MDI alerts page enumerates six External IDs in the family: 2009 (encryption downgrade), 2013 (forged authorization data), 2022 (time anomaly), 2027 (nonexistent account), 2032 (ticket anomaly), and 2040 (ticket anomaly using RBCD) [@mdi-classic].&lt;/p&gt;
&lt;p&gt;The structural observation: every alert in this family detects &lt;em&gt;symptoms of forging from scratch&lt;/em&gt;. None of them detects the primitive of &lt;em&gt;holding the krbtgt key&lt;/em&gt;. That distinction is what makes Generation 4 (Diamond) and Generation 5 (Sapphire) interesting.&lt;/p&gt;
&lt;h3&gt;Generation 3 (parallel path): Silver Ticket&lt;/h3&gt;
&lt;p&gt;Silver Tickets forge a &lt;em&gt;service ticket&lt;/em&gt; (TGS) under a captured service-account key. They sidestep the krbtgt key entirely; the KDC is never involved in the forgery, and the forgery validates only against the one service whose key was captured. MITRE T1558.002 catalogues the technique [@mitre-t1558002]. Mentioned here so the question stops being asked. Silver Tickets are a sibling technique that targets a different trust root (per-service account keys), not the krbtgt key.&lt;/p&gt;
&lt;h3&gt;Generation 4 (June 2022): Diamond Ticket&lt;/h3&gt;
&lt;p&gt;In June 2022, Andrew Schwartz at TrustedSec and Charlie Clark at Semperis co-published &quot;A Diamond in the Ruff,&quot; documenting a refinement of Golden Ticket that defeats every PAC-content anomaly detection in one stroke [@trustedsec-diamond][@semperis-diamond]. The technique: instead of forging the TGT from scratch, the attacker requests a &lt;em&gt;real&lt;/em&gt; TGT from the KDC, then decrypts its &lt;code&gt;enc-part&lt;/code&gt; using the held krbtgt key, modifies the PAC contents, re-signs the PAC under the krbtgt key, re-encrypts the &lt;code&gt;enc-part&lt;/code&gt;, and walks away with a ticket whose every wire property -- &lt;code&gt;sname&lt;/code&gt;, &lt;code&gt;cname&lt;/code&gt;, &lt;code&gt;authtime&lt;/code&gt; skew matching the real KDC&apos;s clock, plausible &lt;code&gt;endtime&lt;/code&gt;, AES-256 envelope -- looks like a legitimate KDC-issued artefact.&lt;/p&gt;

sequenceDiagram
    participant A as Attacker (low-priv user, holds krbtgt key)
    participant K as KDC on a DC
    participant L as Local Kerberos cache
    participant S as Target service
    A-&amp;gt;&amp;gt;K: AS-REQ for low-priv user
    K-&amp;gt;&amp;gt;A: Real TGT, encrypted under krbtgt key
    A-&amp;gt;&amp;gt;A: Decrypt enc-part with held krbtgt key
    A-&amp;gt;&amp;gt;A: Modify PAC SIDs to Domain Admins
    A-&amp;gt;&amp;gt;A: Recompute PAC signatures under krbtgt key
    A-&amp;gt;&amp;gt;A: Re-encrypt enc-part under krbtgt key
    A-&amp;gt;&amp;gt;L: ptt -- inject modified TGT
    L-&amp;gt;&amp;gt;K: TGS-REQ presenting Diamond TGT
    K-&amp;gt;&amp;gt;K: Decrypt -- valid, signatures match
    K-&amp;gt;&amp;gt;L: TGS-REP for target service
    L-&amp;gt;&amp;gt;S: Access granted as Domain Admin
&lt;p&gt;Every MDI Suspected-Golden-Ticket detection disappears, by construction. The encryption type is AES-256 because the KDC issued it that way. The lifetime matches the AD policy because the KDC set it that way. The cname matches a real account because the attacker requested the TGT as a real low-privilege account they own. The only thing the attacker changed is the group SIDs inside the PAC, and the PAC signatures revalidate because the attacker recomputed them under the same krbtgt key the KDC would have used.&lt;/p&gt;
&lt;p&gt;TrustedSec verbatim: Diamond &quot;would almost certainly require access to the AES256 key&quot; [@trustedsec-diamond]. The KDC issued the real TGT in AES-256, so the attacker needs the AES-256 key to decrypt and re-encrypt -- not just the RC4 NTLM hash that the classic Golden Ticket can use.&lt;/p&gt;
&lt;p&gt;The Diamond Ticket disclosure pointed at an architectural problem: with the krbtgt key in hand, every PAC-content anomaly detection is defeated. Microsoft&apos;s structural answer was the Full PAC Signature in November 2022. We come to that in Generation 6.&lt;/p&gt;
&lt;h3&gt;Generation 5 (October 2022): Sapphire Ticket&lt;/h3&gt;
&lt;p&gt;Charlie Bromberg, who publishes under the handle Shutdown (&lt;code&gt;@_nwodtuhs&lt;/code&gt;) at Synacktiv and maintains The Hacker Recipes wiki, disclosed Sapphire Ticket in October 2022 [@hackrecipes-sapphire][@shutdownrepo-sapphire]. Where Diamond modifies the PAC, Sapphire &lt;em&gt;splices&lt;/em&gt; the PAC. The procedure abuses two Kerberos extensions in combination -- Service-for-User-to-Self (S4U2self) and User-to-User (U2U) -- to coerce the KDC into issuing a service ticket whose embedded PAC describes a target user the attacker wishes to impersonate. The attacker then extracts that genuine PAC from the service ticket and embeds it, unchanged, in a freshly constructed TGT signed under the held krbtgt key.&lt;/p&gt;

A Kerberos extension that lets a service request a ticket *to itself*, on behalf of another user, without that user presenting credentials. Originally designed for protocol-transition scenarios (a web service accepting forms-based auth and translating it to Kerberos for downstream calls). Defined in [MS-SFU] (Kerberos Protocol Extensions: Service for User and Constrained Delegation Protocol); referenced from [MS-KILE] [@mssfu].

A Kerberos extension defined in RFC 4120 §3.7 that allows a ticket to be encrypted under the recipient&apos;s session key rather than its long-term key, enabling two clients to authenticate to each other without either being a KDC-registered service [@rfc4120].

sequenceDiagram
    participant A as Attacker (low-priv user, holds krbtgt key)
    participant K as KDC on a DC
    participant L as Local Kerberos cache
    participant S as Target service
    A-&amp;gt;&amp;gt;K: AS-REQ for low-priv user
    K-&amp;gt;&amp;gt;A: Real attacker TGT
    A-&amp;gt;&amp;gt;K: S4U2self + U2U TGS-REQ for target user
    K-&amp;gt;&amp;gt;A: TGS containing target user&apos;s genuine PAC
    A-&amp;gt;&amp;gt;A: Extract genuine PAC from TGS
    A-&amp;gt;&amp;gt;A: Build new TGT, embed genuine PAC
    A-&amp;gt;&amp;gt;A: Sign three PAC signatures under krbtgt key
    A-&amp;gt;&amp;gt;A: Encrypt enc-part under krbtgt key
    A-&amp;gt;&amp;gt;L: ptt -- inject Sapphire TGT
    L-&amp;gt;&amp;gt;K: TGS-REQ presenting Sapphire TGT
    K-&amp;gt;&amp;gt;K: Decrypt -- valid, PAC is genuine
    K-&amp;gt;&amp;gt;L: TGS-REP for target service
    L-&amp;gt;&amp;gt;S: Access granted as target user
&lt;p&gt;By construction, there is no PAC-content anomaly to detect: the PAC inside the resulting TGT is literally a PAC the KDC issued for the target user, because the KDC &lt;em&gt;did&lt;/em&gt; issue it. The PAC&apos;s three signatures revalidate because the attacker held the krbtgt key to sign them; if Microsoft validates the Full PAC Signature on incoming tickets, that signature also validates because the attacker computed it under the same krbtgt key. Detection must move to traffic-flow analysis -- specifically, the anomalous S4U2self plus U2U TGS-REQ sequence on the wire -- and as of May 2026 no vendor has shipped a clean canonical default-enabled analytic for that signal [@unit42-gemstones].&lt;/p&gt;
&lt;p&gt;The Sapphire Ticket disclosure is widely misattributed to Charlie Clark (Semperis). The primary tooling artefact -- the Impacket PR #1411 conversation thread -- addresses the author as &lt;code&gt;@ShutdownRepo&lt;/code&gt;, who is Charlie Bromberg of Synacktiv [@impacket-1411]. The Hacker Recipes wiki and pgj11.com both confirm Bromberg as the author of record [@hackrecipes-sapphire][@pgj11]. The misattribution conflates Sapphire with Clark&apos;s separate &quot;AS Requested Service Tickets&quot; technique.&lt;/p&gt;
&lt;p&gt;The empirical artefact is the Impacket pull request #1411, in which Bromberg added the &lt;code&gt;-impersonate&lt;/code&gt; flag to &lt;code&gt;ticketer.py&lt;/code&gt; to put the tool into &quot;sapphire ticket mode&quot; [@impacket-1411][@shutdownrepo-sapphire]. Palo Alto Unit 42&apos;s &quot;Precious Gemstones&quot; survey is the vendor-side state-of-the-art summary [@unit42-gemstones].&lt;/p&gt;
&lt;h3&gt;Generation 6 (November 2022 to October 2023): KrbtgtFullPacSignature&lt;/h3&gt;
&lt;p&gt;Microsoft&apos;s formal response to the post-2014 attack arc shipped as KB5020805 starting November 8, 2022, addressing CVE-2022-37967 [@kb5020805][@cve-2022-37967]. The fix adds a new PAC signature -- the Full PAC Signature -- computed by the KDC over the &lt;em&gt;entire&lt;/em&gt; PAC including the older two signatures, validated on incoming tickets, and rolled out across five deployment phases:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;&lt;code&gt;KrbtgtFullPacSignature&lt;/code&gt; value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Initial Deployment&lt;/td&gt;
&lt;td&gt;November 8, 2022&lt;/td&gt;
&lt;td&gt;Signatures added, validation disabled&lt;/td&gt;
&lt;td&gt;1 (Compatibility)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Second Deployment&lt;/td&gt;
&lt;td&gt;December 13, 2022&lt;/td&gt;
&lt;td&gt;Audit mode default&lt;/td&gt;
&lt;td&gt;2 (Audit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third Deployment&lt;/td&gt;
&lt;td&gt;June 13, 2023&lt;/td&gt;
&lt;td&gt;Cannot disable signature addition&lt;/td&gt;
&lt;td&gt;(value 0 removed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default Enforcement&lt;/td&gt;
&lt;td&gt;July 11, 2023&lt;/td&gt;
&lt;td&gt;Enforcement default&lt;/td&gt;
&lt;td&gt;3 (Enforcement)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Removal of Compatibility&lt;/td&gt;
&lt;td&gt;October 10, 2023&lt;/td&gt;
&lt;td&gt;Audit removed, Enforcement permanent&lt;/td&gt;
&lt;td&gt;(registry key removed)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;KB5020805 documents the final state verbatim: &quot;Windows updates released on or after October 10, 2023 will do the following: Removes support for the registry subkey KrbtgtFullPacSignature. Removes support for Audit mode. All service tickets without the new PAC signatures will be denied authentication&quot; [@kb5020805].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The KB number for KrbtgtFullPacSignature is KB5020805, not KB5021131. KB5021131 is the paired but distinct KB for CVE-2022-37966 (encryption-type enforcement). The PAC-signature-specific KB is KB5020805. Secondary sources routinely confuse the two.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here is the structural fact. The Full PAC Signature is &lt;em&gt;also&lt;/em&gt; computed under the krbtgt key. So an attacker who holds the krbtgt key still mints fully-validating tickets, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sapphire Tickets, which never modify the PAC at all; the existing signatures the KDC issued are valid by construction, the Full PAC Signature included.&lt;/li&gt;
&lt;li&gt;Recomputed Diamond Tickets, in which the attacker simply computes the Full PAC Signature alongside the older KDC signature in the same step, because both depend on the same key the attacker holds.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;KrbtgtFullPacSignature retired one specific class of attack (Diamond Tickets that did not recompute the Full PAC Signature). It did not retire the underlying primitive (TGT forgery from a known krbtgt key). The PAC signature surface in Section 3 -- all three signatures terminating at the same key -- is exactly why this is so.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Full PAC Signature was Microsoft&apos;s structural response to Diamond Ticket. It is itself computed under the krbtgt key. So an attacker who holds the krbtgt key recomputes it in the same step as the KDC signature -- and Sapphire Tickets, which never modify the PAC at all, are unaffected by construction. CVE-2022-37967 retired one class of attack (PAC-modifying Diamond variants); it did not retire the primitive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Comparing the three forgery variants&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Golden&lt;/th&gt;
&lt;th&gt;Diamond&lt;/th&gt;
&lt;th&gt;Sapphire&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Requires krbtgt key?&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes (AES-256)&lt;/td&gt;
&lt;td&gt;Yes (AES-256)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Calls the KDC?&lt;/td&gt;
&lt;td&gt;No (forges from scratch)&lt;/td&gt;
&lt;td&gt;Yes (real AS-REQ)&lt;/td&gt;
&lt;td&gt;Yes (AS-REQ + S4U2self+U2U)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modifies the PAC?&lt;/td&gt;
&lt;td&gt;Builds it from scratch&lt;/td&gt;
&lt;td&gt;Yes (group SIDs)&lt;/td&gt;
&lt;td&gt;No (genuine PAC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defeats MDI encryption downgrade alert?&lt;/td&gt;
&lt;td&gt;No (defaults RC4)&lt;/td&gt;
&lt;td&gt;Yes (real AES)&lt;/td&gt;
&lt;td&gt;Yes (real AES)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defeats MDI time-anomaly alert?&lt;/td&gt;
&lt;td&gt;No (defaults 10y)&lt;/td&gt;
&lt;td&gt;Yes (KDC lifetime)&lt;/td&gt;
&lt;td&gt;Yes (KDC lifetime)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defeats MDI forged-auth-data alert?&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (still triggers if group mismatch detected via other means)&lt;/td&gt;
&lt;td&gt;Yes (PAC is genuine)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defeats Full PAC Signature (post-July 2023)?&lt;/td&gt;
&lt;td&gt;Yes (recomputed under held key)&lt;/td&gt;
&lt;td&gt;Yes (recomputed)&lt;/td&gt;
&lt;td&gt;Yes (genuine PAC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Known wire-residual?&lt;/td&gt;
&lt;td&gt;Encryption type, lifetime, groups&lt;/td&gt;
&lt;td&gt;Re-encryption-under-held-key timing&lt;/td&gt;
&lt;td&gt;S4U2self+U2U conjunction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Six generations from MS14-068 to KrbtgtFullPacSignature, and the residual primitive is exactly what the 1988 paper described: hold the key, mint the ticket. So what does the detection topology in 2026 actually catch?&lt;/p&gt;
&lt;h2&gt;6. The Detection Stack in 2026&lt;/h2&gt;
&lt;p&gt;Detection of krbtgt-class attacks in 2026 is a four-layer stack. Each layer has a specific class of signal it reads, a specific class of attack it catches, and a specific gap that the next layer is supposed to close. Three of the four layers have a known gap above them. The fourth has nothing above it.&lt;/p&gt;

flowchart TD
    L4[&quot;Layer 4 -- S4U2self plus U2U residual (no vendor analytic shipped)&quot;]
    L3[&quot;Layer 3 -- Network/SIEM (Sentinel, Splunk T1558.001)&quot;]
    L2[&quot;Layer 2 -- Behavioural (MDI Suspected-Golden-Ticket family)&quot;]
    L1[&quot;Layer 1 -- Posture (BloodHound DCSync edge)&quot;]
    KEY[&quot;krbtgt long-term key (the attacker&apos;s objective)&quot;]
    L1 --&amp;gt; L2
    L2 --&amp;gt; L3
    L3 --&amp;gt; L4
    L4 --&amp;gt; KEY
&lt;h3&gt;Layer 1: posture (BloodHound DCSync edge)&lt;/h3&gt;
&lt;p&gt;The posture layer asks a question with no per-event component: &quot;Who has rights that &lt;em&gt;could&lt;/em&gt; extract the krbtgt key, regardless of whether they have used those rights?&quot; In Active Directory terms, the answer is &quot;anyone holding &lt;code&gt;DS-Replication-Get-Changes&lt;/code&gt; plus &lt;code&gt;DS-Replication-Get-Changes-All&lt;/code&gt; rights against a writeable DC, plus anyone who holds privileges that allow them to grant those rights to themselves.&quot; BloodHound encodes the answer as a &lt;code&gt;DCSync&lt;/code&gt; edge in its graph; the canonical community Cypher query is &lt;code&gt;MATCH (u)-[:DCSync]-&amp;gt;(d:Domain) RETURN u, d&lt;/code&gt;. The current shipping release of BloodHound Community Edition is v9.1.0, dated 2026-05-06 per the release notes [@bloodhound-notes].&lt;/p&gt;

A replication primitive Mimikatz first productionised in August 2015. The attacker invokes the `DRSGetNCChanges` API call against a writeable domain controller, masquerading as a peer DC, and the target DC obligingly streams back the requested account secrets including the krbtgt long-term key. MITRE T1003.006 catalogues the technique [@mitre-t1003006]. Sean Metcalf&apos;s adsecurity.org write-up notes &quot;DCSync was written by Benjamin Delpy and Vincent Le Toux&quot; [@adsec-1729].
&lt;p&gt;What this layer detects: any principal whose existing AD permissions create a path to the krbtgt key. What this layer misses: any attacker who &lt;em&gt;already&lt;/em&gt; has the key. Posture is preventive, not detective. By the time the attacker is invoking &lt;code&gt;kerberos::golden&lt;/code&gt;, the posture layer has already missed its window.&lt;/p&gt;
&lt;h3&gt;Layer 2: behavioural (Microsoft Defender for Identity)&lt;/h3&gt;
&lt;p&gt;Microsoft Defender for Identity ships an alert family covering classic Golden-Ticket-from-Mimikatz behaviour. The live MDI classic alerts page enumerates six Suspected-Golden-Ticket External IDs: 2009 (encryption downgrade), 2013 (forged authorization data), 2022 (time anomaly), 2027 (nonexistent account), 2032 (ticket anomaly), and 2040 (ticket anomaly using RBCD) [@mdi-classic]. The Credential access section adds External ID 2006 for &quot;Suspected DCSync attack&quot; on the extraction side [@mdi-classic].&lt;/p&gt;
&lt;p&gt;What this layer detects: the Mimikatz Golden Ticket defaults plus the DCSync extraction primitive that produces the krbtgt key in the first place. What this layer misses: Diamond and Sapphire by construction. Diamond removes the PAC-content anomalies because every artefact except the modified group SIDs comes from the real KDC. Sapphire defeats PAC-content anomaly detection entirely by using a PAC the KDC genuinely issued via S4U2self plus U2U.&lt;/p&gt;
&lt;p&gt;The MDI credential-access alerts page is the entry point to the family in the modern Microsoft Defender XDR console layout [@mdi-credential].&lt;/p&gt;
&lt;h3&gt;Layer 3: network and SIEM (Sentinel, Splunk)&lt;/h3&gt;
&lt;p&gt;Multi-vendor SIEM content packs ship analytic rules covering Kerberos behaviours flagged under MITRE T1558.001. Splunk&apos;s research catalogue contains the canonical example: &quot;Kerberos Service Ticket Request Using RC4 Encryption&quot; detects TGS-REQ traffic with encryption-type 0x17 (RC4-HMAC), leveraging Windows Event 4769 from the DCs [@splunk-7d9]. Microsoft Sentinel ships parallel rules under the Microsoft Defender XDR content connector. The pattern these analytics share is reliance on encryption-type anomalies, group-membership anomalies, or lifetime anomalies that appear in Windows event logs after the fact.&lt;/p&gt;
&lt;p&gt;What this layer detects: signature-style indicators of Golden Ticket behaviour on the wire and in the DC event log. What this layer misses: the same encryption-downgrade dependency MDI&apos;s alert 2009 has. The Splunk analytic verbatim acknowledges its own limit: &quot;This detection may be bypassed if attackers use the AES key instead of the NTLM hash&quot; [@splunk-7d9]. Diamond and Sapphire both use the AES-256 key. Both walk through this layer untouched.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Microsoft Sentinel ships rules called &quot;Kerberoasting&quot; that target MITRE T1558.003 (extracting service-account secrets by requesting SPN-bearing service tickets and brute-forcing the resulting RC4-encrypted blobs offline). Those rules target &lt;em&gt;service accounts&lt;/em&gt; with SPNs registered against them. They are not a krbtgt detection asset. The krbtgt account does not have an SPN that any client can request a TGS for; the relevant Sentinel content for krbtgt-class attacks is the T1558.001 Golden-Ticket and Kerberos-anomaly analytic family.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Layer 4: the Sapphire residual&lt;/h3&gt;
&lt;p&gt;What would catch a Sapphire Ticket? The only wire-observable residual of the technique is the conjunction of (a) a TGS-REQ specifying the S4U2self flag, and (b) the same TGT being used to address a User-to-User request to the KDC. No other layer of the stack reads this signal because no other attack has historically produced it as a precondition.&lt;/p&gt;
&lt;p&gt;What ships: nothing canonical. SpecterOps and the BloodHound content team have signalled graph-query work on the U2U TGS issuance pattern in 2026 trend reports [@bloodhound-notes], but no shipped default-enabled analytic. Palo Alto Unit 42&apos;s &quot;Precious Gemstones&quot; survey describes Cortex XDR detection-attempt heuristics but does not publish the rule [@unit42-gemstones]. The gap is engineering, not theoretical: the signal exists, the analytic to read it has simply not been packaged.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; No vendor analytic shipped for the S4U2self plus U2U conjunction as of May 2026. Sapphire is the current frontier and the article&apos;s &quot;what 2026 still cannot do&quot; gap. An attacker who holds the krbtgt key and uses the Sapphire technique walks past every shipping detection layer.&lt;/p&gt;
&lt;/blockquote&gt;

SpecterOps and the BloodHound content team have signalled graph-query work on the U2U TGS issuance pattern; Palo Alto Unit 42&apos;s &quot;Precious Gemstones&quot; survey describes Cortex XDR detection-attempt heuristics [@unit42-gemstones]. Neither has shipped a clean canonical default-enabled analytic. The gap is engineering, not theoretical, and it is the active research front for the 2026 to 2028 cycle.
&lt;h3&gt;Defensive method matrix&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Catches Golden?&lt;/th&gt;
&lt;th&gt;Catches Diamond?&lt;/th&gt;
&lt;th&gt;Catches Sapphire?&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;BloodHound DCSync edge&lt;/td&gt;
&lt;td&gt;preventive only&lt;/td&gt;
&lt;td&gt;preventive only&lt;/td&gt;
&lt;td&gt;preventive only&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDI Suspected-Golden-Ticket (4 alerts)&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDI Suspected DCSync (ID 2006)&lt;/td&gt;
&lt;td&gt;extraction step only&lt;/td&gt;
&lt;td&gt;extraction step only&lt;/td&gt;
&lt;td&gt;extraction step only&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentinel / Splunk T1558.001 RC4 rule&lt;/td&gt;
&lt;td&gt;yes (if RC4)&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentinel Kerberos-anomaly content pack&lt;/td&gt;
&lt;td&gt;partial (lifetime/groups)&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full PAC Signature (post-July 2023)&lt;/td&gt;
&lt;td&gt;n/a (already signed correctly)&lt;/td&gt;
&lt;td&gt;retires non-recomputing variants&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;n/a (cryptographic enforcement, not detection)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S4U2self+U2U conjunction analytic&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;would catch&lt;/td&gt;
&lt;td&gt;4 (not shipped)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Adjacent T1558 family techniques that are not krbtgt detections&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technique&lt;/th&gt;
&lt;th&gt;What it targets&lt;/th&gt;
&lt;th&gt;krbtgt detection?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;T1558.002 Silver Ticket&lt;/td&gt;
&lt;td&gt;service-account long-term keys&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1558.003 Kerberoasting&lt;/td&gt;
&lt;td&gt;SPN-bearing service accounts via offline RC4 crack&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1558.004 AS-REP Roasting&lt;/td&gt;
&lt;td&gt;accounts with pre-auth disabled&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OverPass-the-Hash&lt;/td&gt;
&lt;td&gt;user NTLM hashes via Kerberos PA-DATA&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Detection in 2026 is a four-layer stack, and three of the layers leave gaps the next layer is supposed to close. The fourth gap -- the Sapphire residual -- has no layer above it. When the gaps close enough to confirm a krbtgt compromise, what does recovery actually look like?&lt;/p&gt;
&lt;h2&gt;7. Recovery: What the Two-Reset Procedure Actually Does&lt;/h2&gt;
&lt;p&gt;The Microsoft AD Forest Recovery page states the procedure verbatim:&lt;/p&gt;

&quot;You should perform this operation twice. You must wait 10 hours between password resets. 10 hours are the default Maximum lifetime for user ticket and Maximum lifetime for service ticket policy settings, hence in a case where the Maximum lifetime period changes, the minimum waiting period between resets should be greater than the configured value.&quot; -- and -- &quot;The password history value for the krbtgt account is 2, meaning it includes the two most recent passwords. By resetting the password twice you effectively clear any old passwords from the history, so there&apos;s no way another DC replicates with this DC by using an old password.&quot; [@ms-forest-recovery]
&lt;p&gt;What exactly do those two resets buy, and what do they not buy?&lt;/p&gt;
&lt;h3&gt;The mechanics of two-slot eviction&lt;/h3&gt;
&lt;p&gt;The krbtgt account, like every other AD account, stores both &lt;em&gt;current&lt;/em&gt; and &lt;em&gt;previous&lt;/em&gt; keys. A TGT issued at time $T = 0$ under key $K_0$ continues to validate after a rotation at $T = T_1$ (when $K_1$ becomes current and $K_0$ moves to the previous slot), because the KDC tries both keys during the in-flight validation window. One rotation fills the previous slot with the now-replaced $K_0$; the second rotation, separated by at least &lt;code&gt;MaxTicketAge&lt;/code&gt; so that all $K_0$-signed TGTs have expired naturally, fills the previous slot with $K_1$ and evicts $K_0$ entirely. After the second rotation completes and replicates, no key in the krbtgt account matches the attacker&apos;s extracted $K_0$; forged TGTs from that key fail validation cleanly [@ms-forest-recovery].&lt;/p&gt;

The Kerberos policy value that bounds the lifetime of a Ticket-Granting Ticket from the moment of issuance. The Active Directory default is 10 hours, configured via the Default Domain Policy. The AD Forest Recovery procedure waits at least `MaxTicketAge` between krbtgt resets to ensure no in-flight TGT outlives the period between the two rotations [@ms-forest-recovery].

flowchart LR
    A0[&quot;T=0: K_0 current, K_prior previous&quot;] --&amp;gt; A1[&quot;T=T_1: reset 1 -- K_1 current, K_0 previous&quot;]
    A1 --&amp;gt; A2[&quot;T_1 + 10h: K_1 still current, K_0 still previous&quot;]
    A2 --&amp;gt; A3[&quot;T=T_2 (≥ T_1 + 10h): reset 2 -- K_2 current, K_1 previous&quot;]
    A3 --&amp;gt; A4[&quot;After replication: K_0 evicted from both slots&quot;]
&lt;p&gt;The 10-hour wait between resets is not a Microsoft convenience choice; it is a cryptographic requirement. If the second reset lands before all $K_0$-signed TGTs have expired naturally, some of those tickets will hit a DC whose previous slot now holds $K_1$ rather than $K_0$, and the KDC will reject them. This is what KB5020805&apos;s PAC-signature deployment phases also had to navigate during the November 2022 to October 2023 rollout: signature additions and validation transitions had to bracket the maximum in-flight ticket lifetime [@kb5020805].&lt;/p&gt;
&lt;p&gt;{`
// Model the krbtgt account as a two-slot store; simulate the two-reset procedure.
function simulate(events) {
  const slots = { current: &quot;K_prior&quot;, previous: null };
  let stolen = null;
  for (const ev of events) {
    if (ev.kind === &quot;compromise&quot;) {
      stolen = slots.current;
    } else if (ev.kind === &quot;reset&quot;) {
      slots.previous = slots.current;
      slots.current  = ev.newKey;
    }
    const validates =
      stolen &amp;amp;&amp;amp; (stolen === slots.current || stolen === slots.previous);
    console.log(
      &quot;[t=&quot; + ev.t.toString().padStart(3) + &quot;h]&quot;,
      ev.kind.padEnd(11),
      &quot;current=&quot; + slots.current,
      &quot;prev=&quot; + (slots.previous ?? &quot;-&quot;),
      &quot;attacker_validates=&quot; + validates
    );
  }
}&lt;/p&gt;
&lt;p&gt;simulate([
  { t: 0,  kind: &quot;issue&quot;      },
  { t: 1,  kind: &quot;compromise&quot; },  // attacker stores K_prior as stolen
  { t: 3,  kind: &quot;reset&quot;, newKey: &quot;K_1&quot; },
  { t: 13, kind: &quot;reset&quot;, newKey: &quot;K_2&quot; },  // ≥ MaxTicketAge later
  { t: 14, kind: &quot;issue&quot;      },
]);
`}&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;New-KrbtgtKeys.ps1&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Microsoft&apos;s reference automation for the procedure is &lt;code&gt;New-KrbtgtKeys.ps1&lt;/code&gt;, originally distributed as an MSDN Gallery script and currently hosted in the &lt;code&gt;microsoftarchive&lt;/code&gt; GitHub organisation. The repository banner reads, verbatim: &quot;This repository was archived by the owner on Mar 8, 2024. It is now read-only&quot; [@new-krbtgt-keys]. The script remains the canonical reference for the rotation procedure, including pre-reset and post-reset replication-health checks; it is simply no longer actively maintained. Operators in 2026 commonly fork it locally or wrap the same &lt;code&gt;Set-ADAccountPassword&lt;/code&gt; plus replication-status pattern in their own runbooks.&lt;/p&gt;
&lt;h3&gt;What two-reset does&lt;/h3&gt;
&lt;p&gt;Cryptographically invalidates previously-forged TGTs after the second reset replicates fully across all writeable DCs. This is unambiguous and well-documented; the Microsoft Learn page is the primary [@ms-forest-recovery]. After step 3 (the second reset) has replicated, no TGT signed under the pre-compromise key validates anywhere in the domain.&lt;/p&gt;
&lt;h3&gt;What two-reset does not do&lt;/h3&gt;
&lt;p&gt;Any attacker who held the krbtgt key has typically already installed parallel persistence. SpecterOps&apos;s &quot;Domain of Thrones Part II&quot; by Nico Shyne and Josh Prager, published November 6, 2023, names the rotation list verbatim: &quot;Machine accounts ... User accounts ... Service accounts -- Per domain KRBTGT account ... Trust keys and objects related to trust of all other domains; Group-managed service accounts; Key distribution service root keys&quot; [@specterops-dot2]. The same playbook enumerates the persistence vectors an attacker with krbtgt access typically establishes: AdminSDHolder ACL edits, AD CS template alternates spanning the ESC1 through ESC8 abuse classes (canonically catalogued in Schroeder and Christensen&apos;s &quot;Certified Pre-Owned,&quot; SpecterOps, June 2021) [@certified-pre-owned], SID History entries, machine-account secret retention, KDS root key exfiltration, trust-key compromise, and DSRM password exfiltration. Two-reset rotates the krbtgt key only; the rest of the trust-root set is untouched [@specterops-dot1][@specterops-dot2].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Two-reset rotation cryptographically invalidates previously-forged TGTs. It does NOT rotate any of the other secrets an attacker who held the krbtgt key has typically already installed: AdminSDHolder edits, ADCS templates, SID History, machine-account secrets, KDS root keys, trust keys, DSRM passwords. This is why confirmed krbtgt compromise is a forest-rebuild event, not a key-rotation event.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Two-reset rotation is the cryptographic finish; the operational finish spans the rest of the Domain-of-Thrones surface, and the rotation alone cannot reach it. The single-sentence punchline of the article lands at the end of §11.&lt;/p&gt;

Why does Microsoft&apos;s AD Forest Recovery page treat krbtgt rotation as a recoverable rotation event while Mandiant-style and SpecterOps-style playbooks treat confirmed krbtgt compromise as a forest-rebuild event? Both statements are true at once. Microsoft documents the *cryptographic* recovery, which terminates at the krbtgt key. The IR playbooks document the *operational* recovery, which spans seven additional secret classes whose compromise the krbtgt holder typically also achieved. The cryptographic recovery is necessary and well-bounded; the operational recovery is necessary and not bounded by the same key.
&lt;p&gt;Recovery has two pieces: a fast cryptographic part (two resets, well-documented) and a slow operational part (seven other secret classes, days to weeks). Both are necessary. Neither is sufficient. Even the combined procedure leaves three structural residuals, which the next section names.&lt;/p&gt;
&lt;h2&gt;8. Theoretical Limits and Open Problems&lt;/h2&gt;
&lt;p&gt;Even with the full Domain-of-Thrones rotation surface executed correctly, three structural residuals remain. Each has a current best-partial-result; none has a closed solution.&lt;/p&gt;
&lt;h3&gt;(a) The pre-second-reset TGT-lifetime window&lt;/h3&gt;
&lt;p&gt;Any TGT minted from the compromised krbtgt key between the moment of compromise and the moment the second reset replicates remains valid until naturally expired or until step 3 lands. Mimikatz&apos;s default 10-year lifetime makes this a years-long window if the attacker pre-minted tickets and a careless DC missed the time-anomaly signal. The MDI Suspected-Golden-Ticket family includes a time-anomaly alert (the External ID 2022 sibling) [@mdi-classic] that reads the difference between plausible and implausible ticket lifetimes. The window is bounded above by the AD &lt;code&gt;MaxTicketAge&lt;/code&gt; floor: at minimum, the procedure must take 10 hours of wall-clock per Microsoft&apos;s own guidance [@ms-forest-recovery]. Below that floor the cryptographic invalidation does not finish.&lt;/p&gt;
&lt;p&gt;The mitigation is procedural: between detection and the start of the rotation, the IR team treats every TGT in the domain as suspect. In practice that means rejecting cached tickets at high-value services, forcing a TGT renewal cycle, and watching the time-anomaly alert closely. The mitigation is not perfect; an attacker who minted tickets with realistic 10-hour lifetimes inside the typical AD policy survives this residual entirely.&lt;/p&gt;
&lt;h3&gt;(b) AD CS alternate persistence (the ESC class)&lt;/h3&gt;
&lt;p&gt;An attacker who held the krbtgt key long enough to also touch AD Certificate Services has often installed an ESC-class alternate-identity persistence: a backdoored certificate template allowing Domain Admin certificate issuance (ESC1), a misconfigured &lt;code&gt;EnrolleeSuppliesSubject&lt;/code&gt; template (ESC4), an HTTP-bound CA endpoint vulnerable to &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM relay&lt;/a&gt; (ESC8). The ESC class taxonomy is catalogued in Schroeder and Christensen&apos;s &quot;Certified Pre-Owned&quot; white paper (SpecterOps, June 2021) [@certified-pre-owned]. The compromised template or endpoint survives krbtgt rotation entirely. The CA private key is its own trust root, parallel to (not subordinate to) the krbtgt key. Domain-of-Thrones Part II names ADCS as a separate rotation workstream that must be addressed alongside the krbtgt reset [@specterops-dot2].&lt;/p&gt;
&lt;p&gt;The structural fact: a domain with AD CS deployed has at least two cryptographic trust roots (krbtgt long-term key + CA private key) whose compromises are &lt;em&gt;both&lt;/em&gt; recoverable only through different mechanisms. PKINIT, the Kerberos pre-authentication extension that validates certificate-bearing AS-REQs, accepts identities the CA chain attests to. Compromise of the CA chain yields valid Kerberos authentication as any principal, by a different mechanism than holding the krbtgt key, with the same end result.&lt;/p&gt;
&lt;h3&gt;(c) Cross-domain trust-key compromise&lt;/h3&gt;
&lt;p&gt;Within a multi-domain forest, the krbtgt of each domain is trusted by the others through inter-domain trust keys. A krbtgt compromise in a child domain can become a forest-level event if the trust topology is not hardened: SID Filtering misconfigurations, missing Selective Authentication on outbound trusts, or stale forest-trust artefacts from earlier domain migrations all extend the blast radius beyond the directly-compromised domain. Microsoft&apos;s &quot;Recover from systemic identity compromise&quot; guidance and the AD Forest Recovery procedure index together cover the cross-domain rotation requirements; Domain-of-Thrones Part II&apos;s &quot;Trust keys and objects related to trust of all other domains&quot; entry is the concise operational statement [@specterops-dot2].&lt;/p&gt;
&lt;p&gt;The mitigation is architectural: domain-isolation discipline at the design phase plus Selective Authentication on all inbound trusts. After the fact, every domain whose krbtgt the compromised domain trusted (directly or transitively) becomes part of the rotation surface.&lt;/p&gt;
&lt;h3&gt;(d) The HSM-bound krbtgt aspiration&lt;/h3&gt;
&lt;p&gt;A theoretically clean solution exists in the literature: split the krbtgt key material such that no single party -- including the DC&apos;s own KDC service -- could read the full key in cleartext. The construction would be a hardware-security-module-bound krbtgt key (the HSM exposes only sign and verify operations on a key it never releases), or a threshold-cryptography scheme (the key is reconstructed across $n$ DCs, $t$ of which must cooperate per ticket-signing operation). Either construction would close the underlying primitive by making the krbtgt key unreadable in cleartext to anyone with code execution on a DC.&lt;/p&gt;
&lt;p&gt;Neither construction is supported by any [MS-KILE] revision through 47.0 dated April 27, 2026 [@mskile]. Neither is on any published Microsoft roadmap as of May 2026. The closest analogues that have shipped -- LSAISO/Credential Guard&apos;s VBS trustlet for LSASS secrets on workstations and member servers -- explicitly omit the writeable-DC case by design, because a writeable DC must read the krbtgt key to issue tickets.&lt;/p&gt;
&lt;p&gt;Even after two-reset and Domain of Thrones, three residuals remain: a window of time, an alternate trust root, and a topology problem. None of them are theoretical -- all three are operational realities documented in 2024-2026 incident-response practice. But they raise a different question: how does the krbtgt key compare to the other secrets in an AD trust-root set?&lt;/p&gt;
&lt;h2&gt;9. Where KRBTGT Sits in the AD Trust-Root Set&lt;/h2&gt;
&lt;p&gt;A correction to a framing that appears in many secondary write-ups: the krbtgt long-term key is &lt;em&gt;one&lt;/em&gt; of a small set of &quot;AD trust roots,&quot; not the only one. The framing matters because the rotation playbook in Section 7 lists seven secret classes for a reason: each is a candidate trust root that survives compromise of any other.&lt;/p&gt;

flowchart TD
    K[&quot;krbtgt long-term key&quot;] --&amp;gt;|&quot;every TGT in the domain&quot;| ENVA[&quot;Domain-wide Kerberos auth&quot;]
    C[&quot;AD CS root CA private key&quot;] --&amp;gt;|&quot;PKINIT certificates&quot;| ENVA
    G[&quot;KDS root key&quot;] --&amp;gt;|&quot;gMSA password derivation&quot;| SVC[&quot;Service-account auth&quot;]
    T[&quot;Inter-domain trust keys&quot;] --&amp;gt;|&quot;cross-domain TGT minting&quot;| FOR[&quot;Forest-wide auth&quot;]
    D[&quot;DSRM passwords on writeable DCs&quot;] --&amp;gt;|&quot;local-admin equivalent&quot;| DC[&quot;DC-local auth&quot;]
    DC --&amp;gt; ENVA
    DC --&amp;gt; C
    DC --&amp;gt; G
    DC --&amp;gt; T
    DC --&amp;gt; K
&lt;p&gt;&lt;strong&gt;KRBTGT long-term key.&lt;/strong&gt; Issues TGTs for all principals in the domain. Unique property within the Kerberos trust root: holding it forges TGTs for arbitrary principals, including ones that do not exist in the directory. Rotation: the two-reset, ten-hour-interval procedure on the AD Forest Recovery page [@ms-forest-recovery].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AD CS root CA private key.&lt;/strong&gt; Issues certificates that PKINIT trusts for Kerberos pre-authentication. Compromise yields Kerberos auth as any principal via PKINIT -- a different mechanism with the same end result. Rotation: CA hierarchy rebuild, significantly more expensive than krbtgt rotation. SpecterOps &quot;Certified Pre-Owned&quot; (Schroeder + Christensen, June 2021) is the canonical primary on the ESC-class abuses of this trust root, cross-referenced in Domain of Thrones Part II [@certified-pre-owned][@specterops-dot2].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KDS root key.&lt;/strong&gt; Group Managed Service Account passwords are derived deterministically from a &lt;a href=&quot;https://paragmali.com/blog/dpapi-and-dpapi-ng-the-credential-vault-under-everything/&quot; rel=&quot;noopener&quot;&gt;KDS root key&lt;/a&gt; plus a per-account &lt;code&gt;msDS-ManagedPasswordId&lt;/code&gt;. Compromise of the KDS root key reads every gMSA password in the forest. Different blast radius (service accounts only). Rotation: KDS root key rotation followed by gMSA cycling [@specterops-dot2].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Per-domain inter-domain trust keys.&lt;/strong&gt; Bridge Kerberos trust between domains in a forest or across explicit external trusts. Compromise yields cross-domain TGT minting. Rotation: per-trust password rotation, with SID Filtering and Selective Authentication audits as the standard hardening procedure.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DSRM passwords on writeable DCs.&lt;/strong&gt; Directory Services Restore Mode is a local-admin equivalent at the DC level; compromise yields a local logon to the DC, which then enables many other paths including direct read of the krbtgt key from &lt;code&gt;ntds.dit&lt;/code&gt;. Rotation: per-DC DSRM password rotation [@specterops-dot2].&lt;/p&gt;
&lt;h3&gt;The precise framing&lt;/h3&gt;
&lt;p&gt;Within the Kerberos trust root of a single domain, the krbtgt key occupies a &lt;em&gt;unique&lt;/em&gt; position: it is the issuer of every TGT, and forging a TGT requires exactly this key. At the forest-AD-trust-graph level, the krbtgt key is one of a handful of high-cost-to-rotate trust roots, not the only one. The framing matters because it explains why Domain of Thrones Part II lists seven rotation workstreams: each is a candidate path to the same end result (arbitrary identity in the forest) through a different cryptographic mechanism.&lt;/p&gt;
&lt;p&gt;Five trust roots, one (krbtgt) with a unique forge-arbitrary-TGTs property, all five surfacing in the rotation list. With the trust-root topology mapped, the article&apos;s last technical job is the practical playbook: what does the reader actually do tomorrow morning?&lt;/p&gt;
&lt;h2&gt;10. Practical Guide: The Rotation and Detection Playbook&lt;/h2&gt;
&lt;p&gt;Four lanes. Each lane is a concrete action a reader can execute starting tomorrow morning.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Lane 1:&lt;/strong&gt; Preventive hygiene -- rotate krbtgt twice a year on a calendar schedule and audit who can DCSync. &lt;strong&gt;Lane 2:&lt;/strong&gt; Detection deployment -- ship MDI Suspected-Golden-Ticket alerts plus SIEM T1558.001 content. &lt;strong&gt;Lane 3:&lt;/strong&gt; Confirmed-compromise response -- two-reset rotation followed by the Domain-of-Thrones surface. &lt;strong&gt;Lane 4:&lt;/strong&gt; What does NOT work -- four traps to avoid.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Lane 1: preventive hygiene&lt;/h3&gt;
&lt;p&gt;Rotate the krbtgt password twice a year on a calendar schedule, regardless of any specific incident. Use &lt;code&gt;New-KrbtgtKeys.ps1&lt;/code&gt; (or a fork of it) with pre-reset and post-reset replication-health checks [@new-krbtgt-keys]. Verify Active Directory replication health between the two rotations; if replication is lagging on any DC, the second reset can outpace the first in some replicas and break in-flight tickets.&lt;/p&gt;
&lt;p&gt;Move every Tier-0 account into the Protected Users group. Enable Credential Guard on every workstation and member server. Credential Guard does NOT protect the DC itself by design -- DCs must read the krbtgt key unencrypted -- but it kills the worker-station memory-scrape that initially gets an attacker into a position to pivot to the DC.&lt;/p&gt;
&lt;p&gt;Audit who can invoke DCSync. The BloodHound query &lt;code&gt;MATCH (u)-[:DCSync]-&amp;gt;(d:Domain)&lt;/code&gt; returns every principal whose existing AD permissions can extract the krbtgt key without a DC compromise [@bloodhound-notes][@mitre-t1003006]. Every match should map to a justified administrative role; any unexpected match is a finding.&lt;/p&gt;

LSAISO is a Virtualisation-Based Security trustlet that isolates long-term secrets from a SYSTEM-privileged kernel on workstations and member servers. On writeable DCs the design omits LSAISO because the KDC service must read the krbtgt key unencrypted to issue tickets. This is precisely the design property a DCSync-capable attacker exploits.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Two krbtgt rotations per year as preventive hygiene -- not a response to a specific incident. Use &lt;code&gt;New-KrbtgtKeys.ps1&lt;/code&gt; with replication-health checks before, between, and after. The 10-hour wait between rotations is mandatory; do not shorten it [@ms-forest-recovery].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Lane 2: detection deployment&lt;/h3&gt;
&lt;p&gt;Ship the MDI Suspected-Golden-Ticket alert family plus the DCSync alert (External ID 2006) [@mdi-classic][@mdi-credential]. Confirm the Suspected-Golden-Ticket alerts (2009, 2013, 2022, 2027, 2032, 2040) are active for every domain controller MDI is deployed against. Configure Microsoft Sentinel content-pack rules covering T1558.001 Golden Ticket and Kerberos-anomaly patterns (not the T1558.003 Kerberoasting rules, which target service-account SPNs and are not a krbtgt detection asset). Configure Splunk T1558.001 detection [@splunk-7d9] and tune the encryption-type baseline against legacy systems that legitimately negotiate RC4 (or, better, retire those systems).&lt;/p&gt;
&lt;p&gt;Ingest BloodHound for posture-graph visibility. Configure regular collections (the default is weekly) so the DCSync edge list stays current as ACLs change. Cross-reference the DCSync edge inventory against the actual administrative role assignments quarterly.&lt;/p&gt;
&lt;h3&gt;Lane 3: confirmed-compromise response&lt;/h3&gt;
&lt;p&gt;When MDI or Sentinel surfaces a confirmed krbtgt compromise -- DCSync extraction observed against a writeable DC, or a Suspected-Golden-Ticket alert with concrete supporting evidence -- the response runs in two parallel tracks. The cryptographic track executes the two-reset rotation: reset the krbtgt password (replicate, verify), wait at least 10 hours, reset again (replicate, verify) [@ms-forest-recovery]. The operational track executes the Domain-of-Thrones Part II rotation surface [@specterops-dot2]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AD CS template review covering the ESC1 through ESC8 abuse classes [@certified-pre-owned]; replace or restrict templates with &lt;code&gt;EnrolleeSuppliesSubject&lt;/code&gt;, broad &lt;code&gt;Enroll&lt;/code&gt; permissions, or weak EKU restrictions.&lt;/li&gt;
&lt;li&gt;SID History audit (&lt;code&gt;Get-ADUser -Filter * -Properties SIDHistory&lt;/code&gt;); investigate every account whose SID History contains a Domain Admins or Enterprise Admins SID.&lt;/li&gt;
&lt;li&gt;AdminSDHolder ACL audit; reset Protected Group inherited ACLs and verify the SDProp runs cleanly.&lt;/li&gt;
&lt;li&gt;Machine-account secret rotation, especially for Tier-0 servers.&lt;/li&gt;
&lt;li&gt;KDS root-key rotation followed by gMSA password cycling.&lt;/li&gt;
&lt;li&gt;Trust-key rotation for every inbound and outbound trust.&lt;/li&gt;
&lt;li&gt;DSRM password rotation on every writeable DC.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After both tracks complete, re-baseline detection: the post-incident DC event-log baseline will differ from the pre-incident baseline, and detection thresholds may need re-tuning to suppress the resulting alerts.&lt;/p&gt;

The reference automation runs against the krbtgt SID specifically, not the friendly name, to avoid any ambiguity with a renamed object. Conceptually: `Set-ADAccountPassword -Identity (Get-ADUser -Filter &quot;objectSID -like &apos;*-502&apos;&quot;) -Reset -NewPassword (Convert-To-SecureString (New-RandomPassword) -AsPlainText -Force)`. The Microsoft Learn PowerShell reference for the `Set-ADAccountPassword` cmdlet documents the `-Reset` plus `-NewPassword` parameters used here [@ms-set-adaccountpassword]. The `New-KrbtgtKeys.ps1` script wraps this with replication checks and a confirmation prompt [@new-krbtgt-keys]. Production runbooks always include a pre-check that `Get-ADReplicationFailure` returns no failures before any reset is issued.
&lt;h3&gt;Lane 4: what does NOT work&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Renaming krbtgt.&lt;/strong&gt; The RID 502 binding is what the KDC derives from, not the &lt;code&gt;sAMAccountName&lt;/code&gt;. The KDC service does not care about the friendly name. &lt;strong&gt;Disabling krbtgt.&lt;/strong&gt; The account is already disabled for interactive logon by design [@ms-default-accounts]. Toggling the field is semantically meaningless to the KDC service, which reads the long-term key directly from the directory. &lt;strong&gt;Single rotation.&lt;/strong&gt; Password-history-of-2 means a single rotation only retires the &lt;em&gt;older&lt;/em&gt; of the two keys, leaving the attacker-extracted key (which was current at compromise) still in the previous slot [@ms-forest-recovery]. The procedure must run twice. &lt;strong&gt;Treating MDI Suspected-Golden-Ticket alerts as sufficient.&lt;/strong&gt; Those alerts do not cover Diamond and Sapphire by construction. Sapphire defeats every PAC-content anomaly detection because the PAC is genuine. Confirmed-compromise response must assume the worst even when MDI is silent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Preventive hygiene, detection deployment, confirmed-compromise response, and four traps to avoid. The FAQ that follows addresses what remains.&lt;/p&gt;
&lt;h2&gt;11. FAQ&lt;/h2&gt;

No. It retires Diamond Tickets that do not recompute the Full PAC Signature. It does nothing against tickets minted from a known krbtgt key, including Sapphire Tickets (no PAC modification) and recomputed Diamond Tickets (the attacker holds the key and can compute the new signature in the same step as the older KDC signature) [@kb5020805][@mspac].

No. See §10 Lane 4 trap #1: the RID 502 binding is what the KDC derives from, not the `sAMAccountName` [@ms-default-accounts][@ms-sids].

No. See §10 Lane 4 trap #3: password-history-of-2 keeps the previous key valid after a single rotation, so the procedure must run twice with at least `MaxTicketAge` between resets [@ms-forest-recovery][@new-krbtgt-keys].

No. See §10 Aside on why Credential Guard skips the DC: the KDC service on a writeable DC must read the krbtgt key unencrypted to issue tickets, and DCSync is a remote replication API call (DRSGetNCChanges), not a local LSASS memory scrape [@mitre-t1003006][@ms-credential-guard].

Mechanically, in-flight TGT validation requires the previous-key slot to retain validity for at least `MaxTicketAge` after each rotation. Operationally, the recommended cadence is calendar-driven preventive rotation twice a year, with incident-driven rotation as a separate workstream when confirmed compromise is detected [@ms-forest-recovery].

Indirectly. It forces all krbtgt-encrypted tickets to AES, raising the offline-crack bar against a captured ticket and reducing the surface for the Splunk RC4-Kerberos-anomaly detection family [@splunk-7d9]. It does not affect attacks against a captured krbtgt key; both AES-128 and AES-256 derivations are held in the same account and both validate forged TGTs cleanly.

Yes. Each Read-Only Domain Controller has its own `krbtgt_` account whose key signs TGTs only for principals that the RODC can authenticate [@adsec-483]. The full-domain krbtgt is the only account whose key signs TGTs accepted by every DC in the domain; compromise of an RODC-specific `krbtgt_` is a contained event whose blast radius is bounded by the RODC&apos;s allowed-list policy.

No. The IAKerb and Local KDC features shipping in recent Windows builds affect *where* KDCs run (allowing client-to-client Kerberos without a domain-joined intermediary), not the krbtgt-key trust root inside a domain. The post-RC4 enctype work affects *which* enctypes the krbtgt key derives, not the role of the key. As of [MS-KILE] revision 47.0 dated April 27, 2026, the krbtgt long-term key is still the sole trust anchor for every TGT in the domain [@mskile].
&lt;h3&gt;One sentence to take away&lt;/h3&gt;

Krbtgt rotation invalidates forged TGTs; it does not recover the systemic compromise that produced the forged TGTs in the first place.
&lt;p&gt;That is the precise sentence to keep from ten thousand words. The cryptographic question -- &quot;is the ticket valid?&quot; -- terminates at one key. The operational question -- &quot;is the domain still ours?&quot; -- never does. The 1988 design chose to make ticket validation a property of a single shared secret because that choice made the protocol simple and provably correct. The choice remains correct in 2026. What changed is the meaning of the word &lt;em&gt;compromise&lt;/em&gt;: in 1988 the threat model was a passive eavesdropper on a campus LAN; in 2026 the threat model is a remote API call that streams the secret across a &lt;code&gt;DRSGetNCChanges&lt;/code&gt; exchange. The key did not move. The attacker&apos;s reach did.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;krbtgt-the-account-that-owns-active-directory&quot; keyTerms={[
  { term: &quot;KRBTGT account&quot;, definition: &quot;The RID-502 Active Directory account whose long-term key encrypts every TGT in the domain.&quot; },
  { term: &quot;Ticket-Granting Ticket (TGT)&quot;, definition: &quot;The Kerberos credential issued at logon, encrypted under the krbtgt long-term key, that the client presents to request service tickets.&quot; },
  { term: &quot;Privilege Attribute Certificate (PAC)&quot;, definition: &quot;The Windows-specific structure inside the authorization-data field of every Kerberos ticket, carrying SIDs and signatures.&quot; },
  { term: &quot;DCSync&quot;, definition: &quot;A replication-API primitive (MITRE T1003.006) that streams account secrets including the krbtgt key from a writeable DC to any principal with replication rights.&quot; },
  { term: &quot;Golden Ticket&quot;, definition: &quot;A forged TGT minted from a held krbtgt key (MITRE T1558.001).&quot; },
  { term: &quot;Diamond Ticket&quot;, definition: &quot;A real KDC-issued TGT, decrypted with the held krbtgt key, with the PAC modified and re-signed.&quot; },
  { term: &quot;Sapphire Ticket&quot;, definition: &quot;A forged TGT containing a genuine PAC obtained via the S4U2self plus U2U Kerberos extensions.&quot; },
  { term: &quot;MaxTicketAge&quot;, definition: &quot;The Kerberos policy value bounding the lifetime of a TGT; default 10 hours in Active Directory.&quot; }
]} flashcards={[
  { front: &quot;What did the MS14-068 patch elevate the krbtgt key from and to?&quot;, back: &quot;From &apos;an important secret&apos; to &apos;the load-bearing secret of every authentication decision in the domain.&apos; The patch tied PAC integrity to a real keyed HMAC under the krbtgt key, making the krbtgt key the single secret worth attacking directly from November 2014 onward.&quot; },
  { front: &quot;Why does the Full PAC Signature not retire the primitive?&quot;, back: &quot;Because the Full PAC Signature is itself computed under the krbtgt key. An attacker who holds the key recomputes it in the same step as the older KDC signature, and Sapphire Tickets never modify the PAC at all -- so the KDC&apos;s own genuine Full PAC Signature is on the ticket by construction.&quot; },
  { front: &quot;What does the two-reset procedure do and not do?&quot;, back: &quot;It cryptographically invalidates previously-forged TGTs after the second reset replicates. It does NOT rotate the seven other secret classes an attacker with krbtgt access has typically also touched: AdminSDHolder, AD CS templates, SID History, machine-account secrets, KDS root keys, trust keys, DSRM passwords.&quot; }
]} questions={[
  { q: &quot;What makes krbtgt unique among AD trust roots?&quot;, a: &quot;Within the Kerberos trust root of a single domain, the krbtgt long-term key is the only secret whose disclosure forges TGTs for arbitrary principals, including ones that do not exist in the directory. The CA private key, KDS root key, trust keys, and DSRM passwords are other trust roots with their own blast radii, but only the krbtgt key has the forge-arbitrary-TGT property.&quot; },
  { q: &quot;Why does the two-reset procedure require at least 10 hours between resets?&quot;, a: &quot;Because the AD default MaxTicketAge is 10 hours. If the second reset lands before all TGTs issued under the now-displaced previous key have expired, those in-flight tickets fail validation when they reach a DC whose previous slot no longer holds their signing key. The 10-hour floor is a cryptographic requirement of the two-slot eviction mechanism, not a Microsoft convenience choice.&quot; },
  { q: &quot;What is the Sapphire residual, and why does no vendor analytic ship for it?&quot;, a: &quot;The Sapphire residual is the wire conjunction of an S4U2self-flagged TGS-REQ with a U2U TGS-REQ addressing the same TGT. No vendor ships a default-enabled analytic for this signal as of May 2026 because the engineering work to package it across SIEM platforms has not been done. The signal exists; the analytic is the engineering gap.&quot; },
  { q: &quot;Name three secret classes that survive krbtgt rotation.&quot;, a: &quot;Three of seven: AD CS root CA private key (and any ESC-class template backdoors), KDS root key (used to derive gMSA passwords), inter-domain trust keys (used to bridge Kerberos trust across domains). The remaining four from the Domain-of-Thrones rotation list: AdminSDHolder ACL edits, SID History entries, machine-account secrets, DSRM passwords on writeable DCs.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>active-directory</category><category>kerberos</category><category>krbtgt</category><category>security</category><category>golden-ticket</category><category>diamond-ticket</category><category>sapphire-ticket</category><category>windows-server</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Who is allowed to log in where? The KDC-side answer to credential theft in Active Directory</title><link>https://paragmali.com/blog/who-is-allowed-to-log-in-where-the-kdc-side-answer-to-creden/</link><guid isPermaLink="true">https://paragmali.com/blog/who-is-allowed-to-log-in-where-the-kdc-side-answer-to-creden/</guid><description>A 28-year arc from Paul Ashton&apos;s pass-the-hash demonstration to the 2026 reference deployment of Tiering, Protected Users, and Authentication Policy Silos.</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>
Every NTLM and Kerberos credential-theft chain reduces to one operational question: which accounts will the directory authenticate, from which machines, with what credential materials? Active Directory&apos;s KDC-side answer arrived in a single October 2013 release -- the tier model (policy intent), the Protected Users security group (a non-configurable credential-restriction switch), and Authentication Policy Silos (KDC-enforced TGT-acceptance rules). It has since acquired residual closures (the November 2021 PAC hardening, the May 2022 PKINIT strong-mapping) and a cloud counterpart (Entra Conditional Access, a second independent enforcement plane). This article traces the 28-year arc from Paul Ashton&apos;s April 1997 pass-the-hash post to the 2026 reference deployment, names the four residuals the KDC cannot close by construction, and gives a six-phase playbook for putting the three controls into production this quarter.
&lt;h2&gt;1. Two accounts, one TGT, every domain controller&lt;/h2&gt;
&lt;p&gt;On a Tuesday morning in April 1997, an independent researcher named Paul Ashton posted to the NTBugtraq mailing list. His patched Samba &lt;code&gt;smbclient&lt;/code&gt; did not accept a password. It accepted the hash, and the file server gave it everything [@exploit-db-19197]. The directory had no answer for the next sixteen years.&lt;/p&gt;
&lt;p&gt;Skip forward to today. A domain admin&apos;s laptop is compromised by a phishing payload. The attacker runs Mimikatz against &lt;code&gt;lsass.exe&lt;/code&gt;, recovers a Kerberos ticket-granting ticket for the admin account, and from that TGT every domain controller in the forest is reachable. The detection engineer who pulls the incident report knows exactly what happened. The architect on the other side of the table knows the answer was never going to come from the workstation, from the smartcard, or from the RDP client. It had to come from the directory.&lt;/p&gt;
&lt;p&gt;This is what every credential-theft chain reduces to: a question about which accounts the directory will authenticate, from which machines, with which credential materials, for how long, and to whom they may delegate. Until October 2013, Active Directory had no place to answer that question. It had access-control lists, group memberships, and an AdminSDHolder template that re-stamped privileges every hour [@metcalf-p1906]. None of those mechanisms could refuse to issue a stolen credential, because on the wire a stolen credential is identical to a legitimate one.&lt;/p&gt;
&lt;p&gt;Windows Server 2012 R2 changed that on October 18, 2013 [@save-date-blog]. In a single release, the directory acquired three controls that compose into one operational answer. The &lt;strong&gt;tier model&lt;/strong&gt; names which accounts and machines belong to which control plane: T0 holds the domain controllers and the systems that manage them, T1 holds servers and business data, T2 holds workstations [@ms-eam]. The &lt;strong&gt;Protected Users security group&lt;/strong&gt; (well-known RID 525) imposes a non-configurable credential-restriction set: no &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM&lt;/a&gt;, no DES or RC4 in Kerberos, no delegation, no cached offline-sign-in verifier, and a four-hour non-renewable TGT cap [@ms-pu-current]. &lt;strong&gt;Authentication Policies&lt;/strong&gt; and &lt;strong&gt;Authentication Policy Silos&lt;/strong&gt; are directory objects that tell the Key Distribution Center (KDC) which source machines may authenticate which accounts, at AS-REQ time, before any TGT exists to be stolen [@ms-aps].&lt;/p&gt;
&lt;p&gt;If you arrived here from the earlier posts in this series: this is the operational counterpart to the NTLM relay story, to the Kerberoasting story, and to the Credential Guard story. Silos are how the KDC says no; Credential Guard is how the host says no; Conditional Access is how the cloud says no. The three planes are independent and they compose.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The on-prem AD KDC, keyed on directory state read at issuance time, is the operational answer to credential-theft attack chains. The directory decides which accounts may authenticate, from which machines, with which credential materials, for how long, and to whom they may delegate. The three controls -- tier model, Protected Users, Authentication Policy Silos -- compose into that decision.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rest of this article pays off the question Ashton&apos;s 1997 post raises. Why did the directory have no answer for sixteen years? What changed in October 2013 that the pre-2013 controls could not deliver? What does a working 2026 deployment look like, and what does it still leave open?&lt;/p&gt;
&lt;h2&gt;2. Why the directory had no answer for a decade&lt;/h2&gt;
&lt;p&gt;Ashton&apos;s 1997 demonstration was not subtle. The NT hash is, on the wire, the credential. Windows NT 4&apos;s challenge-response authentication used the LanMan or NT one-way function output as the long-term key; anyone who could read that value from the SAM, from a network capture, or from &lt;code&gt;lsadump&lt;/code&gt; could authenticate as the principal without ever knowing the password [@exploit-db-19197]. Wikipedia&apos;s secondary anchor attributes the first public demonstration to Ashton and dates it to 1997 [@wiki-pth]; the Exploit-DB mirror of the original patch preserves file modification timestamps that narrow the day to Tuesday, April 8, 1997 [@exploit-db-19197].&lt;/p&gt;

A credential-theft technique that uses an account&apos;s NT one-way function output (the NT hash) to authenticate, instead of the plaintext password. Because the Windows NTLM protocol uses the hash itself as the long-term key, an attacker who reads the hash from memory or from disk can authenticate as the account without ever cracking the password.
&lt;p&gt;For more than a decade after Ashton&apos;s post, Microsoft&apos;s institutional position was that this was a protocol legacy, not a vulnerability. The reasoning was internally consistent: the hash IS the long-term key in the protocol&apos;s design; refusing to honour it would break every existing Windows client. The 2008 Pass-the-Hash Toolkit, written by Hernan Ochoa [@wiki-pth], turned the academic demonstration into a single-binary Windows-native tool that read NT hashes from &lt;code&gt;lsass.exe&lt;/code&gt; and injected them into a running logon session [@wiki-pth]. Microsoft&apos;s &lt;em&gt;Privileged access strategy&lt;/em&gt; page now records the 2008 release of the Pass-the-Hash Toolkit as the proximate cause of the escalation in attacker tooling [@ms-paw-strategy].&lt;/p&gt;
&lt;p&gt;Pre-2012, Microsoft&apos;s public posture toward credential-extraction tooling was, in Benjamin Delpy&apos;s own retelling, &quot;this is not a vulnerability.&quot; The Wired profile records the response he received when he disclosed Mimikatz to Microsoft in 2011 [@wired-mimikatz]. That posture is what made the 2012 white paper a turning point: Microsoft committed to treating the attack class as a vulnerability that had to be mitigated by a Microsoft control, not merely contained by operator discipline.&lt;/p&gt;
&lt;p&gt;The escalation that finally broke the institutional posture was Benjamin Delpy&apos;s Mimikatz, released publicly in May 2011 (closed source) on his personal blog [@mimikatz-blog]. Wired&apos;s biographical piece records the date verbatim: &quot;He released it publicly in May 2011, but as a closed source program&quot; [@wired-mimikatz]. The GitHub repository at &lt;code&gt;github.com/gentilkiwi/mimikatz&lt;/code&gt; opened in April 2014; the &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; command on a SYSTEM-level shell printed plaintext passwords, NT hashes, and Kerberos session keys directly from &lt;code&gt;lsass.exe&lt;/code&gt; [@mimikatz-repo]. Within twenty-four months it was the default post-exploitation credential dumper in every public AD attack-and-defence talk [@metcalf-p1738][@wired-mimikatz].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s first institutional acknowledgement arrived in December 2012 as &lt;em&gt;Mitigating Pass-the-Hash, Version 1&lt;/em&gt;. The canonical Microsoft Download Center URL for that version has not survived the company&apos;s reorganisations and now returns HTTP 404; the document is preserved through references inside its successor, the 2014 Version 2 paper, which is still hosted [@pth-v2-pdf]. Version 2 introduces tiered administrative segmentation as a deployment shape and is unambiguous about why the previous decade of mitigations had not worked.&lt;/p&gt;

Pass-the-Hash and similar credential theft attacks are 100% successful when an attacker gains administrative privileges on a computer, because once a computer is compromised, the attacker can read any credential stored on that computer. -- Microsoft, *Mitigating Pass-the-Hash, Version 2* (2014) [@pth-v2-pdf]
&lt;p&gt;That sentence is the institutional pivot. It moves the framing from &quot;protocol feature, defend the host&quot; to &quot;credentials, once stolen, win.&quot; The defence cannot live in the host, because the host is where the attacker has already won. It also cannot live in the ACL, because the ACL evaluates the principal that is authenticating, and the stolen credential authenticates as the legitimate principal. If access-control lists cannot stop a stolen credential, what can?&lt;/p&gt;
&lt;h2&gt;3. Five generations of pre-2013 controls and why each one failed&lt;/h2&gt;
&lt;p&gt;Between 1997 and 2013, operators tried five distinct families of controls. Each targeted a different part of the stack. Each failed in the same structural way.&lt;/p&gt;
&lt;p&gt;The first family was &lt;strong&gt;operational discipline&lt;/strong&gt;: give every administrator two accounts, &lt;code&gt;alice&lt;/code&gt; for daily work and &lt;code&gt;alice.da&lt;/code&gt; for domain-administrative work, and trust her not to use the privileged identity from her daily workstation. NT 4 (RTM July 31, 1996) shipped with this as the operating model [@wiki-nt4]. As a control it is a procedure, not an enforcement: there is no directory mechanism that prevents &lt;code&gt;alice.da&lt;/code&gt; from interactively logging on to a tier-2 workstation. The Microsoft 2014 paper named the failure mode plainly: once &lt;code&gt;alice.da&lt;/code&gt; runs anywhere an attacker also runs, the credential material sits in that machine&apos;s LSASS and is replayable forest-wide [@pth-v2-pdf].&lt;/p&gt;
&lt;p&gt;The second family was &lt;strong&gt;directory-ACL hardening&lt;/strong&gt;. AdminSDHolder is an object under &lt;code&gt;CN=System&lt;/code&gt; in the directory that stores a template security descriptor. A background task called SDProp runs every 60 minutes on the PDC emulator and re-stamps that ACL onto every account with &lt;code&gt;adminCount=1&lt;/code&gt; -- Domain Admins, Enterprise Admins, Schema Admins, and the rest of the protected groups [@metcalf-p1906]. The intent is to prevent ACL drift: a helpdesk operator&apos;s misconfigured permission cannot weaken Domain Admin protections for more than an hour. The mechanism survives in modern AD, but its original &lt;em&gt;threat-model framing&lt;/em&gt; as a pass-the-hash mitigation is dead. ACLs evaluate the principal; a stolen credential authenticates as the legitimate principal. Worse, Sean Metcalf&apos;s &lt;em&gt;Sneaky Active Directory Persistence #15&lt;/em&gt; documents the inverse abuse: AdminSDHolder is not protected by AdminSDHolder, so an attacker who writes a Full-Control ACE into it once gets that ACE propagated across every protected member within sixty minutes [@metcalf-p1906].&lt;/p&gt;

`CN=AdminSDHolder,CN=System,DC=...` stores a template security descriptor. The SDProp (Security Descriptor propagator) task runs every 60 minutes on the PDC emulator and copies that ACL onto every member of the protected groups -- objects with `adminCount=1`. The mechanism prevents ACL drift on privileged accounts but does not stop credential theft.
&lt;p&gt;The third family was &lt;strong&gt;smartcard-required admin accounts&lt;/strong&gt;. Setting the &lt;code&gt;SMARTCARD_REQUIRED&lt;/code&gt; flag (UAC bit &lt;code&gt;0x40000&lt;/code&gt;) on a privileged account causes the KDC to refuse any AS-REQ that is not a PKINIT request -- the user must present a certificate chain rooted in the domain, with the matching private key on a smartcard [@rfc-4556]. The phishing-credential-into-fake-portal vector is closed: the operator does not know a password to type. But the PKINIT exchange produces a derived long-term key that lives on the workstation as a normal NT hash. The 2014 &lt;em&gt;Mitigating Pass-the-Hash&lt;/em&gt; paper is unambiguous in §6: &quot;Smart cards do not protect against the Pass-the-Hash credential theft attack vector. When a smart card is used to log in to a system, the system computes a derived NT hash of the password and stores it on the system&quot; [@pth-v2-pdf]. Mimikatz extracts the derived hash like any other.&lt;/p&gt;

The Public Key Cryptography for Initial Authentication in Kerberos extension, specified in RFC 4556. PKINIT lets a client present a certificate (typically held on a smartcard or a TPM) in its AS-REQ instead of a password-derived pre-authentication blob. The KDC validates the certificate against an account binding and issues a TGT. The resulting long-term key still lives in the host&apos;s LSASS process.
&lt;p&gt;The fourth family was &lt;strong&gt;host-side credential protection&lt;/strong&gt;: LSA Protection (&lt;code&gt;RunAsPPL&lt;/code&gt;), WDigest plaintext disablement, and the &lt;code&gt;TokenLeakDetectDelaySecs&lt;/code&gt; registry setting. LSA Protection runs &lt;code&gt;lsass.exe&lt;/code&gt; as a &lt;a href=&quot;https://paragmali.com/blog/protected-process-light-when-the-administrator-isnt-enough/&quot; rel=&quot;noopener&quot;&gt;Protected Process Light&lt;/a&gt;, refusing handles with &lt;code&gt;PROCESS_VM_READ&lt;/code&gt; to anything not signed at PPL level [@ms-lsa-prot]. WDigest plaintext disablement (via &lt;code&gt;UseLogonCredential=0&lt;/code&gt;, shipped in KB 2871997 in May 2014) stops the WDigest SSP from caching the user&apos;s plaintext password [@kb-2871997]. Both moved the bar; neither closed the attack. PPL is enforced by the kernel; on pre-VBS Windows an attacker with a signed kernel driver clears the protection bit, and Mimikatz ships &lt;code&gt;mimidrv.sys&lt;/code&gt; for exactly this purpose [@mimikatz-repo] (on modern hardware-rooted HVCI/VBS, the VTL1 secure kernel closes the signed-driver bypass, but the discussion then moves to where the §6 Credential Guard primitive lives [@ms-cred-guard]). WDigest disablement removes plaintext from memory but does nothing to the NT hash or to Kerberos session keys, which are the actually-replayable material.&lt;/p&gt;
&lt;p&gt;The fifth family was &lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/rdp-authentication-26-years/&quot; rel=&quot;noopener&quot;&gt;Restricted Admin Mode for RDP&lt;/a&gt;&lt;/strong&gt;, shipped via the October 14, 2014 revision of KB 2871997 [@kb-2871997]. The intent was to interrupt lateral movement: &lt;code&gt;mstsc /restrictedadmin&lt;/code&gt; causes the RDP client to send a CredSSP-wrapped network logon to the target. The target creates a network-logon token instead of an interactive one, and the user&apos;s NT hash or Kerberos session keys never land on the target [@ms-rcg][@kfalde-restricted-admin]. Within months, Benjamin Delpy demonstrated the inverse: because the RDP client authenticates with the user&apos;s &lt;em&gt;existing&lt;/em&gt; credential material, an attacker on the client can pass a stolen NT hash directly into the RDP session with &lt;code&gt;sekurlsa::pth /user:alice.da /domain:CORP /ntlm:&amp;lt;hash&amp;gt; /run:&quot;mstsc /restrictedadmin&quot;&lt;/code&gt; [@mimikatz-repo]. The defence became the lateral move. Microsoft updated KB 2871997 to acknowledge this, and Restricted Admin is off by default client-side on modern Windows [@kb-2871997].&lt;/p&gt;
&lt;p&gt;Restricted Admin Mode for RDP is the cleanest case in the 28-year arc of a control whose deployment created the inverse of its intent. The mode that protects credentials on the RDP target also enables pass-the-hash &lt;em&gt;into&lt;/em&gt; the RDP target from a compromised client. Microsoft&apos;s response -- disable it on the client side -- is the practical confirmation. This is the strongest argument in the historical record for moving the credential-restriction decision out of the host, the protocol, and the channel, and into the KDC.&lt;/p&gt;

flowchart TD
    Op[&quot;Operator discipline (two-account pattern, 1990s)&quot;] --&amp;gt; Op_x[&quot;Procedure, not enforcement: one mistake compromises the forest&quot;]
    ACL[&quot;AdminSDHolder + SDProp (NT 4 / 2000)&quot;] --&amp;gt; ACL_x[&quot;ACLs evaluate the principal, and a stolen credential authenticates as the legitimate principal&quot;]
    SC[&quot;Smartcard-required (Server 2003+)&quot;] --&amp;gt; SC_x[&quot;PKINIT changes only the AS-REQ method, and the derived NT hash still lives in LSASS&quot;]
    HS[&quot;LSA Protection / WDigest off (2013-14)&quot;] --&amp;gt; HS_x[&quot;PPL bypassable by a signed kernel driver, with NT hash and Kerberos keys still in memory&quot;]
    RA[&quot;Restricted Admin Mode for RDP (Oct 2014)&quot;] --&amp;gt; RA_x[&quot;Inverse-of-intent: enables pass-the-hash via RDP from the compromised client&quot;]
    Op_x --&amp;gt; Sink[&quot;All five enforce in a layer that does not see the directory&apos;s authoritative view of who-may-issue-credentials-from-where&quot;]
    ACL_x --&amp;gt; Sink
    SC_x --&amp;gt; Sink
    HS_x --&amp;gt; Sink
    RA_x --&amp;gt; Sink
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A credential, once usable, is on the wire identical to the legitimate one. Every Generation 1-5 control fails because it enforces in a layer that cannot tell the two apart at the point where it tries to decide. The fix is to refuse to issue or to delegate the credential in the first place -- a decision that has to move one layer up, to the KDC, keyed on directory state.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the operator cannot be trusted, the ACL cannot enforce, the smartcard-derived hash still lives in LSASS, the host-side protections can be bypassed by anyone with privilege to deploy them, and the RDP mode meant to interrupt lateral movement enables it -- where does the decision have to move?&lt;/p&gt;
&lt;h2&gt;4. October 18, 2013: the directory acquires a vocabulary&lt;/h2&gt;
&lt;p&gt;The Microsoft Server team&apos;s August 14, 2013 save-the-date blog post fixed the General Availability of Windows Server 2012 R2 for October 18, 2013 [@save-date-blog]. In that single release, three new directory-side primitives appeared: the &lt;strong&gt;Protected Users&lt;/strong&gt; built-in security group with well-known RID 525, the &lt;strong&gt;&lt;code&gt;msDS-AuthNPolicy&lt;/code&gt;&lt;/strong&gt; AD object class for Authentication Policies, and the &lt;strong&gt;&lt;code&gt;msDS-AuthNPolicySilo&lt;/code&gt;&lt;/strong&gt; AD object class for Authentication Policy Silos [@ms-pu-legacy]. The legacy Windows Server 2012 R2 TechNet documentation, preserved on Microsoft Learn, states the introduction verbatim: &quot;This group was introduced in Windows Server 2012 R2&quot; [@ms-pu-legacy]. The architectural decision visible in the wire format: the KDC, not the application, now decides whether a TGT may be issued, what its lifetime will be, and what delegation operations on it will succeed.&lt;/p&gt;

The Kerberos authentication service, specified in RFC 4120. The KDC handles AS-REQ (issuing a Ticket-Granting Ticket from a long-term key) and TGS-REQ (issuing a service ticket from a TGT). On Windows domains, every domain controller runs a KDC; the KDC reads its policy state from the directory at request time, which is the property the Server 2012 R2 controls exploit [@rfc-4120].

A Microsoft authorisation-data overlay carried inside Kerberos TGTs and service tickets, specified in [MS-PAC]. The PAC&apos;s `PAC_LOGON_INFO` buffer contains the user&apos;s SID, primary-group SID, and a `GroupIds` array of well-known group memberships. Protected Users membership is encoded as RID 525 inside that array. There is no separate Protected Users flag bit [@ms-pac].
&lt;p&gt;The detail that matters: there is no dedicated &quot;Protected Users bit&quot; in the PAC. The encoding is the well-known group SID &lt;code&gt;S-1-5-21-&amp;lt;domain&amp;gt;-525&lt;/code&gt; carried in &lt;code&gt;PAC_LOGON_INFO.GroupIds&lt;/code&gt; ([MS-PAC] §2.5) [@ms-pac][@ms-pu-legacy]. The KDC reads that array at AS-REQ and TGS-REQ time the same way it reads it for every other group; what changes is the behaviour the KDC takes when it sees RID 525.&lt;/p&gt;
&lt;p&gt;The down-level half of the shipment arrived seven months later. On May 13, 2014, Microsoft Security Advisory KB 2871997 backported the &lt;em&gt;client-side honoring&lt;/em&gt; of Protected Users and Authentication Policies to Windows 7, Windows 8, Server 2008 R2, and Server 2012 [@kb-2871997]. KB 2871997 is not the introduction of Protected Users. It is the down-level backport that closed the long-tail Silo-bypass class an enterprise would hit if its 2014-era fleet could not honour the new restriction list. Five months later, the October 14, 2014 revision of the same KB shipped Restricted Admin Mode for RDP -- the mode §3 already taught the reader to treat as a cautionary tale.&lt;/p&gt;
&lt;p&gt;The version-mismatch story matters for the operator who finds a 2014 KB cited as the &quot;introduction&quot; of Protected Users in older blog posts. It is not. The introduction is Server 2012 R2 GA on October 18, 2013; the backport is KB 2871997 on May 13, 2014. The legacy Microsoft Learn page records the introduction date plainly [@ms-pu-legacy].&lt;/p&gt;
&lt;p&gt;Microsoft followed the primitive with a deployment shape. The &lt;em&gt;Securing Privileged Access&lt;/em&gt; reference material, originally published on TechNet circa 2014-2015 and preserved on Microsoft Learn at the &lt;code&gt;privileged-access-workstations&lt;/code&gt; root [@ms-paw-root], codified the &lt;strong&gt;clean-source principle&lt;/strong&gt;: a higher-tier secret must never be exposed to a lower-tier host. T0 holds domain controllers, the PKI root, the identity-sync infrastructure, and the DC backup system. T1 holds servers and business data. T2 holds workstations [@ms-eam]. T0 credentials never authenticate to T1 or T2; T1 credentials never authenticate to T2. The Privileged Access Workstation (PAW) is the dedicated source machine for T0 administration. Server 2012 R2 gave operators the &lt;em&gt;primitives&lt;/em&gt;; SPA gave them the &lt;em&gt;shape&lt;/em&gt;.&lt;/p&gt;

flowchart LR
    A[&quot;Apr 8, 1997: Paul Ashton, NTBugtraq -- hash IS the credential&quot;] --&amp;gt; B[&quot;2008: Hernan Ochoa, Pass-the-Hash Toolkit&quot;]
    B --&amp;gt; C[&quot;May 2011: Benjamin Delpy, Mimikatz public release&quot;]
    C --&amp;gt; D[&quot;Dec 2012: Microsoft, Mitigating Pass-the-Hash v1&quot;]
    D --&amp;gt; E[&quot;Oct 18, 2013: Windows Server 2012 R2 GA -- Protected Users, Authentication Policies, Silos&quot;]
    E --&amp;gt; F[&quot;May 13, 2014: KB 2871997 down-level backport&quot;]
    F --&amp;gt; G[&quot;Oct 14, 2014: KB 2871997 adds Restricted Admin RDP&quot;]
    G --&amp;gt; H[&quot;2014-2015: Securing Privileged Access reference material&quot;]
    H --&amp;gt;     I[&quot;Dec 15, 2020: ESAE retired, Enterprise Access Model begins&quot;]
    I --&amp;gt; J[&quot;Nov 9, 2021: KB 5008380 PAC hardening&quot;]
    J --&amp;gt; K[&quot;May 10, 2022: KB 5014754 PKINIT strong mapping&quot;]
    K --&amp;gt; L[&quot;Feb 11, 2025: KB 5014754 Full Enforcement default&quot;]
    L --&amp;gt; M[&quot;Sep 9, 2025: KB 5014754 Compatibility-mode revert removed&quot;]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The KDC, not the application, decides whether a TGT may be issued, what its lifetime is, and what delegation operations on it will succeed. The decision is made by reading directory state -- group SID 525 in &lt;code&gt;PAC_LOGON_INFO.GroupIds&lt;/code&gt; for Protected Users, &lt;code&gt;msDS-AssignedAuthNPolicySilo&lt;/code&gt; and &lt;code&gt;msDS-AssignedAuthNPolicy&lt;/code&gt; for Silo and Policy bindings -- at request time. This is the architectural pivot. The credential-on-the-wire identity property no longer matters, because the credential never gets issued in the first place to be stolen.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Three controls, one ship. But how do they compose, exactly -- which decision does the KDC actually make at AS-REQ time, what does it read from the directory, and what does it refuse?&lt;/p&gt;
&lt;h2&gt;5. How the three controls compose: a mechanism walkthrough&lt;/h2&gt;
&lt;p&gt;If you have time to read only one section of this article, read this one. The Server 2012 R2 controls compose into a precise decision the KDC makes at AS-REQ and TGS-REQ time. The mechanism has four moving parts.&lt;/p&gt;
&lt;h3&gt;5.1 The tier model as policy intent&lt;/h3&gt;
&lt;p&gt;The tier model is policy intent, not enforcement. &lt;strong&gt;Tier 0&lt;/strong&gt; is the control plane: every domain controller, every certificate authority that issues domain-trust certificates, the Microsoft Entra Connect server that synchronises identity to the cloud, and the backup systems that can restore any of those. &lt;strong&gt;Tier 1&lt;/strong&gt; is the management and data plane: servers, business applications, and the database engines that hold the data the organisation actually cares about. &lt;strong&gt;Tier 2&lt;/strong&gt; is the user plane: workstations and the devices users carry [@ms-eam]. The rule that defines the model is the clean-source principle: a higher-tier credential must never authenticate to a lower-tier host, because once it lands in the lower-tier host&apos;s memory it is exfiltrable by anyone with privilege on that host [@ms-paw-strategy]. The tier model says nothing about how the rule is enforced. Protected Users and Authentication Policy Silos are how.&lt;/p&gt;
&lt;h3&gt;5.2 Protected Users: the credential-restriction switch&lt;/h3&gt;
&lt;p&gt;Protected Users is a global security group with well-known RID 525, present in every domain at Domain Functional Level 2012 R2 or later. Membership is encoded as the well-known SID &lt;code&gt;S-1-5-21-&amp;lt;domain&amp;gt;-525&lt;/code&gt; carried in the &lt;code&gt;GroupIds&lt;/code&gt; array of the user&apos;s &lt;code&gt;PAC_LOGON_INFO&lt;/code&gt; ([MS-PAC] §2.5) [@ms-pac][@ms-pu-current]. When the KDC reads RID 525 in that array, it applies a non-configurable restriction set documented on Microsoft Learn [@ms-pu-current]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No NTLM authentication.&lt;/strong&gt; The DC refuses any NTLM authentication attempt for a Protected Users member -- the NTLM SSP and NetLogon path on the DC enforce the rejection, and the Kerberos KDC enforces the corresponding refusal for AS-REQ flows that fall back to NTLM-style pre-authentication. NTLM relay against the account is structurally impossible because there is no NTLM session to relay.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No NTLM hash caching on the host.&lt;/strong&gt; Even if the user has logged on interactively, the LSA never holds the account&apos;s NT one-way function output. Mimikatz &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; prints &lt;code&gt;(null)&lt;/code&gt; for the NTLM tab.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No DES or RC4 in Kerberos pre-authentication.&lt;/strong&gt; AES-128 or AES-256 only. Kerberoasting against the account becomes inapplicable, because the public roasting tooling requires RC4-HMAC ticket material that the KDC refuses to issue.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No constrained or unconstrained delegation, in either direction.&lt;/strong&gt; The account cannot be the source of a constrained-delegation chain, and S4U2Self / S4U2Proxy against the account as a target is refused at TGS-REQ time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No cached offline-sign-in verifier.&lt;/strong&gt; The Windows Hello for Business PIN-based offline-logon path is unavailable for Protected Users members; this is the operational price of removing the cached verifier from disk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TGT lifetime capped at 240 minutes, non-renewable.&lt;/strong&gt; Microsoft Learn states the figure verbatim: &quot;For Protected Users members, the group automatically sets these lifetime limits to 240 minutes&quot; [@ms-pu-current]. The cap overrides the domain&apos;s &quot;Maximum lifetime for user ticket&quot; and &quot;Maximum lifetime for user ticket renewal&quot; policies.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The built-in domain Administrator (RID 500) is always exempt from Authentication Policy enforcement even when assigned to a Silo, which makes it a candidate break-glass identity [@ms-pu-current]. That exemption does not extend to the Protected Users restriction set itself: adding RID 500 to Protected Users on a domain whose Administrator account lacks AES keys will lock the account out. Service accounts cannot be enrolled in Protected Users without breaking workflows -- see §6&apos;s canonical Microsoft Learn PullQuote on this point.&lt;/p&gt;
&lt;h3&gt;5.3 Authentication Policies and Silos: the KDC-side policy objects&lt;/h3&gt;
&lt;p&gt;Two AD object classes, layered. The containment direction is the most common practitioner confusion, so be precise about it: &lt;strong&gt;the Silo references the Policy, not the other way&lt;/strong&gt;.&lt;/p&gt;

The container object. A Silo enumerates the user, computer, and service accounts that share a set of restrictions and references one or more `msDS-AuthNPolicy` objects whose rules apply to its members. The Silo carries an `msDS-AuthNPolicySiloEnforced` Boolean that switches between audit-only and enforced modes. Accounts bind to it via `msDS-AssignedAuthNPolicySilo`, with `msDS-AuthNPolicySiloMembers` as the back-link [@ms-aps].

The rules object. A Policy carries the non-renewable TGT lifetime cap, the allowed-from SDDLs on source-machine identity (`UserAllowedToAuthenticateFrom`, `ServiceAllowedToAuthenticateFrom` -- computer accounts have no `-From` variant, only `-To`), the corresponding allowed-to SDDLs for delegation targets (`UserAllowedToAuthenticateTo`, `ServiceAllowedToAuthenticateTo`, `ComputerAllowedToAuthenticateTo`), claim-based authentication access-control conditions, and the option to require Kerberos armoring per RFC 6113 [@ms-aps][@rfc-6113].
&lt;p&gt;The same Policy can be referenced by multiple Silos. Accounts can be bound to a Policy directly via &lt;code&gt;msDS-AssignedAuthNPolicy&lt;/code&gt; without being placed in a Silo at all, though the more common pattern is Silo membership for the broader containment and Policy reuse for the rule definitions.&lt;/p&gt;
&lt;p&gt;The containment direction is the single most-common practitioner confusion. The Silo names the Policy that applies to its members. The same Policy can apply to several Silos. The directory links are role-specific: the Silo carries &lt;code&gt;msDS-UserAuthNPolicy&lt;/code&gt;, &lt;code&gt;msDS-ComputerAuthNPolicy&lt;/code&gt;, and &lt;code&gt;msDS-ServiceAuthNPolicy&lt;/code&gt;, each pointing outward to a Policy object [@ms-aps]. Older blog posts that describe &quot;the Policy attached to the Silo&quot; are using imprecise prose; the link in the schema is Silo to Policy, not the other way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Policy and Silo objects replicate via standard AD multi-master directory replication -- the &lt;a href=&quot;https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/&quot; rel=&quot;noopener&quot;&gt;DRS Remote Protocol&lt;/a&gt;, MS-DRSR / &lt;code&gt;drsuapi&lt;/code&gt; [@ms-drsr]. They do NOT replicate via FRS or DFSR. FRS and DFSR replicate SYSVOL files (Group Policy content, scripts), not directory objects. Practitioners who chase &quot;my Policy assignment is not replicating&quot; through DFSR diagnostics are looking in the wrong primitive; the right one is &lt;code&gt;repadmin /showrepl&lt;/code&gt; against the DRS partition.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;5.4 The KDC&apos;s decision points&lt;/h3&gt;
&lt;p&gt;The KDC consults the directory at three precise moments, documented in [MS-KILE] §3.3.5 [@ms-kile]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AS-REQ.&lt;/strong&gt; The KDC reads the requester&apos;s &lt;code&gt;msDS-AssignedAuthNPolicySilo&lt;/code&gt; and any &lt;code&gt;msDS-AssignedAuthNPolicy&lt;/code&gt;. If the Policy specifies a &lt;code&gt;UserAllowedToAuthenticateFrom&lt;/code&gt; SDDL, the KDC evaluates the source-machine identity (as presented in the pre-authentication exchange) against the SDDL. On denial, the KDC returns &lt;code&gt;KDC_ERR_POLICY&lt;/code&gt; and no TGT is issued. The KDC also checks &lt;code&gt;PAC_LOGON_INFO.GroupIds&lt;/code&gt; for RID 525; if present, it applies the Protected Users restriction set to the TGT it is about to issue (AES-only, 240-minute cap, delegation forbidden).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TGS-REQ for S4U2Self.&lt;/strong&gt; The KDC reads the target account&apos;s group memberships and Silo bindings. If the target is a Protected Users member, S4U2Self is refused. If the target&apos;s Silo Policy specifies an allowed-to SDDL, the requesting service identity is evaluated against it [@ms-sfu].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TGS-REQ for S4U2Proxy.&lt;/strong&gt; The KDC evaluates the requesting service&apos;s &lt;code&gt;msDS-AllowedToDelegateTo&lt;/code&gt; and the target&apos;s &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt;, then layers the Silo Policy&apos;s claim requirements on top. Protected Users membership on either side terminates the request [@ms-sfu].&lt;/li&gt;
&lt;/ul&gt;

sequenceDiagram
    participant PAW as PAW (source machine)
    participant KDC as KDC on DC
    participant DS as Directory (LDAP DSA)
    PAW-&amp;gt;&amp;gt;KDC: AS-REQ for alice.da, pre-auth signed
    KDC-&amp;gt;&amp;gt;DS: Read alice.da object (PAC_LOGON_INFO, msDS-AssignedAuthNPolicySilo)
    DS--&amp;gt;&amp;gt;KDC: GroupIds includes RID 525, Silo = &quot;T0 Admins&quot;
    KDC-&amp;gt;&amp;gt;DS: Read referenced Policy (msDS-AuthNPolicy)
    DS--&amp;gt;&amp;gt;KDC: UserAllowedToAuthenticateFrom SDDL pinned to T0 PAWs
    KDC-&amp;gt;&amp;gt;KDC: Evaluate source machine identity against SDDL
    alt Source is in the allowed-from set
        KDC-&amp;gt;&amp;gt;KDC: Apply Protected Users restriction set (AES-only, no NTLM, no delegation)
        KDC-&amp;gt;&amp;gt;KDC: Cap TGT lifetime at 240 minutes non-renewable
        KDC--&amp;gt;&amp;gt;PAW: TGT issued with restriction PAC
    else Source not in the allowed-from set
        KDC--&amp;gt;&amp;gt;PAW: KDC_ERR_POLICY, no TGT issued
    end

flowchart LR
    A[&quot;User account alice.da (msDS-AssignedAuthNPolicySilo)&quot;] --&amp;gt; S[&quot;Silo: T0 Admins (msDS-AuthNPolicySilo)&quot;]
    C[&quot;Computer account paw01 (msDS-AssignedAuthNPolicySilo)&quot;] --&amp;gt; S
    SV[&quot;Service account svc-bkp (msDS-AssignedAuthNPolicySilo)&quot;] --&amp;gt; S
    S -- &quot;references&quot; --&amp;gt; P[&quot;Policy: T0 Source Restriction (msDS-AuthNPolicy)&quot;]
    P --&amp;gt; Rule1[&quot;UserAllowedToAuthenticateFrom SDDL&quot;]
    P --&amp;gt; Rule2[&quot;TGT lifetime cap&quot;]
    P --&amp;gt; Rule3[&quot;Claim transformations&quot;]
    P --&amp;gt; Rule4[&quot;FAST armoring requirement&quot;]
    S -. &quot;alt direct binding&quot; .-&amp;gt; A2[&quot;Account can also bind via msDS-AssignedAuthNPolicy&quot;]
&lt;p&gt;The RunnableCode block below simulates the decision tree as a small JS function. It is pedagogical, not a real KDC, but the logic mirrors what [MS-KILE] specifies. Change the inputs -- move the source machine outside the allowed-from set, flip the Protected Users flag -- and the decision changes.&lt;/p&gt;
&lt;p&gt;{`
function kdcDecideAsReq(account, sourceMachine) {
  // account: { name, inProtectedUsers, siloPolicy: { allowedFrom: [], tgtMinutes, requireFast } }
  // sourceMachine: { name }&lt;/p&gt;
&lt;p&gt;  if (account.siloPolicy &amp;amp;&amp;amp; account.siloPolicy.allowedFrom &amp;amp;&amp;amp;
      !account.siloPolicy.allowedFrom.includes(sourceMachine.name)) {
    return { issued: false, error: &quot;KDC_ERR_POLICY&quot;, reason: &quot;source not in allowed-from set&quot; };
  }&lt;/p&gt;
&lt;p&gt;  const restrictions = [];
  let tgtMinutes = account.siloPolicy ? account.siloPolicy.tgtMinutes : 600;
  let renewable = true;&lt;/p&gt;
&lt;p&gt;  if (account.inProtectedUsers) {
    restrictions.push(&quot;no-NTLM&quot;, &quot;AES-only&quot;, &quot;no-delegation&quot;, &quot;no-cached-verifier&quot;);
    tgtMinutes = Math.min(tgtMinutes, 240);
    renewable = false;
  }&lt;/p&gt;
&lt;p&gt;  return {
    issued: true,
    tgtMinutes,
    renewable,
    restrictions,
    sourceMachine: sourceMachine.name
  };
}&lt;/p&gt;
&lt;p&gt;const alice = {
  name: &quot;alice.da&quot;,
  inProtectedUsers: true,
  siloPolicy: { allowedFrom: [&quot;paw-t0-01&quot;, &quot;paw-t0-02&quot;], tgtMinutes: 480, requireFast: true }
};&lt;/p&gt;
&lt;p&gt;console.log(&quot;From PAW:&quot;, kdcDecideAsReq(alice, { name: &quot;paw-t0-01&quot; }));
console.log(&quot;From workstation:&quot;, kdcDecideAsReq(alice, { name: &quot;wks-finance-77&quot; }));
`}&lt;/p&gt;
&lt;p&gt;The KDC now has a vocabulary it did not have in 1997. Well-known group SID 525 as a credential-restriction switch. &lt;code&gt;msDS-AuthNPolicySilo&lt;/code&gt; and &lt;code&gt;msDS-AuthNPolicy&lt;/code&gt; as policy objects. &lt;code&gt;drsuapi&lt;/code&gt; as the replication primitive that carries policy changes to every DC. The decision is keyed on directory state, made at request time, before any TGT exists to be stolen. With the mechanism in hand, what does a current 2026 reference deployment look like?&lt;/p&gt;
&lt;h2&gt;6. The 2026 reference deployment&lt;/h2&gt;
&lt;p&gt;Microsoft has had thirteen years to settle the deployment shape. As of May 2026, a well-built environment looks like the layered stack below, in which Silos and Protected Users carry the on-prem enforcement and several complementary primitives close residuals the KDC plane cannot address by construction.&lt;/p&gt;

The control plane of an Active Directory environment. T0 contains the domain controllers and every system whose compromise grants forest-wide control: the AD CS certificate authorities, the Microsoft Entra Connect server, the privileged-access workstations used to manage them, and the backup systems that can restore any of those. The SpecterOps Tier Zero Table is the community-maintained canonical asset list and is the practical starting point for any T0 inventory [@tzt-pages][@tzt-github].
&lt;p&gt;The reference deployment composes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tier model present as policy intent&lt;/strong&gt;, with Authentication Policy Silos as the enforcement primitive that makes the tier boundary KDC-visible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;All human T0 administrators in Protected Users&lt;/strong&gt;, in a &quot;T0 Admins&quot; Silo whose Policy&apos;s &lt;code&gt;UserAllowedToAuthenticateFrom&lt;/code&gt; SDDL pins authentication to a defined set of T0 PAWs. The KDC will return &lt;code&gt;KDC_ERR_POLICY&lt;/code&gt; for any AS-REQ from outside that set [@ms-aps][@ms-kile].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;T0 service accounts in a &quot;T0 Services&quot; Silo&lt;/strong&gt; with a more permissive Policy that still pins source machines. Service accounts cannot be in Protected Users; the Silo plane is the only KDC-side enforcement available to them [@ms-pu-current].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain-wide migration off RC4-HMAC&lt;/strong&gt; for AS-REP, with &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; audited per account. Protected Users enforces AES-only for free for human members; service accounts need explicit per-account configuration [@ms-config-pa].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; default-on&lt;/strong&gt; for non-DC Windows 11 22H2+ and Windows Server 2025+ devices that meet the hardware requirements [@ms-cred-guard]. &lt;strong&gt;Windows LAPS&lt;/strong&gt; managing local-administrator password uniqueness on every workstation [@ms-laps].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Entra PIM for Entra ID privileged roles&lt;/strong&gt; [@ms-pim], with &lt;strong&gt;Conditional Access&lt;/strong&gt; keyed on the synced T0 Admins group requiring phishing-resistant MFA and a compliant device. The CA does not see the Silo; it sees the synced group. The two planes are independent (see §8).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microsoft Defender for Identity&lt;/strong&gt; assessments running, including &quot;Identify privileged accounts that are not protected by Protected Users group&quot; and adjacent recommendations [@ms-mdi]. This is the detection plane that tells the operator the reference deployment is the deployed posture.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the service accounts that cannot be enrolled in Protected Users, the explicit AES enforcement story is direct: set &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; to &lt;code&gt;0x18&lt;/code&gt; (AES128 &lt;code&gt;0x08&lt;/code&gt; + AES256 &lt;code&gt;0x10&lt;/code&gt;). To additionally signal Compound-Identity-Supported, use &lt;code&gt;0x20018&lt;/code&gt; (&lt;code&gt;0x18 | 0x20000&lt;/code&gt;) -- Compound-Identity-Supported is the &lt;code&gt;G&lt;/code&gt; bit at position 17 of the [MS-KILE] §2.2.7 &lt;em&gt;Supported Encryption Types Bit Flags&lt;/em&gt; diagram, value &lt;code&gt;0x20000&lt;/code&gt;, not &lt;code&gt;0x40&lt;/code&gt;. The full bit layout per [MS-KILE] §2.2.7 is: DES-CBC-CRC &lt;code&gt;0x01&lt;/code&gt;, DES-CBC-MD5 &lt;code&gt;0x02&lt;/code&gt;, RC4-HMAC &lt;code&gt;0x04&lt;/code&gt;, AES128-CTS-HMAC-SHA1-96 &lt;code&gt;0x08&lt;/code&gt;, AES256-CTS-HMAC-SHA1-96 &lt;code&gt;0x10&lt;/code&gt;, FAST-Supported &lt;code&gt;0x10000&lt;/code&gt;, Compound-Identity-Supported &lt;code&gt;0x20000&lt;/code&gt;, Claims-Supported &lt;code&gt;0x40000&lt;/code&gt;, Resource-SID-Compression-Disabled &lt;code&gt;0x80000&lt;/code&gt;; &lt;code&gt;0x40&lt;/code&gt; is bit 6 (AES128-CTS-HMAC-SHA256-128, an RFC 8009 enctype [@rfc-8009] older KDCs do not fully support and which is &lt;em&gt;not&lt;/em&gt; Compound-Identity-Supported). The value &lt;code&gt;0x18&lt;/code&gt; explicitly excludes RC4 (&lt;code&gt;0x04&lt;/code&gt;) and the two DES flavours (&lt;code&gt;0x01&lt;/code&gt;, &lt;code&gt;0x02&lt;/code&gt;). Note that &lt;code&gt;0x1C&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; AES-only -- it is &lt;code&gt;0x10 | 0x08 | 0x04&lt;/code&gt;, which re-introduces RC4 on the very account you are trying to harden. &lt;a href=&quot;https://paragmali.com/blog/dpapi-and-dpapi-ng-the-credential-vault-under-everything/&quot; rel=&quot;noopener&quot;&gt;Group Managed Service Accounts&lt;/a&gt; (gMSA) are the preferred new-service-account primitive: the Microsoft Key Distribution Service computes a long, automatically-rotated password keyed on a domain-wide root key, and the Microsoft Learn gMSA overview describes the mechanism in detail -- the resulting AES pre-auth tickets are not roastable in practical timeframes [@ms-gmsa-overview]. Microsoft&apos;s &lt;em&gt;How to Configure Protected Accounts&lt;/em&gt; page lays out the per-account migration steps for non-gMSA legacy services [@ms-config-pa].&lt;/p&gt;

Never add accounts for services and computers to the Protected Users group. For those accounts, membership doesn&apos;t provide local protections because the password and certificate is always available on the host. -- Microsoft Learn, *Protected Users Security Group* [@ms-pu-current]
&lt;p&gt;That quote is the operational reason the RBCD residual remains the punchline of §8. Before then, two further pieces of the reference deployment need to be named, because both have been mis-described in widely shared blog posts.&lt;/p&gt;
&lt;p&gt;The first is the &lt;strong&gt;November 2021 PAC hardening&lt;/strong&gt; in KB 5008380, which addressed CVE-2021-42287 and CVE-2021-42278 (&quot;noPAC&quot;). The fix added two new PAC buffer types to the Kerberos TGT: &lt;code&gt;PAC_REQUESTOR&lt;/code&gt; (buffer type 18), which encodes the SID of the principal that requested the ticket, and &lt;code&gt;PAC_ATTRIBUTES_INFO&lt;/code&gt; (buffer type 17), which carries PAC-generation attributes [@kb-5008380][@ms-pac]. The KDC at TGS-REQ time now verifies that the requestor SID in the PAC matches the principal currently presenting the TGT. Initial deployment was November 9, 2021; the Enforcement phase landed October 11, 2022 [@kb-5008380].&lt;/p&gt;
&lt;p&gt;The second is the &lt;strong&gt;May 2022 PKINIT certificate-to-account strong-mapping&lt;/strong&gt; fix in KB 5014754 [@kb-5014754]. Pre-fix, the KDC mapped a PKINIT certificate to an account by sAMAccountName or UPN -- the same comparison that Schroeder and Christensen&apos;s &lt;em&gt;Certified Pre-Owned&lt;/em&gt; whitepaper showed could be spoofed via UPN conflicts or via the trailing dollar-sign convention on machine accounts [@cert-preowned-blog][@cert-preowned-pdf]. The fix added the &lt;code&gt;SecurityIdentifier&lt;/code&gt; X.509 extension OID &lt;code&gt;1.3.6.1.4.1.311.25.2&lt;/code&gt; to certificates issued by AD CS and requires the KDC to match the SID in the certificate against the SID of the account being authenticated. The Full Enforcement default landed February 11, 2025; the Compatibility-mode revert option was removed on September 9, 2025 [@kb-5014754].&lt;/p&gt;

The November 2021 PAC hardening is not the encoding of Protected Users membership. The Protected Users marker is RID 525 in `PAC_LOGON_INFO.GroupIds`, present in the PAC since Windows Server 2012 R2 GA in October 2013. The November 2021 buffers (`PAC_REQUESTOR`, `PAC_ATTRIBUTES_INFO`) are a separate, later KDC anti-spoofing primitive that closes the sAMAccountName-spoofing chain in CVE-2021-42278 plus CVE-2021-42287 [@kb-5008380][@ms-pac]. Conflating them produces wrong threat-model claims: it treats a 2021 anti-spoofing fix as if it were the 2013 credential-restriction marker, and leaves the operator unable to reason about either correctly.
&lt;p&gt;&lt;strong&gt;Reference 2026 deployment: what runs where.&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Account class&lt;/th&gt;
&lt;th&gt;Protected Users?&lt;/th&gt;
&lt;th&gt;Silo membership&lt;/th&gt;
&lt;th&gt;Allowed-from SDDL anchor&lt;/th&gt;
&lt;th&gt;TGT cap&lt;/th&gt;
&lt;th&gt;Host-side&lt;/th&gt;
&lt;th&gt;Cloud-side&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Human T0 admin&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;T0 Admins&lt;/td&gt;
&lt;td&gt;T0 PAWs only&lt;/td&gt;
&lt;td&gt;240 min, non-renewable&lt;/td&gt;
&lt;td&gt;Credential Guard on the PAW; LAPS irrelevant (PAW is unique)&lt;/td&gt;
&lt;td&gt;Entra PIM + CA on synced group, phishing-resistant MFA, compliant device&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T0 service account (gMSA)&lt;/td&gt;
&lt;td&gt;No (breaks workflow)&lt;/td&gt;
&lt;td&gt;T0 Services&lt;/td&gt;
&lt;td&gt;T0 server set&lt;/td&gt;
&lt;td&gt;Default; per-Policy cap&lt;/td&gt;
&lt;td&gt;Credential Guard on every host the account runs on&lt;/td&gt;
&lt;td&gt;n/a (on-prem only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T1 admin&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;T1 Admins&lt;/td&gt;
&lt;td&gt;T1 jump servers&lt;/td&gt;
&lt;td&gt;Default; per-Policy cap&lt;/td&gt;
&lt;td&gt;Credential Guard everywhere&lt;/td&gt;
&lt;td&gt;CA on synced T1 group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T2 user&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;Credential Guard default-on, LAPS for local admin&lt;/td&gt;
&lt;td&gt;CA general policy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;If this is the reference deployment, what about the alternative architectures customers actually have in production -- ESAE forests, MIM PAM bastion forests, the Enterprise Access Model?&lt;/p&gt;
&lt;h2&gt;7. Tiered Administration vs. bastion forest vs. Enterprise Access Model&lt;/h2&gt;
&lt;p&gt;Three operational doctrines coexist in 2026 production environments, with a fourth meta-architecture sitting above them. None are interchangeable; choosing the wrong one means over-building, under-building, or building the right thing in the wrong place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Method A: Tier model + Authentication Policy Silos + Protected Users.&lt;/strong&gt; The current Microsoft recommendation for the on-prem enforcement layer in connected and hybrid environments. The whole of §5 and §6 is the description. Cited references: [@ms-pu-current][@ms-aps][@ms-eam].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Method B: MIM Privileged Access Management with a bastion forest.&lt;/strong&gt; Microsoft Identity Manager PAM with the Server 2016 bastion-forest functional level gives just-in-time activation of privileged group membership in a separate, hardened &quot;bastion&quot; forest with a one-way trust &lt;em&gt;from&lt;/em&gt; production &lt;em&gt;to&lt;/em&gt; bastion. Microsoft Learn&apos;s &lt;em&gt;Raise the bastion forest functional level&lt;/em&gt; page is explicit on the feature pivot: &quot;With Windows Server 2016, PAM features of time-limited group memberships and shadow principal groups are built into Windows Server Active Directory&quot; [@ms-pam-bastion-ffl]. A user requests time-bound activation, MIM validates it, the user is briefly added to a bastion-forest privileged group (a shadow principal at WS 2016 FFL), and the resulting TGT carries the production SIDs via PAC SID History. When the activation expires, the SID History entry disappears from newly issued tickets. The Microsoft Learn page is explicit about scope:&lt;/p&gt;

The PAM approach provided by MIM PAM is not recommended for new deployments in Internet-connected environments. MIM PAM is intended to be used in a custom architecture for isolated AD environments where Internet access is not available, where this configuration is required by regulation, or in high impact isolated environments like offline research laboratories and disconnected operational technology or supervisory control and data acquisition environments. -- Microsoft Learn, *MIM PAM* [@ms-mim-pam]
&lt;p&gt;&lt;strong&gt;Method C: Enhanced Security Admin Environment (ESAE) / Red Forest.&lt;/strong&gt; A separate hardened forest used exclusively for administrative identities, with a one-way trust from production to the admin forest. Production-forest administration is performed by accounts that live exclusively in the admin forest. Microsoft retired ESAE as a mainstream recommendation on December 15, 2020 [@ms-esae-retire].&lt;/p&gt;

A dedicated Active Directory forest containing all administrative identities, with a one-way trust from the production forest to the admin forest. Retired as a mainstream Microsoft recommendation on December 15, 2020 [@ms-esae-retire]; preserved for air-gapped, OT, ICS, and SCADA scenarios where cloud-side privileged-access controls are unavailable. Microsoft&apos;s explicit guidance for existing ESAE deployments is &quot;no urgency to retire&quot; if the deployment is operating as designed.
&lt;p&gt;&lt;strong&gt;Method D: Enterprise Access Model (EAM) / Rapid Modernization Plan (RaMP).&lt;/strong&gt; Microsoft&apos;s current meta-architecture, announced concurrently with the ESAE retirement on December 15, 2020 [@ms-esae-retire][@ms-eam][@ms-ramp]. EAM widens the segmentation from forest boundaries to &lt;em&gt;access levels&lt;/em&gt;: a privileged-access plane (the equivalent of T0, now explicitly including Entra ID admin roles), a management plane (formerly T1), a data/workload plane (where applications run), and a user/app plane (T2). EAM does not deprecate the directory-level controls -- it encloses them inside a larger model that adds the cloud control plane as a first-class object.&lt;/p&gt;

Microsoft&apos;s December 15, 2020 meta-architecture for privileged-access. Replaces forest-level isolation with access-level segmentation across four planes: privileged-access, management, data/workload, and user/app. EAM is the framework; Method A (Tier model + Silos + Protected Users) is the on-prem enforcement layer inside the privileged-access plane; Entra PIM and Conditional Access are the cloud-side enforcement [@ms-eam][@ms-ramp].
&lt;p&gt;&lt;strong&gt;Four operational doctrines, side by side.&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;A: Tier + Silos + Protected Users&lt;/th&gt;
&lt;th&gt;B: MIM PAM bastion&lt;/th&gt;
&lt;th&gt;C: ESAE / Red Forest&lt;/th&gt;
&lt;th&gt;D: EAM + RaMP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Enforcement plane&lt;/td&gt;
&lt;td&gt;KDC (AS-REQ, TGS-REQ, S4U)&lt;/td&gt;
&lt;td&gt;Bastion KDC + MIM workflow&lt;/td&gt;
&lt;td&gt;Admin-forest KDC + one-way trust&lt;/td&gt;
&lt;td&gt;Meta: composes A + cloud + host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Primary restriction&lt;/td&gt;
&lt;td&gt;Where a TGT may be issued and to whom delegated&lt;/td&gt;
&lt;td&gt;Whether and for how long a privileged group is populated&lt;/td&gt;
&lt;td&gt;Which forest privileged identities live in&lt;/td&gt;
&lt;td&gt;Which planes are enforced and by what&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AD schema footprint&lt;/td&gt;
&lt;td&gt;4 attributes / 2 classes + RID 525&lt;/td&gt;
&lt;td&gt;Server 2016 PAM FFL + Shadow Principal extensions&lt;/td&gt;
&lt;td&gt;None new; uses standard trust + SID filtering&lt;/td&gt;
&lt;td&gt;n/a (model)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud / hybrid coverage&lt;/td&gt;
&lt;td&gt;On-prem only&lt;/td&gt;
&lt;td&gt;On-prem only (explicitly NOT for connected)&lt;/td&gt;
&lt;td&gt;On-prem only&lt;/td&gt;
&lt;td&gt;First-class hybrid by design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment complexity&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;High (forest pair + SQL + MIM)&lt;/td&gt;
&lt;td&gt;Highest (forest pair + full DR)&lt;/td&gt;
&lt;td&gt;Variable (sum of constituents)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft current status (May 2026)&lt;/td&gt;
&lt;td&gt;Recommended for on-prem enforcement&lt;/td&gt;
&lt;td&gt;OT / ICS / regulated air-gapped only&lt;/td&gt;
&lt;td&gt;Legacy; supported for existing + OT only&lt;/td&gt;
&lt;td&gt;Recommended as top-level architecture&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Method D is the framework; Method A is the on-prem enforcement layer inside it; Methods B and C are the niche answers for environments Method A cannot reach. The four are not in competition for the same job. A connected hybrid enterprise in 2026 runs Method D + Method A on-prem, with B and C reserved for the air-gapped exception cases.&lt;/p&gt;
&lt;p&gt;EAM is the framework. Method A is its on-prem enforcement layer. What does Method A&apos;s enforcement layer NOT close, by construction?&lt;/p&gt;
&lt;h2&gt;8. What the KDC cannot enforce&lt;/h2&gt;
&lt;p&gt;A well-deployed Method A architecture eliminates the credential-theft attack chain at the KDC. It does not close every gap. The remaining gaps are not implementation bugs; they are structural properties of where the KDC sits in the stack. Naming them is not optional.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The RBCD residual.&lt;/strong&gt; &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Resource-based constrained delegation&lt;/a&gt; is configured by writing the &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; attribute on the target object [@ms-sfu]. The write is governed by the &lt;em&gt;target object&apos;s&lt;/em&gt; DACL, not by the Silo plane. The KDC never sees the write; it only sees the resulting TGS-REQ. If the target is a service account that is Silo&apos;d but not in Protected Users -- which, per Microsoft Learn&apos;s explicit guidance, is the case for most service accounts -- the RBCD chain remains exploitable. The defence is layered: pin the source machine via the Silo Policy, deny &lt;code&gt;WriteProperty&lt;/code&gt; on &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; for everyone but directory administrators, prefer Group Managed Service Accounts for new services, and put Defender for Identity detection on the attribute-write event [@ms-mdi].&lt;/p&gt;

A constrained-delegation primitive introduced in Windows Server 2012. Unlike classic constrained delegation (configured by the privileged administrator on the *delegating* service via `msDS-AllowedToDelegateTo`), RBCD is configured on the *target* by writing `msDS-AllowedToActOnBehalfOfOtherIdentity`. The target object&apos;s owner controls which services may impersonate users to it. Governance is at the ACL plane, not the KDC plane, which is why RBCD writes are invisible to Authentication Policy Silo enforcement [@ms-sfu].
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Even after every tier-model, Silo, and Protected Users control is correctly deployed, RBCD remains exploitable against any tier-protected service account that is not also in Protected Users -- which, in practice, is most service accounts. Protected Users would close the gap but breaks delegation workflows. The KDC cannot prevent writes to &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; because the write is an ACL operation on a directory attribute, not a Kerberos operation. The defence is necessarily layered: ACL the attribute, Silo the target, gMSA the credential material, detect the write at the SIEM.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Physical extraction from a logged-on T0 host.&lt;/strong&gt; The KDC cannot prevent the extraction of credential material from the memory of a machine on which the user is logged on. The credential has to exist somewhere in memory for the user to use it. Credential Guard raises the bar dramatically by placing the credential material in a VBS-protected VTL1 enclave that the VTL0 kernel cannot read, even with a signed driver [@ms-cred-guard]. Remote Credential Guard adds a parallel host-side control for RDP-initiated authentications that redirects Kerberos requests back to the originating client [@ms-rcg]. None of these is a KDC control. The KDC and the host are two layers; both are required.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The on-prem-to-cloud bridge.&lt;/strong&gt; On-prem AD KDC enforcement (Silo membership) and Entra ID Conditional Access enforcement are two independent policy planes by construction. The &lt;a href=&quot;https://paragmali.com/blog/inside-the-primary-refresh-token-the-cryptographic-seam-betw/&quot; rel=&quot;noopener&quot;&gt;Primary Refresh Token&lt;/a&gt; does not carry &lt;code&gt;msDS-AssignedAuthNPolicySilo&lt;/code&gt;. Conditional Access does not consume the Silo binding. Operational alignment is achieved by synchronising the Silo&apos;d group through Microsoft Entra Connect and writing a Conditional Access policy keyed on the synced group. The CA sees the synchronised group; it does not see the Silo. Two planes, both must hold.&lt;/p&gt;
&lt;p&gt;The host-side limit (&quot;Credential Guard moves the bar but cannot eliminate physical extraction&quot;) is the topic of the earlier Credential Guard post in this series; the on-prem-to-cloud limit is the topic of the Conditional Access post. The four-residual recognition in this section is the joint that connects all three.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Closing the on-prem-to-cloud gap requires either a Microsoft product change that projects Silo membership into the Primary Refresh Token, or a third-party policy synthesiser. Neither exists as a product surface in May 2026 -- which is why the §10 Phase 4 workaround (sync the Silo&apos;d group through Microsoft Entra Connect, key the Conditional Access policy on the synced group) is the current production answer. The workaround keeps both planes independent by construction; it does not close the gap, it routes around it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Supply-chain compromise of T0 software.&lt;/strong&gt; The KDC cannot enforce policy against an agent running as SYSTEM on every domain controller. By construction, the agent is outside the KDC&apos;s authorisation scope; it can rewrite the directory the KDC reads its policy from. The canonical instance is the SolarWinds Orion compromise disclosed in December 2020 (CISA Alert AA20-352A): the attackers used a backdoored Orion update to obtain SYSTEM-level access on management hosts and, per the CISA advisory&apos;s &lt;em&gt;User Impersonation&lt;/em&gt; section, in several documented cases used that access to compromise &quot;the SAML signing certificate using their escalated Active Directory privileges&quot; -- the AD FS / Entra Connect token-signing certificate -- and then &quot;create unauthorized but valid tokens&quot; presented to services that trust SAML tokens from the environment, on T0 systems where the secret material has to exist in memory for the system to do its job [@cisa-aa20-352a]. The KDC saw legitimately-signed tickets and made legitimate policy decisions; the enforcement gap is one layer below, where the software running as the KDC&apos;s neighbour ships compromised code. The closure for this residual is not at the KDC; it is at the software-supply-chain layer (code signing, reproducible builds, attested deployment, and strict T0-software inventory).&lt;/p&gt;

Every Method A deployment requires two emergency-access break-glass accounts that are outside every Silo and outside Protected Users -- see §10 Phase 5 for the operational pattern (offline-stored passwords, monthly use-and-rotate, high-fidelity SIEM detection, RID 500 as the canonical first identity). Microsoft&apos;s RaMP guidance treats this as the *first* step of the privileged-access rollout, before any of the controls in §5 and §6 are deployed [@ms-ramp].
&lt;p&gt;A maximally-correct Method A deployment closes the KDC-plane gaps it was designed to close. Four explicit residuals remain by construction. Three need additional controls (target-ACL hardening, Credential Guard, Conditional Access keyed on the synced group); the fourth is closed at the software-supply-chain layer. The architecture is correct. The world is bigger than the architecture.&lt;/p&gt;
&lt;p&gt;What is the active research, and what does a practitioner do on Monday morning to deploy what is settled?&lt;/p&gt;
&lt;h2&gt;9. Active research lines as of mid-2026&lt;/h2&gt;
&lt;p&gt;The community is not standing still. Five lines of work are visible on the public radar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Projecting Authentication Policy Silo membership into Entra Conditional Access as a first-class signal.&lt;/strong&gt; The most-named open problem in both SpecterOps research and Microsoft&apos;s own post-NTLM roadmap discussion. Matthew Palko&apos;s October 2023 post &lt;em&gt;Evolution of Windows Authentication&lt;/em&gt; is Microsoft&apos;s institutional acknowledgement that the post-NTLM future is Kerberos plus IAKerb plus Local KDC; the post does not commit to projecting Silo membership into the Primary Refresh Token, but it is the closest reading the community has of a hybrid identity direction [@palko-evol]. IAKerb plus Local KDC is plausibly the substrate that could eventually carry Silo state across the on-prem-to-cloud boundary, but no public Microsoft roadmap entry as of May 2026 announces that projection.&lt;/p&gt;

A community-maintained checklist of Active Directory and Microsoft Entra ID assets, annotated with whether each asset is &quot;Tier Zero&quot; (its compromise grants forest-wide or tenant-wide control), what platform it sits on, how to identify it (typically by SID or by role assignment), and what attack techniques apply by default versus by misconfiguration. The repository is `github.com/SpecterOps/TierZeroTable` with a rendered live view at `specterops.github.io/TierZeroTable` [@tzt-github][@tzt-pages].
&lt;p&gt;&lt;strong&gt;Tier Zero scoping at hybrid-cloud scale.&lt;/strong&gt; Defining the boundary of T0 in a hybrid environment is increasingly difficult. The on-prem T0 set (DCs, AD CS, Entra Connect, DC backup) is enumerable. The cloud-side T0 set (Entra ID Application Administrators with Graph permissions over AD-synced objects, Hybrid Identity Administrators, Global Administrators, Privileged Authentication Administrators) is large, dynamic, and contains roles whose tier-0 status is contested. The SpecterOps Tier Zero Table is the community&apos;s canonical operational answer; its GitHub README is explicit that &quot;the table does not include all Tier Zero assets yet&quot; [@tzt-github]. BloodHound Community Edition is the companion discovery primitive: feed it a directory snapshot, ask it for attack paths to T0, fix the paths [@bloodhound]. The introductory blog series at SpecterOps explains the &quot;Defining the Undefined&quot; definitional work behind the table [@tier-zero-part1].&lt;/p&gt;
&lt;p&gt;If you have never used BloodHound against your own forest, that is the most leveraged single action you can take this month. The tool exposes the attack paths your tier model is supposed to be closing -- and the gaps are almost always somewhere you did not look. The Tier Zero Table is the human-readable companion; BloodHound is the machine-readable one [@bloodhound][@tzt-github].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Continued discovery of ADCS misconfiguration classes (ESC1-ESC8+).&lt;/strong&gt; Schroeder and Christensen&apos;s June 17, 2021 &lt;em&gt;Certified Pre-Owned&lt;/em&gt; whitepaper was the inflection [@cert-preowned-blog][@cert-preowned-pdf]. The original taxonomy catalogued ESC1 through ESC8; ESC9 and several subsequently-disclosed classes have been added since by the SpecterOps team and the wider AD CS research community, with the GhostPack &lt;code&gt;Certify&lt;/code&gt; tool tracking the enumerable classes in its active branch [@ghostpack-certify], and adjacent variants continuing to land in the SpecterOps blog stream. Each class is a tier-bypass primitive that survives Method A&apos;s deployment if the AD CS configuration is itself misconfigured: the KDC sees a legitimately-signed certificate and a legitimate AS-REQ. KB 5014754&apos;s strong-mapping closes the specific CVE-2022-26923 (&quot;Certifried&quot;) class; template hardening (manager-approval, no-CT, no-enrollee-supplies-subject) addresses several other classes [@kb-5014754].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kerberos relay primitives.&lt;/strong&gt; The KrbRelay family of attacks, anchored to James Forshaw&apos;s October 2021 Project Zero research on cross-protocol Kerberos relaying [@krb-relay-pz] and operationalised in the &lt;code&gt;cube0x0/KrbRelay&lt;/code&gt; tool released shortly thereafter [@cube0x0-krbrelay], exploits the absence of channel binding in some pre-authentication flows. Silos enforce on the source-machine identity &lt;em&gt;as presented in the AS-REQ&lt;/em&gt;; an attacker who can cause a different machine to issue an AS-REQ on the attacker&apos;s behalf and relay it can satisfy the Silo Policy. FAST (RFC 6113) provides the cryptographic primitive for channel binding [@rfc-6113]; Microsoft&apos;s Kerberos armoring uses FAST, and a Silo Policy can be configured to require FAST armoring. The open deployment question is whether FAST armoring becomes the universal default in legacy environments. The Palko post on the post-NTLM Windows authentication roadmap is the closest Microsoft has come to addressing the deployment direction publicly [@palko-evol].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Service-account placement: Protected Users vs. Silo-only.&lt;/strong&gt; The unsolved sub-problem inside the RBCD residual. Service accounts have two failure modes: they cannot be placed in Protected Users without breaking their delegation workflows, and they cannot be left out without leaving an RBCD-attack primitive against tier-protected service accounts that have writable &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt;. The current best partial result is composite: Group Managed Service Accounts plus a tight Silo Policy plus an ACL on the delegation attribute plus a SIEM rule on attribute writes. The architectural answer would be an extension to Protected Users that retains delegation-as-source but refuses NTLM, RC4, and DES. No such extension appears on Microsoft&apos;s public roadmap as of May 2026 [@ms-pu-current][@ms-mdi].&lt;/p&gt;
&lt;p&gt;The settled controls are deployable. The open research is real and has not been closed. Five years from now, the Silo plane will likely still be the operational answer, with the residuals closed by different parts of the stack. What does that look like to a practitioner reading this on a Monday morning?&lt;/p&gt;
&lt;h2&gt;10. A six-phase playbook for deploying Method A this quarter&lt;/h2&gt;
&lt;p&gt;A staged playbook. The phases are ordered for safety: each phase reduces the blast radius of the next, and the first phase is the most important and the most often skipped.&lt;/p&gt;
&lt;h3&gt;Phase 0: Inventory Tier 0&lt;/h3&gt;
&lt;p&gt;Use the SpecterOps Tier Zero Table as the starting checklist [@tzt-github][@tzt-pages]. Pair it with BloodHound Community Edition to discover the attack paths your environment actually has into the T0 set [@bloodhound]. The Tier Zero Table is intentionally incomplete -- treat it as the floor, not the ceiling -- and add the assets specific to your environment: any service account whose compromise grants write access to a DC, any backup system that can restore a DC&apos;s NTDS.dit, any monitoring system that can run code on a DC. Sean Metcalf&apos;s body of work on secure workstation baselines is the canonical operator-grade reading for this phase [@metcalf-p3299][@metcalf-p1738].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Do not start with Silo creation. Start with the T0 inventory. Every subsequent phase depends on a defensible list of what T0 contains. A T0 asset missed by the inventory is a T0 asset that is not Silo&apos;d, not in Protected Users, and not behind a Conditional Access policy on the cloud side. Phase 0 is the single most-skipped step in failed Method A deployments and the single highest-value step in successful ones.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Phase 1: Create the T0 Admins Silo and Policy in audit mode&lt;/h3&gt;
&lt;p&gt;Create the &lt;code&gt;msDS-AuthNPolicySilo&lt;/code&gt; named &quot;T0 Admins&quot; and its referenced &lt;code&gt;msDS-AuthNPolicy&lt;/code&gt; named &quot;T0 Source Restriction.&quot; Set &lt;code&gt;msDS-AuthNPolicySiloEnforced=FALSE&lt;/code&gt; to start in audit mode [@ms-aps]. Place a single test admin account in Protected Users and assign it to the Silo. Set the Policy&apos;s &lt;code&gt;UserAllowedToAuthenticateFrom&lt;/code&gt; SDDL to a SID set containing exactly one PAW. Confirm that authentication from the PAW succeeds, that authentication from a tier-2 workstation generates the expected audit event (&lt;code&gt;Authentication Policy Silo&lt;/code&gt; audit failure in the Security log), and that nothing else in the environment breaks. Once the audit window is clean, flip the Silo to enforced mode. The KDC now returns &lt;code&gt;KDC_ERR_POLICY&lt;/code&gt; for any AS-REQ from outside the allowed-from set [@ms-kile].&lt;/p&gt;
&lt;h3&gt;Phase 2: Catalogue every delegation relationship in the directory&lt;/h3&gt;
&lt;p&gt;Enumerate every account with &lt;code&gt;msDS-AllowedToDelegateTo&lt;/code&gt; set, every object with &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; set, and every account with the legacy &lt;code&gt;TrustedForDelegation&lt;/code&gt; UAC bit. For each T0-adjacent service account, decide whether the workflow can survive Protected Users membership. If yes, enrol the account and move on. If no -- which will be the common answer -- create a &quot;T0 Services&quot; Silo with a tight &lt;code&gt;UserAllowedToAuthenticateFrom&lt;/code&gt; Policy, bind the account to the Silo, deny &lt;code&gt;WriteProperty&lt;/code&gt; on &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; for everyone but directory administrators, and audit Defender for Identity for the corresponding alerts [@ms-mdi]. The composite defence is the current best partial answer to the RBCD residual.&lt;/p&gt;
&lt;p&gt;Group Managed Service Accounts (gMSA) are the preferred new-service-account primitive for the §6 reference deployment. The Microsoft Key Distribution Service (&lt;code&gt;kdssvc.dll&lt;/code&gt;) on the domain controller derives the account&apos;s password from a domain-wide root key plus a per-account key identifier and rotates it on a configurable schedule; service hosts retrieve the current password through an ACL-controlled flow [@ms-gmsa-overview]. The cryptographic-rotation property -- not Silo membership -- is what closes the AS-REP roasting primitive in practical timeframes for a service-account workflow that the §6 PullQuote forbids from enrolling in Protected Users. Microsoft&apos;s &lt;em&gt;How to Configure Protected Accounts&lt;/em&gt; page covers the wider per-account migration shape for legacy non-gMSA services [@ms-config-pa].&lt;/p&gt;
&lt;h3&gt;Phase 3: Roll the human T0 administrators into Protected Users in batches&lt;/h3&gt;
&lt;p&gt;Audit the longest-running tier-0 administrative task in your environment &lt;em&gt;before&lt;/em&gt; you enrol anyone. Forest backups, replication health checks, schema upgrade dry-runs, DC promotions, and emergency operational procedures sometimes exceed four hours; the Protected Users 240-minute non-renewable TGT cap will silently re-authenticate or fail outright when they do [@ms-config-pa]. Enrol in batches of two or three administrators at a time; keep the previous batch in for at least two weeks before adding the next. Microsoft&apos;s &lt;em&gt;How to Configure Protected Accounts&lt;/em&gt; page lays out the staged enrolment shape [@ms-config-pa].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 240-minute non-renewable TGT cap on Protected Users members is the single most common cause of failed pilot deployments. Tasks that ran fine for years quietly fail at the 4-hour mark, or worse, re-authenticate against a different identity that has lower privilege. Audit your longest-running T0 operations against the cap &lt;em&gt;before&lt;/em&gt; enrolling humans; document workarounds (&lt;code&gt;runas&lt;/code&gt; for long tasks; batch jobs running under gMSAs with a per-Policy lifetime configured deliberately) before the enrolment, not after.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Phase 4: Project the T0 group into Entra Conditional Access&lt;/h3&gt;
&lt;p&gt;Sync the T0 Admins group through Microsoft Entra Connect. Write a Conditional Access policy that requires phishing-resistant MFA (FIDO2, Windows Hello for Business, or certificate-based authentication) for that group, plus a compliant device, plus a known-good location if the threat model justifies it [@ms-pim]. Document explicitly that the CA is keyed on the synchronised group, not on the Silo binding; the two enforcement planes are independent by construction. The Entra side is the topic of the Conditional Access post in this series for the deeper treatment.&lt;/p&gt;
&lt;p&gt;For the cloud-side treatment of Conditional Access policy shapes -- compliant device, phishing-resistant MFA grant control, location and risk conditions -- see the Conditional Access post in this series. The CA policy keyed on the synced T0 group is what holds the two-plane workaround together.&lt;/p&gt;
&lt;h3&gt;Phase 5: Break-glass&lt;/h3&gt;
&lt;p&gt;Two emergency-access accounts that are &lt;em&gt;outside&lt;/em&gt; every Silo, &lt;em&gt;outside&lt;/em&gt; Protected Users, with passwords stored offline in a tamper-evident envelope held by two separate people, with a documented monthly use-and-rotate procedure, and with high-fidelity SIEM detection on every authentication attempt. The cost of the break-glass pair is the deliberate, audited counter-balance to the rest of the architecture. Microsoft&apos;s RaMP guidance treats this as the &lt;em&gt;first&lt;/em&gt; step of the privileged-access rollout [@ms-ramp]. The built-in domain Administrator (RID 500) is the natural canonical first break-glass identity because it is exempt from Authentication Policy enforcement even when assigned to a Silo [@ms-pu-current].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s RaMP page lists &quot;Emergency access accounts&quot; as the first initiative of the entire Rapid Modernization Plan, ahead of Entra PIM and the on-prem controls [@ms-ramp]. The ordering is deliberate: a privileged-access deployment that locks itself out before it has secured the recovery path is worse than no deployment at all.&lt;/p&gt;

The Active Directory PowerShell module exposes the cmdlets directly. The skeleton below creates a Policy and a Silo in audit mode, then assigns one user. Adapt the SDDL to your PAW computer SIDs before running.&lt;p&gt;&lt;code&gt;New-ADAuthenticationPolicy -Name &quot;T0 Source Restriction&quot; -UserTGTLifetimeMins 240 -UserAllowedToAuthenticateFrom &apos;O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo == &quot;T0 Admins&quot;))&apos;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;@USER.ad://ext/AuthenticationSilo&lt;/code&gt; token in that SDDL is evaluated at AS-REQ time against the &lt;em&gt;source machine&apos;s&lt;/em&gt; user-token claims, not against the requesting user&apos;s own Silo binding -- the Policy admits the requesting user only from devices whose computer accounts are themselves Silo members of &quot;T0 Admins&quot; (typically the T0 PAW set). The token&apos;s evaluation context is the source-device side of the request, which is the practical encoding of the source-machine pinning Method A relies on [@ms-aps].&lt;/p&gt;
&lt;p&gt;&lt;code&gt;New-ADAuthenticationPolicySilo -Name &quot;T0 Admins&quot; -Enforce:$false -UserAuthenticationPolicy &quot;T0 Source Restriction&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Set-ADAccountAuthenticationPolicySilo -Identity alice.da -AuthenticationPolicySilo &quot;T0 Admins&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Add-ADGroupMember -Identity &quot;Protected Users&quot; -Members alice.da&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Run in audit mode (Enforce:false) for a full audit cycle, validate the Security log for &lt;code&gt;Authentication Policy Silo&lt;/code&gt; events, then flip to enforced mode. The official PowerShell-cmdlet documentation is on the Microsoft Learn AD-cmdlet pages; the relevant deployment shape is described in &lt;em&gt;How to Configure Protected Accounts&lt;/em&gt; [@ms-config-pa].
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You have a playbook. You also have a set of questions readers are now going to ask. Here they are.&lt;/p&gt;
&lt;h2&gt;11. Frequently asked questions&lt;/h2&gt;


No -- service accounts must not be (see §6&apos;s canonical Microsoft Learn PullQuote), and workstation users do not need to be (the Silo plane and Credential Guard handle their threat model). For human administrators, the answer is &quot;yes, in batches, after testing&quot; -- see §10 Phase 3&apos;s Callout on the 4-hour TGT cap, which is the single most common pilot break.


Indirectly. Kerberoasting per se is defeated by AES-only enforcement and high-entropy passwords. Protected Users forbids RC4 and DES for its members, so a Silo&apos;d and Protected human administrator cannot be roasted with the public RC4-dependent tooling. For service accounts that cannot be Protected, the defence is explicit AES enforcement via `msDS-SupportedEncryptionTypes` plus gMSA-managed high-entropy passwords [@ms-config-pa]. Defender for Identity surfaces accounts that still use RC4 [@ms-mdi].


No. Two independent planes. The PRT does not carry `msDS-AssignedAuthNPolicySilo`, and Conditional Access does not consume it. The standard alignment is to synchronise the Silo&apos;d group through Microsoft Entra Connect and write a CA policy keyed on the synced group. The CA sees the synchronised group, not the Silo. Both planes must hold for a hybrid privileged identity to be safe [@ms-eam][@palko-evol]. Closing the gap requires either a Microsoft product change or a third-party policy synthesiser; neither exists as a product surface in May 2026.


Subtly. ESAE -- the Red Forest pattern -- was retired as a mainstream recommendation on December 15, 2020 [@ms-esae-retire]. The tier model as an *idea* was folded into the Enterprise Access Model [@ms-eam]; the directory-level controls (Authentication Policy Silos, Protected Users) remain Microsoft&apos;s recommended on-prem enforcement layer. New ESAE deployments are not recommended outside air-gapped OT, ICS, and SCADA scenarios; existing ESAE deployments operating as designed have no urgency to retire.


KB 2871997 is the May 13, 2014 down-level backport of Protected Users client-side honoring and Authentication Policy / Silo client-side support to Windows 7, Windows 8, Server 2008 R2, and Server 2012 [@kb-2871997]. It is NOT the introduction of those features -- the introduction is Windows Server 2012 R2 GA on October 18, 2013 [@save-date-blog][@ms-pu-legacy]. The October 14, 2014 revision additionally shipped Restricted Admin Mode for RDP, which has its own cautionary history as the canonical example of a defence that became its own inverse [@kfalde-restricted-admin][@ms-rcg].


The schema supports it -- a Silo&apos;s `msDS-ComputerAuthNPolicy` link carries a Computer Policy with its own Computer TGT Lifetime, and DCs are valid Silo members in principle [@ms-aps]. The operational pattern doesn&apos;t do that, for two reasons. First, DCs are themselves the authentication authority, and Microsoft Learn&apos;s Authentication Policies and Silos page explicitly warns against changing Computer TGT Lifetime on DC class accounts because shortened TGT lifetimes disrupt replication and other DC-to-DC operations (&quot;It is not recommended to change this setting&quot; [@ms-aps]). Second, the Silo plane is built for the accounts that authenticate *to* DCs -- T0 admins, the AD CS computer account, the Entra Connect server -- where source-machine pinning is the high-impact control. Silo the accounts that authenticate to your DCs; protect the DCs themselves with the orthogonal directory primitives (KDC service-account configuration, Defender for Identity sensor deployment, code-signing and update management, physical isolation). The Tier Zero Table and BloodHound surface the DC-adjacent accounts that need Silo membership [@tzt-github][@bloodhound].

&lt;p&gt;The directory now has the answer it lacked for sixteen years. Three controls, one ship, plus thirteen years of operational discipline to compose them, plus an explicit acknowledgement of the four residuals the KDC cannot close by construction. On the Tuesday morning in April 1997 when Paul Ashton posted his patched &lt;code&gt;smbclient&lt;/code&gt; to NTBugtraq, no one in the AD product group could have written this article. They can now -- and the KDC, keyed on directory state, is the layer they would write it from.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;ad-tiering-protected-users-silos&quot; keyTerms={[
  {&quot;term&quot;: &quot;Pass-the-Hash&quot;, &quot;definition&quot;: &quot;Credential-theft technique that uses an account&apos;s NT hash as the long-term key. The NTLM protocol cannot distinguish the legitimate password-holder from anyone holding the hash.&quot;},
  {&quot;term&quot;: &quot;Protected Users&quot;, &quot;definition&quot;: &quot;Global security group (well-known RID 525) introduced in Windows Server 2012 R2. Members get a non-configurable credential-restriction set: no NTLM, no DES or RC4 in Kerberos, no delegation, no cached offline-sign-in verifier, 240-minute non-renewable TGT cap.&quot;},
  {&quot;term&quot;: &quot;Authentication Policy Silo&quot;, &quot;definition&quot;: &quot;The msDS-AuthNPolicySilo container object. Enumerates the user, computer, and service accounts that share a set of restrictions, and references one or more Authentication Policies whose rules apply to its members.&quot;},
  {&quot;term&quot;: &quot;Authentication Policy&quot;, &quot;definition&quot;: &quot;The msDS-AuthNPolicy rules object. Carries the TGT lifetime cap, the allowed-from SDDL on source-machine identity, allowed-to delegation rules, claim transformations, and optional FAST armoring requirement.&quot;},
  {&quot;term&quot;: &quot;KDC (Key Distribution Center)&quot;, &quot;definition&quot;: &quot;The Kerberos authentication service that handles AS-REQ (TGT issuance) and TGS-REQ (service-ticket issuance). On Windows, every DC runs a KDC; the KDC reads policy from the directory at request time.&quot;},
  {&quot;term&quot;: &quot;PAC (Privilege Attribute Certificate)&quot;, &quot;definition&quot;: &quot;Microsoft authorisation-data structure carried inside Kerberos TGTs and service tickets. PAC_LOGON_INFO.GroupIds encodes Protected Users membership via well-known SID 525.&quot;},
  {&quot;term&quot;: &quot;Tier 0 (T0)&quot;, &quot;definition&quot;: &quot;The control plane: domain controllers, AD CS root CAs, Entra Connect servers, DC backup systems, and any system whose compromise grants forest-wide control.&quot;},
  {&quot;term&quot;: &quot;Enterprise Access Model (EAM)&quot;, &quot;definition&quot;: &quot;Microsoft&apos;s December 15, 2020 meta-architecture for privileged-access. Segments by access level (privileged-access, management, data/workload, user/app) rather than by forest boundary, and incorporates Entra ID admin roles as first-class control-plane objects.&quot;},
  {&quot;term&quot;: &quot;RBCD (Resource-Based Constrained Delegation)&quot;, &quot;definition&quot;: &quot;Constrained delegation configured by writing msDS-AllowedToActOnBehalfOfOtherIdentity on the target. Governed by the target object&apos;s ACL, not by the Silo plane; remains exploitable against tier-protected service accounts that cannot be in Protected Users.&quot;},
  {&quot;term&quot;: &quot;Tier Zero Table (SpecterOps)&quot;, &quot;definition&quot;: &quot;Community-maintained checklist of AD and Entra ID assets that must be enclosed in the T0 control plane. Intentionally incomplete; designed to be the floor of the inventory, not the ceiling.&quot;}
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>active-directory</category><category>kerberos</category><category>authentication-silos</category><category>protected-users</category><category>tiering</category><category>credential-theft</category><category>pass-the-hash</category><category>privileged-access</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Two Checkmarks and the Keys to the Kingdom: How Active Directory&apos;s Replication Protocol Became the Longest-Lived Credential Attack on Windows</title><link>https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/</link><guid isPermaLink="true">https://paragmali.com/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/</guid><description>MS-DRSR was designed for domain controllers to replicate secrets to each other. Its access check gates on an ACL, not on whether the caller is a DC. Eleven years after Mimikatz proved it, no patch can fix it.</description><pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate><content:encoded>
Active Directory&apos;s replication protocol (MS-DRSR) lets any domain controller pull every secret in the directory from any other domain controller, and the access check gates on an ACL, not on whether the caller is actually a DC. Mimikatz&apos;s `lsadump::dcsync` (August 11, 2015) and `lsadump::dcshadow` (January 2018) are the read and write sides of this loophole; both remain in active operational use eleven years later because the protocol cannot be amended without breaking AD replication. Credential Guard cannot help -- the secret moves from a remote DC&apos;s NTDS.dit over the network, never touching the attacker&apos;s LSASS. The 2026 defender response is four parallel detection layers (posture, behavioral, network, graph) because no single layer catches every case, and the architectural fifth layer that would close the class is not coming.
&lt;h2&gt;1. Two Checkmarks and the Keys to the Kingdom&lt;/h2&gt;
&lt;p&gt;A non-admin service account, created during a 2017 file-server migration and never cleaned up, holds exactly two access-control entries on the &lt;code&gt;contoso.local&lt;/code&gt; domain object: &lt;code&gt;Replicating Directory Changes&lt;/code&gt; and &lt;code&gt;Replicating Directory Changes All&lt;/code&gt;. From a Windows 11 workstation -- not a domain controller, not a tier-zero admin host, just a desk -- the attacker opens a Mimikatz prompt and types:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lsadump::dcsync /domain:contoso.local /user:krbtgt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sixty seconds later they have the &lt;code&gt;krbtgt&lt;/code&gt; NT hash and &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos AES keys&lt;/a&gt;, and they own the domain. &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt;, enabled on every workstation in the building, never saw the credential transit anywhere in its scope.&lt;/p&gt;
&lt;p&gt;That last sentence is the punchline of the entire field. The secret never touches the attacker&apos;s LSASS, so Credential Guard&apos;s design has nothing to say. The keys move from a remote domain controller&apos;s on-disk database, over an RPC channel, into the attacker&apos;s process memory. Credential Guard isolates LSASS on the &lt;em&gt;local&lt;/em&gt; machine. It has no jurisdiction over what a remote DC chooses to send when asked nicely.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Credential Guard isolates LSASS-resident secrets in a separate virtual trust level. DCSync reads secrets from a remote DC&apos;s NTDS.dit over MS-DRSR -- a network protocol attack, not a local-memory attack. Microsoft&apos;s Credential Guard documentation does not claim protection against MS-DRSR-based credential extraction [@credential-guard-considerations].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The 60-second timeline is not a marketing number. One RPC round trip per principal is the protocol&apos;s per-principal cost, fixed by specification. For a single high-value target -- and &lt;code&gt;krbtgt&lt;/code&gt; is the highest-value target in any Active Directory forest, because its long-term key signs every Kerberos ticket -- the attack is over before a typical SOC operator has finished pouring coffee.&lt;/p&gt;
&lt;p&gt;The four people whose names recur in this story are worth meeting now. Benjamin Delpy (gentilkiwi) wrote Mimikatz and authored both the DCSync read primitive (2015) and, with Vincent Le Toux, the DCShadow write primitive (2018). Vincent Le Toux built the original DCShadow implementation and the PingCastle posture-assessment tool. Sean Metcalf (Trimarc / ADSecurity) translated DCSync into operator vocabulary in the weeks after its release. Microsoft&apos;s Defender for Identity team ships the canonical first-party detections that fire on this attack class today.&lt;/p&gt;
&lt;p&gt;This story is what happens when a 23-year-old domain-controller-to-domain-controller protocol&apos;s access check turns out to gate on an ACL, not on whether the caller is a domain controller. Two ACEs on one object should not give an attacker the entire credential trove. The fact that they do is not a bug in the implementation. It is a 1999 design assumption -- that nobody who is not a DC would ever speak this protocol -- that survived twenty-five years as a social convention and was nowhere written down in the access-check code.&lt;/p&gt;
&lt;p&gt;The next section explains why Microsoft built this protocol in the first place, and why its access check forgot to ask the one question that would have closed the loophole.&lt;/p&gt;
&lt;h2&gt;2. Why the Protocol Exists at All&lt;/h2&gt;
&lt;p&gt;Rewind to February 17, 2000. Microsoft ships Windows 2000 Server, and Active Directory replaces the old NT 4.0 PDC/BDC model [@microsoft-windows-2000-launch]. NT 4.0 was single-master: one Primary Domain Controller held the authoritative account database, every Backup Domain Controller held a read-only copy, and a password change on the PDC propagated to BDCs through a hub-and-spoke replication channel. AD inverts the model. Every domain controller in an AD domain holds a writable copy of the directory; a password change on &lt;em&gt;any&lt;/em&gt; DC must propagate to every other DC within minutes; the replication topology is a mesh, not a star.&lt;/p&gt;
&lt;p&gt;Multi-master replication is the design constraint that forces MS-DRSR&apos;s existence. If any DC can accept a write, then every DC must be able to pull every change -- &lt;em&gt;including secret attributes&lt;/em&gt; like &lt;code&gt;unicodePwd&lt;/code&gt;, &lt;code&gt;dBCSPwd&lt;/code&gt;, &lt;code&gt;ntPwdHistory&lt;/code&gt;, &lt;code&gt;lmPwdHistory&lt;/code&gt;, and &lt;code&gt;supplementalCredentials&lt;/code&gt; -- from every other DC. There is no second protocol. Replication of secrets is replication, and replication is MS-DRSR [@ms-drsr-spec].&lt;/p&gt;

The RPC protocol by which any Active Directory domain controller can replicate any object, including secret attributes, from any other DC in the same forest. Layered over DCE/RPC; the current public specification is revision 46.0 dated March 9, 2026 [@ms-drsr-spec]. MS-DRSR is the mechanism that makes AD&apos;s multi-master replication invariant work.

The MS-DRSR method (opnum 3) that returns changed objects within a naming context. A calling DC supplies a target DN and a set of replication flags; the called DC returns the object&apos;s attribute values, with secret attributes encrypted under a session-derived key. This is the protocol method that DCSync invokes.

flowchart LR
    subgraph Domain[&quot;contoso.local domain&quot;]
        DCA[DC-A&lt;br /&gt;NTDS.dit]
        DCB[DC-B&lt;br /&gt;NTDS.dit]
        DCC[DC-C&lt;br /&gt;NTDS.dit]
    end
    DCA -- IDL_DRSGetNCChanges&lt;br /&gt;unicodePwd, ntPwdHistory --&amp;gt; DCB
    DCB -- IDL_DRSGetNCChanges&lt;br /&gt;supplementalCredentials --&amp;gt; DCA
    DCB -- IDL_DRSGetNCChanges&lt;br /&gt;dBCSPwd --&amp;gt; DCC
    DCC -- IDL_DRSGetNCChanges&lt;br /&gt;unicodePwd --&amp;gt; DCB
    DCA -- IDL_DRSGetNCChanges&lt;br /&gt;ntPwdHistory --&amp;gt; DCC
    DCC -- IDL_DRSGetNCChanges&lt;br /&gt;krbtgt keys --&amp;gt; DCA
&lt;p&gt;The access check that gates &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; is defined in [MS-DRSR] §4.1.10. It asks one question: does the calling principal hold the appropriate extended rights on the naming-context root being replicated? Extended rights are AD&apos;s mechanism for control-access permissions that do not fit into the standard ACL bit set [@ms-drsr-spec].&lt;/p&gt;

A schema-defined access-control right identified by a GUID rather than by a standard ACL bit. Extended rights are granted via an access-control entry on a target object and checked at runtime by the operation that requires them. The three replication extended rights are the canonical example: each is identified only by GUID, and each is checked by `IDL_DRSGetNCChanges` against the caller&apos;s effective rights on the naming-context root.

A top-level replication partition of the Active Directory database. Every AD forest has at least three NCs: the Schema NC, the Configuration NC, and one Domain NC per domain (plus optional Application NCs). DCSync operates against the Domain NC root.
&lt;p&gt;Three extended rights together form what practitioners call the rights triad. The two-checkmark version from §1 is the most-common configuration; the third right unlocks a smaller set of attributes flagged confidential. Microsoft&apos;s own AD schema documentation enumerates each one [@ad-schema-get-changes][@ad-schema-get-changes-all][@ad-schema-get-changes-filtered-set]:&lt;/p&gt;

The combination of three replication extended rights on a naming-context root: `DS-Replication-Get-Changes` (the baseline read), `DS-Replication-Get-Changes-All` (unlocks secret attributes), and `DS-Replication-Get-Changes-In-Filtered-Set` (unlocks attributes with the confidential flag). The first two are what most operators mean when they say &quot;DCSync rights&quot;; the third is sometimes required for completeness.
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Right&lt;/th&gt;
&lt;th&gt;Display name&lt;/th&gt;
&lt;th&gt;Rights-GUID&lt;/th&gt;
&lt;th&gt;What it unlocks&lt;/th&gt;
&lt;th&gt;Introduced&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DS-Replication-Get-Changes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Replicating Directory Changes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Baseline replication read&lt;/td&gt;
&lt;td&gt;Windows 2000 Server [@ad-schema-get-changes]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DS-Replication-Get-Changes-All&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Replicating Directory Changes All&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1131f6ad-9c07-11d1-f79f-00c04fc2dcd2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Secret attribute replication (&lt;code&gt;unicodePwd&lt;/code&gt;, &lt;code&gt;ntPwdHistory&lt;/code&gt;, etc.) [@ad-schema-get-changes-all]&lt;/td&gt;
&lt;td&gt;Windows Server 2003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DS-Replication-Get-Changes-In-Filtered-Set&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Replicating Directory Changes In Filtered Set&lt;/td&gt;
&lt;td&gt;&lt;code&gt;89e95b76-444d-4c62-991a-0facbeda640c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Confidential-flag attributes [@ad-schema-get-changes-filtered-set]&lt;/td&gt;
&lt;td&gt;Windows Server 2008&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;In a freshly-installed AD domain, four principal sets hold the rights triad by default on the Domain NC root: the &lt;code&gt;Domain Controllers&lt;/code&gt; group, the &lt;code&gt;Domain Admins&lt;/code&gt; group, the &lt;code&gt;Enterprise Admins&lt;/code&gt; group, and the built-in &lt;code&gt;Administrators&lt;/code&gt; group [@sean-metcalf-dcsync-2015]. Every other ACE on that object is a deliberate delegation choice made by some operator at some point in the domain&apos;s history.&lt;/p&gt;
&lt;p&gt;Now read the access check carefully. It asks whether the caller holds the rights. It does not ask anything about &lt;em&gt;who&lt;/em&gt; the caller is. The protocol does not check whether the caller&apos;s Service Principal Name is &lt;code&gt;GC/...&lt;/code&gt; or &lt;code&gt;ldap/...&lt;/code&gt; or anything else. It does not check whether the caller&apos;s machine account is in the &lt;code&gt;Domain Controllers&lt;/code&gt; group. It does not check whether the caller&apos;s Kerberos service ticket was issued for a DC service. The whole gate is the ACL on one object.&lt;/p&gt;
&lt;p&gt;This is the most consequential design omission in any Microsoft network protocol. Every other replication-style protocol in Windows ships some form of caller-machine-identity assertion. MS-DRSR shipped without one because, in 1999, nobody on the design team imagined an unprivileged workstation would speak the DC-to-DC protocol.&lt;/p&gt;
&lt;p&gt;The 1999 closed-population design assumption is the load-bearing fiction underneath this whole story. The protocol&apos;s designers assumed -- entirely reasonably for the deployment universe of that decade -- that the only software that would ever implement an MS-DRSR client was the DC role itself, which Microsoft shipped, signed, and audited. No defender in 1999 was thinking about a Python script speaking DRSUAPI from a desk. The assumption was a social convention dressed as a security model, and it survived for fifteen years.&lt;/p&gt;
&lt;p&gt;If the protocol exists to replicate every secret in the directory, and the access check is the ACL on one object, what stopped anyone from abusing it for the protocol&apos;s first fifteen years? That accidental safety period is the subject of the next section.&lt;/p&gt;
&lt;h2&gt;3. The Fifteen-Year Accidental Safety Period&lt;/h2&gt;
&lt;p&gt;Between 2000 and 2015, attackers who wanted the entire credential trove of an Active Directory domain had exactly one road open to them: reach a domain controller and steal its database. The reasons are not subtle. The credentials lived in one file -- &lt;code&gt;C:\Windows\NTDS\NTDS.dit&lt;/code&gt;, an Extensible Storage Engine database protected by a Password Encryption Key wrapped under the BootKey scattered across four registry values in the SYSTEM hive [@ntdsxtract-repo]. Without code execution on a DC, there was no obvious way to ask the directory for its secrets in bulk.&lt;/p&gt;

The on-disk Extensible Storage Engine (&quot;Jet Blue&quot;) database that holds every Active Directory object, including secret attributes. Located at `C:\Windows\NTDS\NTDS.dit` on every domain controller. The file is locked while AD DS is running; offline copying requires either Volume Shadow Copy snapshots, `ntdsutil ifm` bundling, or DC downtime [@mitre-t1003-003].
&lt;p&gt;Three sub-techniques bloomed inside this constraint, and MITRE catalogs them collectively as T1003.003 OS Credential Dumping: NTDS [@mitre-t1003-003]. Each is operationally distinct, and each requires the same precondition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;G1a -- Volume Shadow Copy plus offline parse.&lt;/strong&gt; The attacker runs &lt;code&gt;vssadmin create shadow /for=C:&lt;/code&gt; on a domain controller, creating an instant point-in-time snapshot. They copy &lt;code&gt;NTDS.dit&lt;/code&gt; and &lt;code&gt;SYSTEM&lt;/code&gt; out of the shadow path, exfiltrate both files, and parse them offline with Csaba Barta&apos;s &lt;code&gt;ntdsxtract&lt;/code&gt; toolkit [@ntdsxtract-repo] or Impacket&apos;s &lt;code&gt;secretsdump.py&lt;/code&gt; running in offline mode. The parse walks the &lt;code&gt;datatable&lt;/code&gt; ESE table row by row, decrypts the PEK with the BootKey, and decrypts each principal&apos;s secret attributes with the PEK.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;G1b -- &lt;code&gt;ntdsutil&lt;/code&gt; Install From Media.&lt;/strong&gt; The built-in command &lt;code&gt;ntdsutil &quot;activate instance ntds&quot; &quot;ifm&quot; &quot;create full C:\Temp\IFM&quot;&lt;/code&gt; packages NTDS.dit and the SYSTEM hive into a clean bundle, intended for legitimate seeding of a new replica DC. With local admin on any DC, an attacker invokes it without involving VSS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;G1c -- LSASS injection of the long-term DC secrets.&lt;/strong&gt; Mimikatz&apos;s pre-DCSync technique reads cached long-term secret material (including the &lt;code&gt;krbtgt&lt;/code&gt; key) directly out of &lt;code&gt;lsass.exe&lt;/code&gt; memory on a domain controller via &lt;code&gt;lsadump::lsa /inject /name:krbtgt&lt;/code&gt;. The variant that turned this surface into a persistence implant was Skeleton Key, disclosed by the Dell SecureWorks Counter Threat Unit on January 12, 2015 [@skeleton-key-wayback]. Skeleton Key patches the &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM&lt;/a&gt; and Kerberos validation routines in LSASS on a DC so that a single master password works for any account.&lt;/p&gt;
&lt;p&gt;Skeleton Key sits at the boundary between credential dumping and persistence. It does not produce usable NT hashes or Kerberos keys for offline forging; it gives the attacker a backdoor at the authentication step. The 2015 community debate over Skeleton Key versus the (then-imminent) DCSync technique was settled decisively by DCSync&apos;s August release: dumping the hashes is more useful than backdooring the auth path, because dumped hashes survive a DC reboot and are forge-ready material [@skeleton-key-wayback].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sub-technique&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Canonical tool&lt;/th&gt;
&lt;th&gt;Emitted artifact&lt;/th&gt;
&lt;th&gt;Host artifact on DC&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;G1a VSS + offline parse&lt;/td&gt;
&lt;td&gt;Point-in-time snapshot, file copy, offline ESE parse&lt;/td&gt;
&lt;td&gt;&lt;code&gt;vssadmin&lt;/code&gt; + &lt;code&gt;secretsdump.py&lt;/code&gt; / &lt;code&gt;ntdsxtract&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;NT hashes, Kerberos keys, password history&lt;/td&gt;
&lt;td&gt;VSS event in system log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G1b &lt;code&gt;ntdsutil&lt;/code&gt; IFM&lt;/td&gt;
&lt;td&gt;Built-in admin command produces clean bundle&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ntdsutil &quot;ac i ntds&quot; &quot;ifm&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identical to G1a&lt;/td&gt;
&lt;td&gt;IFM staging directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G1c LSASS inject&lt;/td&gt;
&lt;td&gt;Read long-term secrets from &lt;code&gt;lsass.exe&lt;/code&gt; memory&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mimikatz lsadump::lsa /inject&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;krbtgt&lt;/code&gt; key and other LSA-cached secrets&lt;/td&gt;
&lt;td&gt;Process access of &lt;code&gt;lsass.exe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The structural cost across all three is the same: code execution as SYSTEM on a domain controller. Read that requirement slowly. In a mature enterprise with even a basic tiered-administration model -- no interactive logon to DCs from workstations, &lt;a href=&quot;https://paragmali.com/blog/rdp-authentication-26-years/&quot; rel=&quot;noopener&quot;&gt;restricted-admin RDP&lt;/a&gt;, Privileged Access Workstations for Domain Admin sessions, Protected Users group membership for Tier Zero principals -- DCs are the most defended boundary in the network. An attacker who has crossed that boundary has, in operational terms, already won. The credential dump is the trophy lap.&lt;/p&gt;

flowchart TD
    Start[Attacker foothold&lt;br /&gt;on workstation]
    Start --&amp;gt; VSS[G1a: VSS snapshot&lt;br /&gt;+ offline parse]
    Start --&amp;gt; IFM[G1b: ntdsutil IFM&lt;br /&gt;create full]
    Start --&amp;gt; Inject[G1c: LSASS inject&lt;br /&gt;on DC]
    VSS --&amp;gt; Gate[SYSTEM on DC]
    IFM --&amp;gt; Gate
    Inject --&amp;gt; Gate
    Gate --&amp;gt; Creds[All domain credentials&lt;br /&gt;NT hashes, Kerberos keys, krbtgt]
&lt;p&gt;This is what made the closed-population design assumption survive its first fifteen years. The protocol&apos;s design was open to abuse from any joined workstation that held the rights triad, but nobody noticed because the cheaper attack road -- compromise a DC, parse the database offline -- still passed through a defended chokepoint. The ACL on the Domain NC was nowhere on a defender&apos;s risk register, because no offensive tooling existed that treated the ACL as the gate.&lt;/p&gt;
&lt;p&gt;There was a question waiting to be asked, though. &lt;em&gt;What if you could ask the DC to send you the credentials, using a protocol the DC already speaks fluently with its peers?&lt;/em&gt; The protocol&apos;s wire format is published. Microsoft Learn hosts the IDL. The DCs trust each other&apos;s calls by ACL. The only missing piece was a client implementation that any attacker could run from any joined machine.&lt;/p&gt;
&lt;p&gt;In August 2015 the missing piece arrived.&lt;/p&gt;
&lt;h2&gt;4. Generation by Generation&lt;/h2&gt;
&lt;p&gt;August 11, 2015, 01:27 Central European Time. Benjamin Delpy commits 47,132 insertions to the Mimikatz repository in a single push titled &lt;em&gt;&quot;DCSync in mimikatz &amp;amp; for XP/2003.&quot;&lt;/em&gt; The diff introduces four new modules -- &lt;code&gt;kull_m_rpc_drsr.c/.h&lt;/code&gt; and &lt;code&gt;kull_m_rpc_ms-drsr.h/_c.c&lt;/code&gt; -- generated from the [MS-DRSR] IDL. They are an MS-DRSR client surface, slotted into &lt;code&gt;kuhl_m_lsadump.c&lt;/code&gt; as the new &lt;code&gt;lsadump::dcsync&lt;/code&gt; command [@mimikatz-dcsync-commit][@mimikatz-repo]. Vincent Le Toux is credited as co-author.&lt;/p&gt;
&lt;p&gt;Six weeks later Sean Metcalf writes the canonical operator post and presents the technique at DerbyCon V on Friday, September 25, 2015, in the Track 1 (Break Me) slot from 3:00 to 3:50 pm [@sean-metcalf-dcsync-2015][@sean-metcalf-derbycon-2015]. The closed-population assumption shatters in a weekend.&lt;/p&gt;

A commit hash widely cited in operator forums for the DCSync introduction -- `79b3577aed999baac0352cb1ba3a5f86b6d29f34`, dated 2015-07-20 -- does not exist in the Mimikatz repository. A `git --no-pager log --all` against a fresh clone returns `fatal: bad object` for that hash; the GitHub commit URL returns 404; the GitHub API returns 422. The actual introducing commit is `7717b7a7173fa6a6b6566bbbc3e7372b464d988f`, authored by Benjamin DELPY at 2015-08-11 01:27:13 +0200, with the subject line *&quot;DCSync in mimikatz &amp;amp; for XP/2003&quot;* [@mimikatz-dcsync-commit]. Sean Metcalf&apos;s contemporary writeup at ADSecurity confirms August 2015 as the release month [@sean-metcalf-dcsync-2015]. The lesson for verifying any third-party claim about a Mimikatz commit is the same lesson Stage 1 of this article&apos;s research pipeline applied: clone the repo, run `git show`.
&lt;p&gt;What follows is the story of four generations of attacker approaches against this protocol, each motivated by the operational limit of the previous one.&lt;/p&gt;
&lt;h3&gt;Generation 2: DCSync (2015-08-11 onward)&lt;/h3&gt;
&lt;p&gt;Mimikatz becomes a DRSUAPI client. Operator invocation is one line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lsadump::dcsync /domain:contoso.local /user:krbtgt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Behind that line, six wire steps fire:&lt;/p&gt;

sequenceDiagram
    participant A as Attacker workstation
    participant DC as Target DC (DRSUAPI)
    A-&amp;gt;&amp;gt;DC: 1. resolve target DC by domain
    A-&amp;gt;&amp;gt;DC: 2. IDL_DRSBind (interface UUID DRSUAPI)
    DC--&amp;gt;&amp;gt;A: 3. bind reply (handle, session key)
    A-&amp;gt;&amp;gt;DC: 4. IDL_DRSGetNCChanges (opnum 3, MTX_ADDR DN, EXOP_REPL_OBJ)
    DC--&amp;gt;&amp;gt;A: 5. DRS_MSG_GETCHGREPLY (encrypted secret attributes)
    A-&amp;gt;&amp;gt;A: 6. decrypt with session key, emit NT hash and Kerberos keys
&lt;p&gt;The wire format is one round trip per principal. To dump every account in the domain, Mimikatz&apos;s &lt;code&gt;/all /csv&lt;/code&gt; mode iterates the request server-side via the same opnum with paginating up-to-date vectors. Per-call wire size is a few kilobytes for a single user; full-domain bulk dumps run to tens of megabytes. Wall-clock time is dominated by network latency to the target DC [@sean-metcalf-dcsync-2015][@trellix-silent-domain-hijack].&lt;/p&gt;
&lt;p&gt;The Generation-1 precondition is gone. The attack runs from any joined workstation. The Generation-1 host artifacts -- VSS events, IFM staging directories, multi-megabyte file copies -- all disappear. The only on-the-wire signature is &lt;em&gt;&quot;an &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; call from an IP that is not a domain controller&quot;&lt;/em&gt; -- which has to be detected at the protocol layer, not the host layer.&lt;/p&gt;
&lt;p&gt;Sean Metcalf&apos;s 2015 post named the detection recipe in the same breath as the attack: &lt;em&gt;&quot;Configure IDS to trigger if DsGetNCChange request originates an IP not on the &apos;Replication Allow List&apos; ...&quot;&lt;/em&gt; [@sean-metcalf-dcsync-2015]. Every network detection rule in this space, including Microsoft&apos;s own ATA &quot;Unusual Protocol Implementation&quot; category two years later, descends from that one sentence [@ata-v17-release-notes].&lt;/p&gt;
&lt;p&gt;DCSync is read-only. The ACL pair the attack exploits does not include directory-write rights. An attacker who wants to plant SID-history backdoors, modify &lt;code&gt;userAccountControl&lt;/code&gt; flags, or write to AdminSDHolder needs a different primitive. The same trust loophole that gave them read access turns out to support a symmetric write side.&lt;/p&gt;
&lt;h3&gt;Generation 3: DCShadow (2018-01-24)&lt;/h3&gt;
&lt;p&gt;January 23-24, 2018. Benjamin Delpy and Vincent Le Toux present at BlueHat IL in Tel Aviv. The talk is titled &lt;em&gt;&quot;Active Directory: What can make your million dollar SIEM go blind?&quot;&lt;/em&gt; [@youtube-bluehat-2018-dcshadow]. Four days later, on January 27, 2018, Delpy pushes the mainline merge to Mimikatz with commit &lt;code&gt;ab18bd1&lt;/code&gt;, subject &lt;em&gt;&quot;Pushing @vletoux DCShadow in current branch with some adaptations&quot;&lt;/em&gt; [@mimikatz-dcshadow-commit].&lt;/p&gt;
&lt;p&gt;Vincent Le Toux contributed the original implementation; the BlueHat IL talk shared joint Delpy/Le Toux billing; the Mimikatz mainline merge commit &lt;code&gt;ab18bd103a5cd7e26fb8d475c5ea0157d6633ca9&lt;/code&gt; is dated 2018-01-27 01:37:55 +0100, four days after the conference disclosure. Le Toux is the same author behind PingCastle&apos;s posture-assessment tooling and the canonical &lt;code&gt;dcshadow.com&lt;/code&gt; reference site [@mimikatz-dcshadow-commit][@dcshadow-com].&lt;/p&gt;
&lt;p&gt;DCShadow inverts DCSync. Where DCSync makes the attacker a DRSUAPI client, DCShadow makes the attacker a DRSUAPI &lt;em&gt;server&lt;/em&gt;. The mechanism: temporarily register an &lt;code&gt;nTDSDSA&lt;/code&gt; object plus the associated SPNs in the Configuration NC; signal to a legitimate DC that the new &quot;DC&quot; wants to push changes via &lt;code&gt;IDL_DRSReplicaAdd&lt;/code&gt; followed by &lt;code&gt;IDL_DRSReplicaSync&lt;/code&gt;; the legitimate DC pulls the attacker&apos;s pre-staged writes through the replication channel as if they were legitimate peer replication; deregister to clean up [@mitre-t1207][@dcshadow-com].&lt;/p&gt;

sequenceDiagram
    participant A as Attacker (rogue DC)
    participant Cfg as Configuration NC
    participant T as Target DC
    A-&amp;gt;&amp;gt;Cfg: 1. create nTDSDSA + server object
    A-&amp;gt;&amp;gt;Cfg: 2. add SPNs (GC, DRS UUID) to machine account
    A-&amp;gt;&amp;gt;T: 3. IDL_DRSReplicaAdd (dsaSrc = attacker)
    T-&amp;gt;&amp;gt;A: 4. IDL_DRSGetNCChanges callback (target pulls)
    A--&amp;gt;&amp;gt;T: 5. staged writes returned as replication payload
    A-&amp;gt;&amp;gt;T: 6. IDL_DRSReplicaDel
    A-&amp;gt;&amp;gt;Cfg: 7. delete nTDSDSA, remove SPNs

A directory operation that does not generate the standard Event ID 4662 / 4738 / 5136 object-modification events that the Domain Services Auditing subsystem emits for normal writes. Legitimate DC-to-DC replication is SACL-silent by design -- the audit subsystem intentionally suppresses change events on the replication channel to avoid drowning every DC in audit traffic on every directory change. DCShadow writes are SACL-silent because they ride the same channel.
&lt;p&gt;That last design fact is the entire point of the talk title. A SIEM watching object-modification events sees nothing when a DCShadow write lands, because the modifications arrive on the replication channel that the SIEM intentionally ignores as routine DC chatter. The original 2018 framing -- &quot;your million-dollar SIEM goes blind&quot; -- was correct for SIEMs that monitored only object-modification events. We will see in §6 how that framing has aged.&lt;/p&gt;
&lt;p&gt;DCShadow is &lt;em&gt;write&lt;/em&gt; capability. An attacker who reaches it can plant SID-history backdoors (write &lt;code&gt;S-1-5-21-...-519&lt;/code&gt; for Enterprise Admins into a low-privileged account&apos;s &lt;code&gt;sIDHistory&lt;/code&gt;), modify &lt;code&gt;userAccountControl&lt;/code&gt; to clear &lt;code&gt;ACCOUNTDISABLE&lt;/code&gt; on dormant high-privilege accounts, add ACEs to AdminSDHolder (which then propagate via the SDProp process to every protected admin account every 60 minutes), or set &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; on a target computer to enable resource-based constrained delegation chains.&lt;/p&gt;
&lt;h3&gt;Generation 4: Permission-graph attacks (2018-present)&lt;/h3&gt;
&lt;p&gt;By 2018 the attack-side question had shifted. &lt;em&gt;Holding the rights triad directly&lt;/em&gt; was no longer the interesting precondition; the interesting question was how to reach it transitively, through whatever chain of ACL delegations a real-world domain happened to contain. The umbrella term that emerged is permission-graph attack. Its terminal edge is still DCSync; its novelty is the path that gets you to the terminal.&lt;/p&gt;
&lt;p&gt;Three primitives anchor this generation. Elad Shamir&apos;s &lt;em&gt;Wagging the Dog&lt;/em&gt; (January 28, 2019) showed how writing &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt; on a target computer object enables S4U2Self plus S4U2Proxy impersonation of any user to that computer [@shenaniganslabs-wagging-the-dog]. Shamir&apos;s &lt;em&gt;Shadow Credentials&lt;/em&gt; (June 21, 2021) demonstrated that writing &lt;code&gt;msDS-KeyCredentialLink&lt;/code&gt; on a target account adds an attacker-controlled certificate trust, enabling Kerberos PKINIT authentication as that account without resetting its password [@eladshamir-shadow-credentials]. And Sean Metcalf&apos;s earlier work on AdminSDHolder template abuse showed that writing the AdminSDHolder ACL causes SDProp to propagate the new ACL onto every protected admin account every 60 minutes -- self-healing persistence that survives defender cleanup [@sean-metcalf-adminsdholder].&lt;/p&gt;
&lt;p&gt;The unifying observation: DCSync is a terminal in a permission graph. The graph&apos;s nodes are AD principals; its edges are individual access-control entries (&lt;code&gt;WriteDACL&lt;/code&gt;, &lt;code&gt;WriteOwner&lt;/code&gt;, &lt;code&gt;GenericAll&lt;/code&gt;, &lt;code&gt;WriteProperty&lt;/code&gt;, &lt;code&gt;AddMember&lt;/code&gt;, &lt;code&gt;ForceChangePassword&lt;/code&gt;). Whoever can traverse the graph to the rights triad on the domain root has DCSync transitively. The attacker&apos;s job is no longer to invoke &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt;; it is to find the shortest path through the graph from a foothold to the rights triad. The defender&apos;s mirror job is to enumerate all paths into the rights triad and either prune them or monitor them.&lt;/p&gt;

gantt
    title Domain replication attack class evolution
    dateFormat YYYY-MM-DD
    axisFormat %Y
    section Attack
    Gen 1 NTDS.dit theft           :a1, 2000-02-17, 2015-08-11
    Gen 2 DCSync                   :active, a2, 2015-08-11, 2026-12-31
    Gen 3 DCShadow                 :active, a3, 2018-01-24, 2026-12-31
    Gen 4 Permission-graph chains  :active, a4, 2018-06-01, 2026-12-31
    section Defense
    BloodHound 1.0 DEF CON 24     :d1, 2016-08-06, 30d
    ATA 1.7 release                :d2, 2017-04-01, 30d
    Azure ATP DCShadow alerts      :d3, 2018-07-24, 30d
    Azure ATP rebrand to MDI       :d4, 2020-09-22, 30d
    BloodHound v6.0                :d5, 2024-09-30, 30d
    BloodHound v6.3 Butterfly      :d6, 2024-12-09, 30d
    BloodHound v8.0 OpenGraph      :d7, 2025-07-29, 30d
    Trellix NDR Silent Hijack      :d8, 2025-12-08, 30d
&lt;p&gt;To make the read-side access check decision concrete -- and to expose how thin it actually is -- here is the logic of the gate written as a runnable function. This is pseudocode for the &lt;em&gt;decision&lt;/em&gt;, not the protocol bytes:&lt;/p&gt;
&lt;p&gt;{`
// Illustrative model of the MS-DRSR access check on IDL_DRSGetNCChanges.
// Returns &quot;secrets returned&quot; or &quot;ACCESS_DENIED&quot; given a caller&apos;s effective
// rights on the naming-context root.
function dcsyncAccessCheck(callerRights, ncRootDn, requestedAttrs) {
  const GET_CHANGES         = &apos;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2&apos;;
  const GET_CHANGES_ALL     = &apos;1131f6ad-9c07-11d1-f79f-00c04fc2dcd2&apos;;
  const GET_CHANGES_FILTERED = &apos;89e95b76-444d-4c62-991a-0facbeda640c&apos;;&lt;/p&gt;
&lt;p&gt;  const SECRET_ATTRS = new Set([&apos;unicodePwd&apos;, &apos;dBCSPwd&apos;,
    &apos;ntPwdHistory&apos;, &apos;lmPwdHistory&apos;, &apos;supplementalCredentials&apos;]);
  const wantsSecrets = requestedAttrs.some(a =&amp;gt; SECRET_ATTRS.has(a));&lt;/p&gt;
&lt;p&gt;  // Baseline read requires GetChanges.
  if (!callerRights.has(GET_CHANGES)) return &apos;ACCESS_DENIED&apos;;
  // Secret attributes require GetChangesAll.
  if (wantsSecrets &amp;amp;&amp;amp; !callerRights.has(GET_CHANGES_ALL))
    return &apos;ACCESS_DENIED&apos;;&lt;/p&gt;
&lt;p&gt;  // Notice what is NOT checked: caller&apos;s SPN, machine-group membership,
  // ticket service, source IP. The access gate is the ACL, full stop.
  return &apos;secrets returned&apos;;
}&lt;/p&gt;
&lt;p&gt;const attacker = new Set([
  &apos;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2&apos;,
  &apos;1131f6ad-9c07-11d1-f79f-00c04fc2dcd2&apos;,
]);
console.log(dcsyncAccessCheck(attacker, &apos;DC=contoso,DC=local&apos;,
  [&apos;unicodePwd&apos;, &apos;ntPwdHistory&apos;]));
`}&lt;/p&gt;
&lt;p&gt;Four generations, eleven years, no Generation 5 in sight. What is the single insight that lets all of this exist, and why has nobody patched it?&lt;/p&gt;
&lt;h2&gt;5. There Is No DC Check&lt;/h2&gt;
&lt;p&gt;The whole structural error of this protocol is one missing question. Specification [MS-DRSR] §4.1.10 defines the access check on &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; as: does the calling principal hold the rights triad on the naming context being replicated? [@ms-drsr-spec] That is the whole gate. There is no second check that asks &quot;is the caller&apos;s service principal name a domain-controller SPN?&quot; or &quot;is the caller&apos;s machine account in the &lt;code&gt;Domain Controllers&lt;/code&gt; group?&quot; or &quot;was the caller&apos;s Kerberos service ticket issued for a DC service?&quot; The spec is empirically and literally just an ACL check on the NC root.&lt;/p&gt;
&lt;p&gt;The empirical proof that a non-DC client succeeds lives in Mimikatz&apos;s &lt;code&gt;kuhl_m_lsadump.c&lt;/code&gt; and its DRSUAPI client surface in &lt;code&gt;kull_m_rpc_drsr*&lt;/code&gt; [@mimikatz-repo]. Mimikatz is software running on a workstation. It binds to the DRSUAPI interface UUID, calls &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt;, and the call returns. The protocol&apos;s behavior is correct by specification. The security model is the bug.&lt;/p&gt;

A major feature added to Mimkatz in August 2015 is &apos;DCSync&apos; which effectively &apos;impersonates&apos; a Domain Controller and requests account password data from the targeted Domain Controller. DCSync was written by Benjamin Delpy and Vincent Le Toux. -- Sean Metcalf, ADSecurity, September 2015 [@sean-metcalf-dcsync-2015]
&lt;p&gt;Read Metcalf&apos;s verb carefully: &lt;em&gt;impersonates&lt;/em&gt;. The scare quotes are doing work. The Mimikatz client is not pretending to be a DC in any cryptographic sense. It is not forging a machine-account ticket. It is not spoofing an SPN. It is not bypassing any signature check.&lt;/p&gt;
&lt;p&gt;It is honestly making an authenticated call as the principal it actually is -- some user or service account that happens to hold the rights triad -- and the protocol honestly responds because its gate is satisfied. The &quot;impersonation&quot; framing is operator vocabulary borrowed from the social model the protocol was written under.&lt;/p&gt;
&lt;p&gt;The 1999 designers assumed only DCs would speak. By that social contract, anyone who speaks must be a DC. The spec encoded the social contract by way of &lt;em&gt;not encoding it at all&lt;/em&gt;. The ACL was the whole gate because, in 1999, the ACL was always satisfied by something that was always a DC.&lt;/p&gt;

flowchart TD
    Start[IDL_DRSGetNCChanges request arrives]
    Start --&amp;gt; Q1{&quot;Caller holds rights triad&lt;br /&gt;on the NC root?&quot;}
    Q1 -- yes --&amp;gt; Return[Return encrypted&lt;br /&gt;secret attributes]
    Q1 -- no --&amp;gt; Deny[ERROR_DS_DRA_ACCESS_DENIED]
    Start -.-&amp;gt; Absent[&quot;What the check does NOT ask:&lt;br /&gt;Is the caller a domain controller?&lt;br /&gt;Is the SPN a DC SPN?&lt;br /&gt;Is the machine in Domain Controllers?&quot;]
    Absent -.-&amp;gt; Nothing[no second gate exists]
&lt;p&gt;This is the article&apos;s intellectual fulcrum. The 1999 closed-population assumption -- only DCs speak this protocol -- survives in 2026 as an open-population reality (anyone with the rights speaks it), and the closed-population assumption is nowhere written down in the access-check code. The fix that would close the model would require a second gate. The spec did not write one. The implementation cannot synthesize one without breaking every legitimate consumer that already operates without one (more on this in §8).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The protocol&apos;s design is correct. The security model is the bug. No patch can fix this without breaking Active Directory replication itself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is a temptation, on first encountering this, to assume the missing gate is an oversight that Microsoft will eventually fix. That intuition is wrong, and it is wrong for a deeper reason than &quot;Microsoft has not gotten around to it.&quot; If the protocol is the bug and the protocol cannot be amended, what defenses can possibly work in 2026? That question carries us into the next section.&lt;/p&gt;
&lt;h2&gt;6. What 2026 Actually Ships Against This&lt;/h2&gt;
&lt;p&gt;If the protocol cannot be fixed, the defender&apos;s question is no longer &quot;how do I prevent DCSync?&quot; but &quot;which layer catches which class of attempt?&quot; Four production detection layers ship against this attack class in 2026. None of them is individually sufficient. A fifth layer -- the architectural one that would close the structural error -- does not exist and is not coming.&lt;/p&gt;
&lt;h3&gt;Posture: enumerate who holds the rights&lt;/h3&gt;
&lt;p&gt;The posture layer reads the static ACL on the Domain NC root and surfaces every principal that holds any of the three rights. Microsoft Defender for Identity ships this as an Accounts security posture assessment family, computed continuously from MDI&apos;s per-DC sensors [@mdi-security-posture-accounts]. Vincent Le Toux&apos;s PingCastle exposes it as the &lt;em&gt;C-DCSync&lt;/em&gt; finding in its critical-risks section. Tenable Identity Exposure exposes it as an indicator of exposure. Christopher Keim&apos;s 2025 practitioner guide documents the PowerShell pattern that AD administrators without a posture-tool license can run on demand [@keim-dcsync-rights]:&lt;/p&gt;
&lt;p&gt;{`&lt;/p&gt;
Illustrative model of the posture-layer check.
In production, replace SAMPLE_ACL with output from Get-Acl in PowerShell
or python-ldap against the live Domain NC root.
&lt;p&gt;GET_CHANGES          = &apos;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2&apos;
GET_CHANGES_ALL      = &apos;1131f6ad-9c07-11d1-f79f-00c04fc2dcd2&apos;
GET_CHANGES_FILTERED = &apos;89e95b76-444d-4c62-991a-0facbeda640c&apos;
TRIAD = {GET_CHANGES, GET_CHANGES_ALL, GET_CHANGES_FILTERED}&lt;/p&gt;
&lt;p&gt;DEFAULTS = {
    &apos;BUILTIN\\Administrators&apos;,
    &apos;CONTOSO\\Domain Controllers&apos;,
    &apos;CONTOSO\\Domain Admins&apos;,
    &apos;CONTOSO\\Enterprise Admins&apos;,
    &apos;NT AUTHORITY\\ENTERPRISE DOMAIN CONTROLLERS&apos;,
}&lt;/p&gt;
&lt;p&gt;SAMPLE_ACL = [
    {&apos;principal&apos;: &apos;CONTOSO\\Domain Admins&apos;,     &apos;right&apos;: GET_CHANGES},
    {&apos;principal&apos;: &apos;CONTOSO\\Domain Admins&apos;,     &apos;right&apos;: GET_CHANGES_ALL},
    {&apos;principal&apos;: &apos;CONTOSO\\Enterprise Admins&apos;, &apos;right&apos;: GET_CHANGES},
    {&apos;principal&apos;: &apos;CONTOSO\\Enterprise Admins&apos;, &apos;right&apos;: GET_CHANGES_ALL},
    {&apos;principal&apos;: &apos;CONTOSO\\backup_svc_2017&apos;,   &apos;right&apos;: GET_CHANGES},
    {&apos;principal&apos;: &apos;CONTOSO\\backup_svc_2017&apos;,   &apos;right&apos;: GET_CHANGES_ALL},
    {&apos;principal&apos;: &apos;CONTOSO\\MSOL_a1b2c3&apos;,       &apos;right&apos;: GET_CHANGES},
    {&apos;principal&apos;: &apos;CONTOSO\\MSOL_a1b2c3&apos;,       &apos;right&apos;: GET_CHANGES_ALL},
]&lt;/p&gt;
&lt;p&gt;residual = {}
for ace in SAMPLE_ACL:
    if ace[&apos;right&apos;] in TRIAD and ace[&apos;principal&apos;] not in DEFAULTS:
        residual.setdefault(ace[&apos;principal&apos;], set()).add(ace[&apos;right&apos;])&lt;/p&gt;
&lt;p&gt;for principal, rights in residual.items():
    print(f&quot;{principal}: {len(rights)} of 3 replication rights&quot;)
`}&lt;/p&gt;
&lt;p&gt;The residual set is the operational unit of work. In a freshly-installed domain it is empty. In a ten-year-old forest with a history of mergers and migrations it typically contains five to twenty entries -- a mix of legitimately delegated identity-sync products and forgotten service accounts from projects nobody on the current operations team remembers.&lt;/p&gt;

In Microsoft&apos;s Enhanced Security Administrative Environment and the BloodHound conventions, the set of principals and assets whose compromise yields domain-wide control. The `krbtgt` account, members of `Domain Admins` and `Enterprise Admins`, the Entra ID Connect MSOL_ sync account, and any non-default principal holding the rights triad on the domain root are all Tier Zero by construction.

The Microsoft Entra ID (formerly Azure AD) Connect synchronization service account, created on-premises during Entra Connect installation. The account name uses an `MSOL_` prefix followed by a hex suffix. It legitimately holds the rights triad on the Domain NC root because it must replicate password hashes to the cloud directory; treating it as Tier Zero is the standard hardening recommendation.

Microsoft Defender for Identity&apos;s (and ATA&apos;s earlier) internal baseline of which computers in the domain legitimately speak DRSUAPI to which DCs. Incoming `IDL_DRSGetNCChanges` requests are matched against this baseline; a request from a source outside the list fires the External ID 2006 alert.
&lt;p&gt;An earlier scope document for this article quoted an MDI assessment titled verbatim &lt;em&gt;&quot;Remove non-admin accounts with DCSync permissions.&quot;&lt;/em&gt; That exact title does not appear on the live MDI Accounts security-posture-assessment page in 2026 [@mdi-security-posture-accounts][@mdi-security-posture-hybrid]. The surface exists -- MDI&apos;s Accounts and Hybrid security posture-assessment families together cover non-default principals with replication rights -- but the verbatim title was not reproducible.&lt;/p&gt;
&lt;h3&gt;Behavioral: catch the act after it fires&lt;/h3&gt;
&lt;p&gt;The behavioral layer watches network traffic and event logs for the act of DCSync or DCShadow as it happens. Microsoft&apos;s first-party stack lives in Defender for Identity and ships three canonical alerts [@mdi-alerts-classic]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;External ID 2006 -- &quot;Suspected DCSync attack (replication of directory services).&quot;&lt;/strong&gt; Credential Access (TA0006), Persistence (TA0003). Technique T1003.006. Severity High. Trigger: a replication request is initiated from a computer that is not a domain controller.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;External ID 2028 -- &quot;Suspected DCShadow attack (domain controller promotion).&quot;&lt;/strong&gt; Defense Evasion (TA0005). Technique T1207. Trigger: a machine in the network tries to register as a rogue domain controller.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;External ID 2029 -- &quot;Suspected DCShadow attack (domain controller replication request).&quot;&lt;/strong&gt; Defense Evasion (TA0005). Technique T1207. Trigger: a suspicious replication request is generated against a genuine domain controller, indicative of DCShadow.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The product lineage is Microsoft Advanced Threat Analytics 1.7 (April 2017, where DCSync was covered under the umbrella &quot;Unusual Protocol Implementation enhancements&quot; detection category [@ata-v17-release-notes]); Azure Advanced Threat Protection (2018, where Tali Ash&apos;s July 24, 2018 Microsoft Tech Community post announced the two named DCShadow detections that became 2028 and 2029 [@tali-ash-azure-atp-dcshadow]); and Defender for Identity (the Microsoft Ignite 2020 rebrand, week of September 22-24, 2020 [@rcpmag-defender-rebrand]). The detection content carries forward unchanged across product renamings; what changes is the portal it surfaces in [@mdi-whats-new].&lt;/p&gt;
&lt;p&gt;Open-source SIEM equivalents implement the same detection via Event ID 4662 on the domain object. The Sigma rule &lt;em&gt;Mimikatz DC Sync&lt;/em&gt; (id &lt;code&gt;611eab06-a145-4dfa-a295-3ccc5c20f59a&lt;/code&gt;) fires on Event ID 4662 where &lt;code&gt;Properties&lt;/code&gt; contains any of the three rights GUIDs or the literal string &lt;em&gt;Replicating Directory Changes All&lt;/em&gt;, with &lt;code&gt;AccessMask=0x100&lt;/code&gt; [@sigma-rule-dcsync]. Splunk&apos;s parallel detection &lt;em&gt;Windows AD Replication Request Initiated by User Account&lt;/em&gt; (rule &lt;code&gt;51307514-1236-49f6-8686-d46d93cc2821&lt;/code&gt;) implements the equivalent SPL search with the same MITRE T1003.006 annotation and the same known-false-positive list (Azure AD Connect, &lt;code&gt;dcdiag.exe /Test:Replications&lt;/code&gt;) [@splunk-research-dcsync].&lt;/p&gt;
&lt;p&gt;The SACL-event detection layer (Sigma + Splunk + every other SIEM-side implementation) requires that the operator first enable Advanced Security Audit policy &lt;code&gt;Audit Directory Services Access&lt;/code&gt; under &lt;code&gt;DS Access&lt;/code&gt;, with SACLs on the domain root auditing the three rights against &lt;code&gt;Everyone&lt;/code&gt;, &lt;code&gt;Domain Computers&lt;/code&gt;, and &lt;code&gt;Domain Controllers&lt;/code&gt;. A fresh-install AD does not have these SACLs by default [@splunk-research-dcsync]. The detection rule&apos;s documentation calls out the prerequisite explicitly; many operators discover it only after wondering why their Splunk dashboard is silent.&lt;/p&gt;
&lt;h3&gt;Network: NDR on the DRSUAPI interface&lt;/h3&gt;
&lt;p&gt;The network layer parses DCE/RPC traffic on the wire, identifies the DRSUAPI interface by its UUID, and fires when an &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; call originates from a source outside the legitimate-DC baseline. The canonical 2025 reference is Trellix Advanced Research Center&apos;s &lt;em&gt;&quot;Silent Domain Hijack: Uncovering the DCSync Attack and Detecting with Trellix NDR&quot;&lt;/em&gt;, published in week 50 of 2025 [@trellix-silent-domain-hijack]. Equivalent capability ships in Microsoft Defender for Identity&apos;s network analytics layer (the same sensor that powers External ID 2006) [@mdi-alerts-classic].&lt;/p&gt;
&lt;p&gt;The Trellix writeup is explicit about the architecture: &lt;em&gt;&quot;Trellix NDR detects replication protocol abuse by analyzing abnormal DCE/RPC and MS-DRSR traffic. It detects DCSync-like behavior when replication requests are sent from non-DC hosts or unusual users&quot;&lt;/em&gt; [@trellix-silent-domain-hijack]. The detection is independent of host-side telemetry, so it survives EDR tampering and works in environments where a DC is un-sensored from MDI&apos;s perspective.&lt;/p&gt;
&lt;h3&gt;Graph: BloodHound traverses the permission graph&lt;/h3&gt;
&lt;p&gt;The graph layer was built specifically for Generation 4. BloodHound, originally released by Andy Robbins, Rohan Vazarkar, and Will Schroeder at DEF CON 24 on August 6, 2016, models &lt;em&gt;&quot;you have DCSync rights to the domain&quot;&lt;/em&gt; as a directed edge from a principal to the domain node, computed by combining the separately-collected &lt;code&gt;GetChanges&lt;/code&gt; and &lt;code&gt;GetChangesAll&lt;/code&gt; ACEs through nested-group membership [@wald0-bloodhound-intro][@defcon24-bloodhound-pdf][@bloodhound-edge-dcsync]. An operator queries &lt;em&gt;&quot;shortest path from any compromised principal to the DCSync edge into a Domain node&quot;&lt;/em&gt; and gets back every transitive route into the rights triad.&lt;/p&gt;
&lt;p&gt;The 2024-2026 release cadence is dense and matters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BloodHound v6.0 (September 30, 2024)&lt;/strong&gt; improved logic for identifying and creating complex edges requiring multiple permissions, including DCSync, when &lt;code&gt;Authenticated Users&lt;/code&gt; or &lt;code&gt;Everyone&lt;/code&gt; groups are involved [@bloodhound-v6-0-release-notes]. This closed a long-standing blind spot in which rights granted to a wildcard principal (the worst kind of delegation drift, often dating from compatibility settings in pre-2003 forests) were not surfaced as DCSync edges.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BloodHound v6.3 (December 9, 2024)&lt;/strong&gt; introduced the &lt;em&gt;Butterfly&lt;/em&gt; algorithm -- bi-directional risk analysis. Where the historical query was &lt;em&gt;&quot;which principals can attack this target?&quot;&lt;/em&gt;, Butterfly adds &lt;em&gt;&quot;which targets can be attacked from this compromised principal?&quot;&lt;/em&gt; SpecterOps describes the algorithm in their blog post &lt;em&gt;Unwrapping BloodHound v6.3 with Impact Analysis&lt;/em&gt;: &lt;em&gt;&quot;This is a massive upgrade to BloodHound Enterprise&apos;s risk analysis capability with a new algorithm we call &apos;Butterfly&apos;&quot;&lt;/em&gt; [@specterops-butterfly-blog][@bloodhound-v6-3-release-notes].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BloodHound v8.0 (July 29, 2025)&lt;/strong&gt; introduced &lt;em&gt;OpenGraph&lt;/em&gt;, generalizing the graph engine to model attack paths across non-AD systems (GitHub, 1Password, NPM, Snowflake) using the same Cypher front-end. The DCSync edge remains AD-specific; OpenGraph&apos;s relevance is that hybrid-cloud principals can now be modeled end-to-end [@bloodhound-v8-0-release-notes].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The graph layer is the only one that catches multi-hop chains to the rights triad. A principal A with &lt;code&gt;GenericAll&lt;/code&gt; on group B, where B has the DCSync triad, is invisible to MDI&apos;s posture assessment but stands out as a one-hop path in BloodHound.&lt;/p&gt;

flowchart TD
    subgraph Posture[Posture layer]
        P1[MDI Accounts assessments]
        P2[PingCastle C-DCSync]
        P3[Keim PowerShell pattern]
    end
    subgraph Behavioral[Behavioral layer]
        B1[MDI 2006 / 2028 / 2029]
        B2[Sigma 611eab06]
        B3[Splunk 51307514]
    end
    subgraph Network[Network layer NDR]
        N1[Trellix NDR]
        N2[MDI per-DC sensor]
        N3[CrowdStrike DCE/RPC IoA]
    end
    subgraph Graph[Graph layer]
        G1[BloodHound DCSync edge]
        G2[v6.3 Butterfly Impact]
        G3[v8.0 OpenGraph]
    end
    P1 --&amp;gt; SOC[SOC alert queue]
    P2 --&amp;gt; SOC
    P3 --&amp;gt; SOC
    B1 --&amp;gt; SOC
    B2 --&amp;gt; SOC
    B3 --&amp;gt; SOC
    N1 --&amp;gt; SOC
    N2 --&amp;gt; SOC
    N3 --&amp;gt; SOC
    G1 --&amp;gt; SOC
    G2 --&amp;gt; SOC
    G3 --&amp;gt; SOC
&lt;p&gt;The full layer-by-layer comparison is the load-bearing matrix of the entire 2026 SOTA:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What it inputs&lt;/th&gt;
&lt;th&gt;What it detects&lt;/th&gt;
&lt;th&gt;What it misses&lt;/th&gt;
&lt;th&gt;False-positive class&lt;/th&gt;
&lt;th&gt;Detection latency&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Posture&lt;/td&gt;
&lt;td&gt;NC-root ACL&lt;/td&gt;
&lt;td&gt;Direct grant of the rights triad to a non-default principal&lt;/td&gt;
&lt;td&gt;Multi-hop transitive paths; legitimate-principal abuse&lt;/td&gt;
&lt;td&gt;Identity-sync products (Entra Connect MSOL_, third-party HR-IDM); legitimately delegated backup agents&lt;/td&gt;
&lt;td&gt;24h score recomputation; ACE changes near real time&lt;/td&gt;
&lt;td&gt;Built in to MDI; PowerShell variant free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Event ID 4662 or sensor-captured DRSUAPI traffic&lt;/td&gt;
&lt;td&gt;The act of DCSync, or the DCShadow registration / replication, after it happens&lt;/td&gt;
&lt;td&gt;Pre-attack staging; compromised-DC speaker; un-sensored DC blind spot&lt;/td&gt;
&lt;td&gt;Azure AD Connect syncs; &lt;code&gt;dcdiag.exe /Test:Replications&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Minutes (alert &quot;after the fact&quot;)&lt;/td&gt;
&lt;td&gt;MDI license; Sigma / Splunk free with SACL config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;DCE/RPC packet capture&lt;/td&gt;
&lt;td&gt;Wire signature of &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; from non-DC source&lt;/td&gt;
&lt;td&gt;Encrypted RPC payloads (per-principal granularity); sub-DC replicas misclassified&lt;/td&gt;
&lt;td&gt;Same as behavioral plus Samba-DC peers&lt;/td&gt;
&lt;td&gt;Seconds (passive inspection)&lt;/td&gt;
&lt;td&gt;Commercial NDR appliance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph&lt;/td&gt;
&lt;td&gt;LDAP-collected ACEs and group nesting&lt;/td&gt;
&lt;td&gt;Multi-hop graph paths that could reach the rights triad&lt;/td&gt;
&lt;td&gt;Net-new ACEs created after the last collection&lt;/td&gt;
&lt;td&gt;Stale data showing principals that no longer hold the right&lt;/td&gt;
&lt;td&gt;Hours to weeks (collection cadence)&lt;/td&gt;
&lt;td&gt;BloodHound CE free; BHE commercial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architectural (un-shipped)&lt;/td&gt;
&lt;td&gt;TPM-attested DC machine identity&lt;/td&gt;
&lt;td&gt;Pre-empts non-DC speaker entirely&lt;/td&gt;
&lt;td&gt;Compromised DC speaker; rogue &lt;code&gt;nTDSDSA&lt;/code&gt; registration&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A (preventive)&lt;/td&gt;
&lt;td&gt;Requires Microsoft protocol amendment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Four layers, dozens of products, no shortage of detections. Why isn&apos;t the problem solved?&lt;/p&gt;
&lt;h2&gt;7. Which Gap Does Each Defense Close?&lt;/h2&gt;
&lt;p&gt;The matrix in §6 has one structural observation that earns its keep. Read down the &lt;em&gt;What it misses&lt;/em&gt; column. Each detection layer has a class of cases it cannot see. The posture layer cannot see transitive paths. The behavioral layer cannot see pre-attack staging or compromised-DC speakers. The network layer cannot see encrypted RPC payloads. The graph layer cannot see net-new ACEs created after the last collection. That is the load-bearing reason a mature defender runs all four in parallel instead of picking one.&lt;/p&gt;
&lt;p&gt;Run a thought experiment. Suppose you ship only the posture layer. Your MDI assessment is green: no non-default principals hold the rights triad. An attacker compromises a workstation belonging to an unrelated business unit, finds that the BU has &lt;code&gt;GenericAll&lt;/code&gt; on a group &lt;code&gt;LegacyApp_Operators&lt;/code&gt; that itself has &lt;code&gt;WriteDACL&lt;/code&gt; on the &lt;code&gt;BackupOperators&lt;/code&gt; group, and adds themselves to &lt;code&gt;BackupOperators&lt;/code&gt;. &lt;code&gt;BackupOperators&lt;/code&gt; inherits a forgotten 2014 delegation of the rights triad through three levels of nesting. Then DCSync runs.&lt;/p&gt;
&lt;p&gt;The posture layer never saw this because the residual list at the NC root is the four defaults. The graph layer would have surfaced the path. The behavioral or network layer would have fired the moment the DCSync call hit the wire. Without those layers, your green dashboard is a single-layer fantasy.&lt;/p&gt;
&lt;p&gt;Now consider the inverse. You ship only the behavioral layer. MDI fires External ID 2006 -- but only after the request hits the DC. Your SOC&apos;s mean response time is twelve minutes. The attacker&apos;s mean &lt;em&gt;complete-the-extraction&lt;/em&gt; time is sixty seconds. The detection is real; the response window is not.&lt;/p&gt;
&lt;p&gt;The same structural observation applies on the attack side. The four attack primitives have very different precondition costs:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attack primitive&lt;/th&gt;
&lt;th&gt;Pre-condition&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Default detection layer&lt;/th&gt;
&lt;th&gt;Tier of damage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;DCSync via Mimikatz&lt;/td&gt;
&lt;td&gt;Rights triad on NC root&lt;/td&gt;
&lt;td&gt;Every secret-attribute value for one or all principals&lt;/td&gt;
&lt;td&gt;MDI 2006; Sigma 611eab06; Splunk 51307514; NDR&lt;/td&gt;
&lt;td&gt;Domain takeover (via Golden Ticket from &lt;code&gt;krbtgt&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DCSync via Impacket&lt;/td&gt;
&lt;td&gt;Same as Mimikatz; no on-target binary footprint&lt;/td&gt;
&lt;td&gt;Same as Mimikatz, plus PtH / PtT auth modes&lt;/td&gt;
&lt;td&gt;Same as Mimikatz (wire signature is identical)&lt;/td&gt;
&lt;td&gt;Domain takeover&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DCShadow&lt;/td&gt;
&lt;td&gt;Domain Admin, local administrator on a DC, or &lt;code&gt;KRBTGT&lt;/code&gt; hash (for rogue-DC registration) [@mitre-t1207][@dcshadow-com]&lt;/td&gt;
&lt;td&gt;Arbitrary directory write, SACL-silent&lt;/td&gt;
&lt;td&gt;MDI 2028 + 2029&lt;/td&gt;
&lt;td&gt;Domain persistence (SID-history, AdminSDHolder ACE re-grant)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gen-4 chains&lt;/td&gt;
&lt;td&gt;Any ACE that transitively leads to the triad&lt;/td&gt;
&lt;td&gt;Reach DCSync, then DCSync&apos;s output&lt;/td&gt;
&lt;td&gt;BloodHound DCSync edge inbound paths&lt;/td&gt;
&lt;td&gt;Domain takeover (composite)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;DCSync via Mimikatz and via Impacket [@impacket-secretsdump] share the &lt;em&gt;output&lt;/em&gt; (domain takeover via credential theft) and the &lt;em&gt;default detection&lt;/em&gt; (the wire signature is the same). Their pre-conditions are identical. The Hacker Recipes documents Impacket&apos;s invocation surface for both pass-the-hash and pass-the-ticket modes [@hacker-recipes-dcsync]. This is why Impacket&apos;s &lt;code&gt;secretsdump.py -just-dc&lt;/code&gt; has become the universal red-team and IR tool, while Mimikatz remains the reference implementation that every blue-team detection still names.&lt;/p&gt;
&lt;p&gt;The Generation-4 row is the interesting one. Its pre-condition is dramatically cheaper than the other three (&lt;em&gt;any&lt;/em&gt; ACE that leads to the triad, rather than the triad in hand). Its detection is by graph traversal, not by wire signature. This is why the 2024-2026 frontier in this space has been the graph layer: the attack-side cost asymmetry favors the chain-finding problem, so the defense-side investment has landed there.&lt;/p&gt;

A reader who has internalized the &quot;no DC check&quot; observation will naturally ask: surely the obvious architectural fix is to add a caller-machine-identity check? CVE-2020-1472, popularly known as Zerologon, is the counterexample. Secura&apos;s September 2020 whitepaper, published approximately one month after Microsoft&apos;s August 11, 2020 patch, documented that the Netlogon protocol&apos;s `ComputeNetlogonCredential` AES-CFB8 implementation used an all-zero initialization vector. An attacker who sends an all-zero `ClientChallenge` exploits the IV bug to authenticate with roughly 1-in-256 probability per attempt, then calls `NetrServerPasswordSet2` to reset the DC&apos;s machine account password (commonly to all zeros) and becomes that DC for protocol purposes [@secura-zerologon-whitepaper]. After Zerologon-class compromise, the attacker *is* a DC. Any architectural caller-machine-identity check on `IDL_DRSGetNCChanges` would have been satisfied. Zerologon is the canonical worked proof that promoting the access-check from &quot;rights&quot; to &quot;rights and DC identity&quot; raises the bar but does not change the class.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every detection layer in this space has a class of cases it cannot see. Mature defenders run all four (posture, behavioral, network, graph) because each layer is the only answer for a specific class of inputs, and accept that the un-shipped fifth layer (architectural) would only narrow the gap, not close it. Single-layer deployments produce confident but incomplete coverage.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If even the hypothetical perfect architectural fix would not close the class, what are the actual theoretical limits of any possible defense?&lt;/p&gt;
&lt;h2&gt;8. Why the Protocol Cannot Be Fixed&lt;/h2&gt;
&lt;p&gt;Two structural ceilings bound any conceivable MS-DRSR amendment. Both are provable from the specification&apos;s own definition of what it must do; both have been corroborated by the post-2018 industry consensus that &lt;em&gt;detection&lt;/em&gt; (not prevention) is the only viable defender posture.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ceiling 1: replicated secret material is the data the protocol exists to carry.&lt;/strong&gt; MS-DRSR is the mechanism by which Active Directory&apos;s multi-master replication invariant holds. If &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; did not return secret attributes -- &lt;code&gt;unicodePwd&lt;/code&gt;, &lt;code&gt;dBCSPwd&lt;/code&gt;, &lt;code&gt;ntPwdHistory&lt;/code&gt;, &lt;code&gt;lmPwdHistory&lt;/code&gt;, &lt;code&gt;supplementalCredentials&lt;/code&gt; -- then a password change on DC-A would not converge to DC-B within the replication interval. AD&apos;s &lt;em&gt;&quot;any DC accepts any write and the others catch up within minutes&quot;&lt;/em&gt; property would collapse [@ms-drsr-spec]. The protocol cannot stop returning secrets without ceasing to be the protocol. This is why &quot;disable MS-DRSR&quot; appears on every list of options that look attractive in a slide deck and break replication in production within minutes of being applied.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ceiling 2: a machine-identity check on the caller would shift the attack class, not close it.&lt;/strong&gt; Suppose Microsoft amended the access check on &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; to require, in addition to the rights triad, a cryptographic proof that the caller&apos;s machine account is in the &lt;code&gt;Domain Controllers&lt;/code&gt; group -- for example, that the call was made under a Kerberos service ticket issued for a DC SPN. This would defeat the Mimikatz-from-workstation case. It would also defeat every legitimate integration that today holds the rights triad on a non-DC service account: the Entra ID Connect MSOL_ account, third-party HR identity-management connectors, every backup and disaster-recovery tool that integrates at the AD level.&lt;/p&gt;
&lt;p&gt;Worse, the new check would shift the attack class to &lt;em&gt;compromising a DC&apos;s machine account&lt;/em&gt; -- CVE-2020-1472 Zerologon being the canonical worked example (see the §7 Aside for the mechanism). After a Zerologon-class compromise the attacker &lt;em&gt;is&lt;/em&gt; a DC, so promoting the speaker check from (rights) to (rights and DC-identity) raises the bar but does not change the class [@secura-zerologon-whitepaper].&lt;/p&gt;

flowchart TD
    Fix[Proposed MS-DRSR fix]
    Fix --&amp;gt; A[Stop returning secrets&lt;br /&gt;in IDL_DRSGetNCChanges]
    Fix --&amp;gt; B[Add machine-identity check&lt;br /&gt;on the caller]
    A --&amp;gt; A1[AD multi-master replication breaks&lt;br /&gt;password changes do not propagate]
    B --&amp;gt; B1[Legitimate integrations break&lt;br /&gt;MSOL_ account, HR IDM, backup tools]
    B --&amp;gt; B2[Attack shifts to compromised DC&lt;br /&gt;machine accounts e.g. Zerologon&lt;br /&gt;CVE-2020-1472]
&lt;p&gt;The honest structural fix would require a different replication architecture: a &lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;TPM&lt;/a&gt;- or HSM-attested DC machine identity, bound to a sealed replication key, with secret attributes encrypted under that key on the wire. No caller without the sealed key (or its hardware-bound equivalent on a different DC) could ever decrypt the response.&lt;/p&gt;
&lt;p&gt;Microsoft has not announced any such architecture. Its closest published precedent in the Windows security stack is the &lt;a href=&quot;https://paragmali.com/blog/vbs-trustlets-what-actually-runs-in-the-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;LSAIso trustlet&lt;/a&gt; that Credential Guard uses for LSASS isolation -- a per-host isolation primitive applied to a per-host secret store. Applying the same idea to a multi-party wire protocol that must interoperate with twenty-five years of installed identity-sync tooling is a different engineering problem at a different scale. Microsoft has not committed to it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The replication attack class is structurally permanent. The honest defender response is detection-and-response, not prevention.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the article&apos;s humility moment. The reader who arrived at §5 thinking &quot;this is fixable&quot; should now understand why eleven years of attack/defense iteration have produced detection layers, not protocol revisions. The four-layer detection architecture is not a placeholder while we wait for Microsoft to ship the real fix. It is the real fix, conditional on the constraint that the protocol&apos;s job description does not change.&lt;/p&gt;
&lt;p&gt;If the protocol is structurally unfixable, what exactly does 2026 still not solve operationally?&lt;/p&gt;
&lt;h2&gt;9. What 2026 Still Cannot Do&lt;/h2&gt;
&lt;p&gt;Five problems sit on the open-questions register in 2026. Each is documented in the literature. None has a satisfying answer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The DCShadow gap window.&lt;/strong&gt; MDI&apos;s External ID 2029 alert fires on the rogue DC&apos;s replication request, which is structurally &lt;em&gt;after&lt;/em&gt; the rogue &lt;code&gt;nTDSDSA&lt;/code&gt; registration has been committed. The alert documentation describes the detection as firing after the fact [@mdi-alerts-classic]. An attacker who completes the register-replicate-deregister cycle inside the alert&apos;s batch interval commits the persistence write before any SOC responder sees the alert. External ID 2028 (rogue promotion) fires earlier in the kill chain and partially closes the gap, but the gap is structural to the alert-batch model. The directory write that DCShadow lands -- a SID-history injection, an AdminSDHolder ACE re-grant -- survives the alert.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Encrypted-channel DCSync.&lt;/strong&gt; DRSUAPI clients that negotiate &lt;code&gt;AUTH_LEVEL_PKT_PRIVACY&lt;/code&gt; on the RPC binding (the modern hardened-DC default) encrypt the request and response bodies on the wire. Passive NDR sensors that depend on parsing the &lt;code&gt;IDL_DRSGetNCChanges&lt;/code&gt; request to determine which principal is being targeted lose per-principal granularity.&lt;/p&gt;
&lt;p&gt;The interface-bind packet is still in clear, so the existence of a DRSUAPI call is still visible, but the payload is not. The Microsoft channel-binding rollout that began in late 2023 (targeting LDAP rather than DRSUAPI, but cementing the broader trend toward encrypted directory traffic) makes this gap permanent on the wire side [@microsoft-ldap-channel-binding-kb4520412]. Detection moves into the DC itself via the MDI sensor model.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The legitimate-principal-compromise non-detection.&lt;/strong&gt; A hijacked Domain Admin session that uses its rightful DCSync ability triggers no layer. The posture layer sees a default principal. The behavioral layer sees a request from a DC or admin workstation that the Replication Allow List baseline accepts. The network layer sees the same. The graph layer sees the principal as a default Tier Zero member. The MDI alert is explicit: the trigger is &lt;em&gt;&quot;a computer that isn&apos;t a domain controller&quot;&lt;/em&gt; -- a compromised legitimate principal acting from a legitimately-baselined workstation does not fire it [@mdi-alerts-classic].&lt;/p&gt;
&lt;p&gt;This is the failure mode that catches mature SOCs. The attacker who already has Domain Admin does not need to attack DCSync detection because DCSync detection is not designed for legitimate principal abuse. UEBA-style per-principal anomaly detection (&lt;em&gt;&quot;this DA has not run DCSync in 90 days; this DA running DCSync at 03:00 from a workstation it has not used before is anomalous&quot;&lt;/em&gt;) is the partial answer. No production product currently delivers it with low enough false-positive rates to be operationally useful for already-Tier-Zero principals.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-forest replication abuse is under-instrumented.&lt;/strong&gt; The interaction of &lt;code&gt;DS-Replication-Get-Changes-In-Filtered-Set&lt;/code&gt; with the SPN-suffix routing matrix in multi-forest environments is poorly covered in public detection guidance. Large enterprises with M&amp;amp;A history hold dozens of trusts; the cross-trust edges are the least-audited surface in their identity architecture. BloodHound&apos;s SharpHound collector can enumerate cross-trust data, and v6.0&apos;s wildcard-principal fix improves the picture, but no fully automated detection pattern exists [@bloodhound-v6-0-release-notes].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Delegation-drift residual long tail.&lt;/strong&gt; Even with the MDI Accounts security posture assessment perfectly tuned, the long tail of forgotten ACE delegations across a twenty-five-year-old forest with mergers, acquisitions, decommissioned products, and migrations remains the canonical entry point. Christopher Keim frames it unambiguously [@keim-dcsync-rights]:&lt;/p&gt;

&quot;The defaults aren&apos;t the problem. The problem is delegation drift, backup agents, identity sync products, and application service accounts accumulate these rights over time, often with no documentation and no review.&quot; -- Christopher Keim, *&quot;DCSync Attack: Finding and Fixing Replication Rights in Active Directory&quot;* (2025) [@keim-dcsync-rights]
&lt;p&gt;The posture-layer detection is necessary but not sufficient; the human-process loop -- documented ownership, periodic review, removal of unjustified ACEs -- is what closes the residual. Most enterprise SOCs are not staffed to run this loop at the cadence the residual requires.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Open problem&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;th&gt;Current best partial result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;DCShadow gap window&lt;/td&gt;
&lt;td&gt;Persistence write commits before SOC sees the alert&lt;/td&gt;
&lt;td&gt;Configure MDI to surface External ID 2028 (rogue promotion) with automated investigation and response to block RPC traffic from the suspected source [@mdi-credential-access-alerts]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encrypted-channel DCSync&lt;/td&gt;
&lt;td&gt;Passive NDR loses per-principal granularity&lt;/td&gt;
&lt;td&gt;Hybrid deployment: NDR for cross-DC visibility, MDI on-DC sensor for per-principal granularity [@trellix-silent-domain-hijack]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legitimate-principal compromise non-detection&lt;/td&gt;
&lt;td&gt;The Tier Zero principal who already has DCSync rights triggers nothing&lt;/td&gt;
&lt;td&gt;Reduce the count of DCSync-capable principals to a number a human can monitor; surface their DCSync activity to a high-severity review queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-forest replication abuse&lt;/td&gt;
&lt;td&gt;Cross-trust DCSync paths are not enumerated by default&lt;/td&gt;
&lt;td&gt;SharpHound trust-collection methods; manual BloodHound inspection of foreign-domain principals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delegation-drift residual long tail&lt;/td&gt;
&lt;td&gt;Posture surfaces the principals; humans still have to decide which are legitimate&lt;/td&gt;
&lt;td&gt;Quarterly posture review with documented justification per non-default principal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;What can a defender actually do on Monday morning, given all of the above?&lt;/p&gt;
&lt;h2&gt;10. What a Defender Does on Monday Morning&lt;/h2&gt;
&lt;p&gt;Three action lanes, in priority order.&lt;/p&gt;
&lt;h3&gt;Lane 1: inventory the rights triad&lt;/h3&gt;
&lt;p&gt;Read the Domain NC root&apos;s ACL. Filter on the three rights GUIDs. Subtract the four default principal sets plus any legitimately delegated identity-sync product (Entra ID Connect&apos;s MSOL_ account is the canonical exclusion). Every entry that remains gets a documented owner and a documented justification, or the ACE gets removed.&lt;/p&gt;
&lt;p&gt;{`&lt;/p&gt;
Operator-facing inventory script. The browser-runnable demo uses a
hardcoded SAMPLE_ACL; in production, replace the SAMPLE_ACL with output
from one of:
PowerShell:  Get-Acl &quot;AD:$( (Get-ADDomain).DistinguishedName )&quot;
python-ldap: ldap_search(ncroot_dn, attr=&apos;nTSecurityDescriptor&apos;)
&lt;p&gt;GET_CHANGES          = &apos;1131f6aa-9c07-11d1-f79f-00c04fc2dcd2&apos;
GET_CHANGES_ALL      = &apos;1131f6ad-9c07-11d1-f79f-00c04fc2dcd2&apos;
GET_CHANGES_FILTERED = &apos;89e95b76-444d-4c62-991a-0facbeda640c&apos;
TRIAD = {GET_CHANGES, GET_CHANGES_ALL, GET_CHANGES_FILTERED}&lt;/p&gt;
&lt;p&gt;DEFAULT_OK = {
    &apos;BUILTIN\\Administrators&apos;,
    &apos;CONTOSO\\Domain Controllers&apos;,
    &apos;CONTOSO\\Domain Admins&apos;,
    &apos;CONTOSO\\Enterprise Admins&apos;,
    &apos;NT AUTHORITY\\ENTERPRISE DOMAIN CONTROLLERS&apos;,
}&lt;/p&gt;
MSOL_ accounts: legitimate Entra ID Connect sync principals.
Exclude by prefix, never by exact name (the suffix is random).
&lt;p&gt;def is_known_legitimate(principal):
    return principal in DEFAULT_OK or &apos;\\MSOL_&apos; in principal&lt;/p&gt;
&lt;p&gt;SAMPLE_ACL = [
    {&apos;principal&apos;: &apos;CONTOSO\\Domain Admins&apos;,     &apos;right&apos;: GET_CHANGES_ALL},
    {&apos;principal&apos;: &apos;CONTOSO\\MSOL_a1b2c3d4&apos;,     &apos;right&apos;: GET_CHANGES_ALL},
    {&apos;principal&apos;: &apos;CONTOSO\\backup_svc_2017&apos;,   &apos;right&apos;: GET_CHANGES_ALL},
    {&apos;principal&apos;: &apos;CONTOSO\\hr_idm_connector&apos;,  &apos;right&apos;: GET_CHANGES},
    {&apos;principal&apos;: &apos;CONTOSO\\fileserver_old$&apos;,   &apos;right&apos;: GET_CHANGES_ALL},
]&lt;/p&gt;
&lt;p&gt;findings = []
for ace in SAMPLE_ACL:
    if ace[&apos;right&apos;] not in TRIAD:
        continue
    if is_known_legitimate(ace[&apos;principal&apos;]):
        continue
    findings.append(ace[&apos;principal&apos;])&lt;/p&gt;
&lt;p&gt;print(&quot;Principals to investigate:&quot;)
for p in sorted(set(findings)):
    print(f&quot;  - {p}  -&amp;gt;  document owner or remove ACE&quot;)
`}&lt;/p&gt;
&lt;p&gt;Anything in the &lt;em&gt;Principals to investigate&lt;/em&gt; output is either a legitimately delegated service (document the owner and add to your exclusions; treat as Tier Zero) or a forgotten ACE from a project nobody remembers (remove it). Christopher Keim&apos;s framing is the operationally useful one: every common culprit is a backup tool, an identity-governance tool, or a service account from a long-dead migration [@keim-dcsync-rights].&lt;/p&gt;

The Microsoft Entra ID Connect synchronization service account, created on-premises during Entra Connect installation with an `MSOL_` prefix and a random hex suffix, legitimately holds the rights triad on the Domain NC root. It must -- it has to replicate password hashes to the cloud directory so that Entra ID can validate cloud logons against on-premises credentials. Removing its ACE breaks Entra ID password hash sync within a single replication interval, and your help desk will know about it.&lt;p&gt;The right answer is not to remove the ACE. It is to treat the MSOL_ account as Tier Zero. Dedicated host (the Entra Connect server itself, hardened as a DC-tier asset). No interactive logon. Multi-factor authentication on any privileged use. Conditional access policies that block sign-in from anything other than the Entra Connect service identity. The MDI Hybrid security posture-assessment family documents the surrounding controls [@mdi-security-posture-hybrid].
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Lane 2: enable the canonical alerts and audit&lt;/h3&gt;
&lt;p&gt;Three configuration items.&lt;/p&gt;
&lt;p&gt;First, ensure Microsoft Defender for Identity (or an equivalent identity-threat-detection product) is deployed with a sensor on every DC. The un-sensored-DC gap that the MDI alert documentation explicitly warns about creates a structural blind spot that an attacker will preferentially target [@mdi-alerts-classic].&lt;/p&gt;
&lt;p&gt;Second, enable Advanced Security Audit policy &lt;code&gt;Audit Directory Services Access&lt;/code&gt; under &lt;code&gt;DS Access&lt;/code&gt; and apply SACLs on the Domain NC root that audit the three replication rights against &lt;code&gt;Everyone&lt;/code&gt;, &lt;code&gt;Domain Computers&lt;/code&gt;, and &lt;code&gt;Domain Controllers&lt;/code&gt;. This is what makes Event ID 4662 fire on the request, which is what the Sigma 611eab06 and Splunk 51307514 rules consume [@sigma-rule-dcsync][@splunk-research-dcsync]. A fresh-install AD does not have these SACLs by default; the most common reason a SIEM dashboard for DCSync is silent is that the SACL never got applied.&lt;/p&gt;
&lt;p&gt;Third, deploy or configure NDR coverage on the inter-DC subnet, with a rule that fires on DRSUAPI bind requests originating from source IPs outside the legitimate-DC baseline. Trellix NDR, Microsoft&apos;s MDI sensor, CrowdStrike Falcon, and community Zeek/Suricata rulesets all implement this [@trellix-silent-domain-hijack]. Where commercial NDR is out of budget, Sysmon with the SwiftOnSecurity or Olaf Hartong modular configuration surfaces Event ID 3 (NetworkConnect) and Event ID 22 (DnsQuery) outbound from non-DC hosts to DC RPC endpoints; a SIEM correlation rule can combine this endpoint-side signal with Event ID 4662 on the DC to approximate the network-plus-host signature without an appliance budget.&lt;/p&gt;
&lt;h3&gt;Lane 3: run BloodHound on the domain quarterly&lt;/h3&gt;
&lt;p&gt;Collect with SharpHound at minimum quarterly. Continuous collection if BloodHound Enterprise is available. Run the canonical query for the &lt;code&gt;DCSync&lt;/code&gt; edge into the domain node. Trace inbound paths. Close the longest path first -- the longest paths are the ones a human operator is least likely to have noticed and most likely to have been delegated decades ago for a reason nobody remembers.&lt;/p&gt;
&lt;p&gt;The v6.0 wildcard-principal fix is particularly worth a re-run on any forest that has been operated since before 2003: legacy &lt;code&gt;Authenticated Users&lt;/code&gt; or &lt;code&gt;Everyone&lt;/code&gt; ACEs on the domain root are exactly the kind of thing that survived a Server 2003 upgrade silently and never showed up in any subsequent audit [@bloodhound-v6-0-release-notes]. The v6.3 Butterfly algorithm lets you query the inverse view -- &lt;em&gt;which targets fall if this principal is compromised?&lt;/em&gt; -- which is the right question to ask about any newly-discovered non-default DCSync holder [@specterops-butterfly-blog][@bloodhound-v6-3-release-notes].&lt;/p&gt;
&lt;h3&gt;What does not work&lt;/h3&gt;
&lt;p&gt;Four common misbeliefs are worth naming.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; See §1 -- Credential Guard does not stop DCSync. The secret transits remote-to-remote (a DC&apos;s NTDS.dit to the attacker&apos;s process), never local-to-LSASS, so the trustlet&apos;s isolation boundary has no jurisdiction over the call [@credential-guard-considerations]. Credential Guard is the right control for the local-memory attack surface and the wrong control for the network-protocol attack surface.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; After a confirmed DCSync of &lt;code&gt;krbtgt&lt;/code&gt;, rotate the &lt;code&gt;krbtgt&lt;/code&gt; account password twice, with at least ten hours between rotations. The first rotation invalidates the old key after the current Kerberos ticket lifetime expires. The second rotation invalidates the &lt;em&gt;previous&lt;/em&gt; old key, which the directory stores alongside the current key for compatibility during replication convergence. Rotating only once leaves Golden Tickets forged from the dumped key valid for the duration of the second key. Rotating twice ten hours apart is what closes the window [@microsoft-new-krbtgtkeys]. (And neither rotation removes the ACE that allowed the dump in the first place: come back to Lane 1.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Renaming &lt;code&gt;krbtgt&lt;/code&gt; does nothing. The account&apos;s Relative Identifier (RID 502) is fixed by AD&apos;s design and is what the TGT signing key derives against, not the &lt;code&gt;sAMAccountName&lt;/code&gt; [@microsoft-well-known-sids]. Renaming it to &lt;code&gt;krbtgt-old-do-not-use&lt;/code&gt; confuses operators, not attackers.&lt;/p&gt;
&lt;p&gt;Disabling MS-DRSR is not an option. The protocol is what makes AD replication work. Blocking opnum 3 at the RPC layer or refusing the DRSUAPI bind stops DCSync and stops every DC in the forest from talking to every other DC. Replication grinds. Password changes do not propagate. Domain joins fail. Within hours, the directory is split-brain across DCs, and within days, it is unrecoverable without DR-grade restore from backup: Microsoft&apos;s own AD-replication troubleshooting documentation walks the lingering-object pathology that produces exactly this split-brain when DCs stop replicating for longer than the tombstone lifetime [@microsoft-ad-lingering-objects].&lt;/p&gt;

On any DC, run `auditpol /get /subcategory:&quot;Directory Service Access&quot;` from an elevated prompt. If the output reads `No Auditing`, your Sigma / Splunk SACL-event detection will not fire because Event ID 4662 is not being generated. Enable with `auditpol /set /subcategory:&quot;Directory Service Access&quot; /success:enable /failure:enable`, then apply the SACL on the domain root as described in the Splunk rule&apos;s implementation notes [@splunk-research-dcsync].
&lt;p&gt;The six FAQ items in the next section cover the misconceptions that did not fit into any single lane.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

No. The access check on `IDL_DRSGetNCChanges` requires both the baseline `DS-Replication-Get-Changes` right *and* `DS-Replication-Get-Changes-All` to read secret attributes [@ad-schema-get-changes][@ad-schema-get-changes-all]. The *All* suffix unlocks the secret attribute set given the baseline right; it is not a self-sufficient gate. Christopher Keim&apos;s PowerShell pattern filters on both GUIDs together [@keim-dcsync-rights]. Confidential-flag attributes additionally require `DS-Replication-Get-Changes-In-Filtered-Set`. Some detection rules (Sigma 611eab06 included) accept either GUID in the SACL event because the operational cost of a false positive on the broader filter is lower than the risk of missing one of the two required ACEs being present without the other [@sigma-rule-dcsync].

No. Credential Guard isolates LSASS-resident secrets in a separate virtual trust level so that local-memory attacks (Mimikatz `sekurlsa::logonpasswords`, comsvcs.dll mini-dumps of `lsass.exe`, and similar) cannot read cached credentials. DCSync does not touch the attacker&apos;s LSASS at all. The secret transits from a remote DC&apos;s NTDS.dit, over an encrypted MS-DRSR session, into the attacker&apos;s process memory. Microsoft&apos;s Credential Guard documentation lists the scenarios Credential Guard does and does not cover; MS-DRSR-based network credential extraction is not in scope [@credential-guard-considerations]. This is one of the clearest examples in the Windows security model of a control that is right for one attack surface and orthogonal to another.

Not anymore. The BlueHat IL 2018 &quot;your million-dollar SIEM goes blind&quot; framing was correct in 2018 against SIEMs that monitored only object-modification events: the replication writes are SACL-silent. By July 24, 2018, Tali Ash announced Azure ATP&apos;s two new preview detections, which fired on the rogue-DC promotion fingerprint (creating an `nTDSDSA` object in the Configuration NC) and the replication request from the rogue, respectively [@tali-ash-azure-atp-dcshadow]. Those detections carried forward as Microsoft Defender for Identity External IDs 2028 and 2029 [@mdi-alerts-classic]. The writes themselves remain SACL-silent; the *registration* fingerprint that has to precede them is not. The honest contemporary statement is &quot;DCShadow&apos;s writes are silent, but the rogue-DC scaffolding is not, and a sensored DC catches the scaffolding.&quot; A skilled attacker who completes the register-replicate-deregister cycle inside the alert batch interval may still commit the persistence write before SOC response.

No. The protocol&apos;s design is the issue. Microsoft has not announced any MS-DRSR amendment that would change the `IDL_DRSGetNCChanges` access check, because amending the access check breaks legitimate non-DC consumers (the Entra ID Connect MSOL_ account is the most prominent) and shifts the attack class to compromised DC machine accounts (Zerologon is the worked example [@secura-zerologon-whitepaper]). The &quot;fixes&quot; that have shipped since 2015 are all detection: ATA 1.7 (April 2017) [@ata-v17-release-notes], Azure ATP (2018) [@tali-ash-azure-atp-dcshadow], Microsoft Defender for Identity (post-Ignite 2020 rebrand) [@rcpmag-defender-rebrand][@mdi-whats-new], and the posture-assessment families that surface non-default rights triad holders [@mdi-security-posture-accounts]. The protocol itself is the same protocol it was in Windows 2000 Server.

The MSOL_ sync account legitimately holds the rights triad on the Domain NC root because it must replicate password hashes to Entra ID. Treat it as Tier Zero with the hardening profile listed in §10&apos;s MSOL_ Aside (dedicated hardened host, no interactive logon, MFA on privileged use, conditional access restricted to the Entra Connect service identity) [@mdi-security-posture-hybrid]. Critically, do *not* remove the ACE from the Domain NC root: doing so breaks Entra ID password hash sync within one replication interval, and your help desk will know about it within hours.

No. DCSync is over DRSUAPI/MS-DRSR, not over LDAP. The directory&apos;s LDAP service refuses to return `unicodePwd` and related secret-attribute values regardless of caller privilege, because the attribute is marked confidential and the LDAP read path does not honor the replication extended rights. There is no &quot;DCSync over LDAP&quot; technique because LDAP simply does not return the data; MITRE T1003.006 names DRSUAPI explicitly as the protocol vector [@mitre-t1003-006]. Operators occasionally confuse this with LDAPS (LDAP over TLS) or with the November 2023 LDAP signing and channel-binding rollout, both of which are channel-protection concerns rather than credential-read concerns.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;dcsync-dcshadow-and-the-domain-replication-attack-class&quot; keyTerms={[
  { term: &quot;MS-DRSR&quot;, definition: &quot;Directory Replication Service Remote Protocol; the RPC interface by which any AD domain controller can replicate any object including secret attributes from any other DC.&quot; },
  { term: &quot;IDL_DRSGetNCChanges&quot;, definition: &quot;MS-DRSR&apos;s opnum-3 method that returns changed objects within a naming context; the protocol method DCSync invokes.&quot; },
  { term: &quot;Extended Right&quot;, definition: &quot;A schema-defined access-control right keyed by GUID rather than by standard ACL bit. Granted via ACE; checked at runtime by the operation that requires it.&quot; },
  { term: &quot;Naming Context&quot;, definition: &quot;A top-level replication partition of the Active Directory database. DCSync operates against the Domain NC root.&quot; },
  { term: &quot;Rights Triad&quot;, definition: &quot;DS-Replication-Get-Changes, DS-Replication-Get-Changes-All, and DS-Replication-Get-Changes-In-Filtered-Set extended rights on a naming-context root.&quot; },
  { term: &quot;NTDS.dit&quot;, definition: &quot;The on-disk Extensible Storage Engine database holding every AD object including secret attributes.&quot; },
  { term: &quot;SACL-silent&quot;, definition: &quot;A directory operation that does not generate the Event ID 4662/4738/5136 events normally emitted by Domain Services Auditing. Legitimate DC-to-DC replication is SACL-silent by design.&quot; },
  { term: &quot;Tier Zero&quot;, definition: &quot;Principals and assets whose compromise yields domain-wide control. KRBTGT, Domain Admins, the MSOL_ account, and any principal holding the rights triad are all Tier Zero.&quot; },
  { term: &quot;MSOL_ account&quot;, definition: &quot;The Entra ID Connect synchronization service account; legitimately holds the rights triad to replicate password hashes to the cloud directory.&quot; },
  { term: &quot;Replication Allow List&quot;, definition: &quot;MDI&apos;s internal baseline of which computers in the domain legitimately speak DRSUAPI to which DCs.&quot; }
]} flashcards={[
  { front: &quot;What does MS-DRSR §4.1.10 check on IDL_DRSGetNCChanges?&quot;, back: &quot;Only that the calling principal holds the rights triad on the naming-context root. It does not check whether the caller is a domain controller.&quot; },
  { front: &quot;What is the Mimikatz commit hash and date for DCSync&apos;s introduction?&quot;, back: &quot;Commit 7717b7a7173fa6a6b6566bbbc3e7372b464d988f, authored by Benjamin DELPY on 2015-08-11 01:27:13 +0200, subject &apos;DCSync in mimikatz &amp;amp; for XP/2003&apos;.&quot; },
  { front: &quot;What are MDI&apos;s three DCSync/DCShadow alert IDs?&quot;, back: &quot;External ID 2006 (DCSync), 2028 (DCShadow promotion), 2029 (DCShadow replication request).&quot; },
  { front: &quot;Why can&apos;t Microsoft patch DCSync?&quot;, back: &quot;Two structural ceilings: stopping the protocol from returning secrets breaks AD replication; adding a machine-identity check shifts the attack class to compromised DC machine accounts (Zerologon).&quot; },
  { front: &quot;What is the BloodHound v6.3 &apos;Butterfly&apos; algorithm?&quot;, back: &quot;Bi-directional impact analysis: in addition to &apos;which principals can reach this target?&apos;, also computes &apos;which targets fall if this principal is compromised?&apos;.&quot; }
]} questions={[
  { q: &quot;Why does adding a caller-machine-identity check to MS-DRSR not close the attack class?&quot;, a: &quot;Because compromising a DC&apos;s machine account (CVE-2020-1472 Zerologon being the canonical worked example) satisfies the new check while still enabling the original attack.&quot; },
  { q: &quot;Why is Credential Guard the wrong control for DCSync?&quot;, a: &quot;Credential Guard isolates LSASS-resident secrets on the local machine. DCSync reads secrets from a remote DC&apos;s NTDS.dit over MS-DRSR; the secret never transits the attacker&apos;s LSASS.&quot; },
  { q: &quot;Why must the krbtgt password be rotated twice after a confirmed DCSync?&quot;, a: &quot;Each AD account stores both the current and previous password. Rotating once invalidates only the older of the two keys; the most recently dumped key remains valid. Rotating a second time, after the first replication interval has converged, invalidates the dumped key.&quot; },
  { q: &quot;What does each of the four defense layers miss?&quot;, a: &quot;Posture misses transitive paths. Behavioral misses pre-attack staging and compromised-DC speakers. Network misses encrypted RPC payloads. Graph misses net-new ACEs created after the last collection.&quot; },
  { q: &quot;Why is the DCShadow gap window structural?&quot;, a: &quot;MDI External ID 2029 fires on the rogue&apos;s replication request after registration. An attacker who completes register-replicate-deregister inside the alert batch interval commits the persistence write before SOC response.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;A final observation, since the closing should add something new. The protocol that this article calls structurally unfixable is not unusual. Most Microsoft security primitives that survive long enough enter the same regime -- the LSASS surface, the Kerberos delegation surface, the SMB authentication surface -- where the only honest answer is detection in depth because the protocol&apos;s job description and its abuse surface are the same surface viewed from different chairs.&lt;/p&gt;
&lt;p&gt;The thing that makes MS-DRSR notable is the &lt;em&gt;clarity&lt;/em&gt; with which the structural error is visible. Read §4.1.10 once and you are done. Everything from §6 onward is the industry&apos;s slow accumulation of detection layers around a gate that cannot be moved. Twenty-five years in, the gate is still where it was on February 17, 2000, and the four layers around it are still under active engineering.&lt;/p&gt;
</content:encoded><category>active-directory</category><category>dcsync</category><category>dcshadow</category><category>ms-drsr</category><category>credential-theft</category><category>defender-for-identity</category><category>bloodhound</category><category>kerberos</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Kerberos in Windows: The Other Half of NTLMless</title><link>https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/</link><guid isPermaLink="true">https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/</guid><description>After NTLM, Kerberos becomes the load-bearing authentication protocol for Windows. Eight years of attacks, the December 2025 Beyond-RC4 cadence, and the H2 2026 IAKerb / Local KDC broad enable.</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Kerberos was a 1988 protocol that solved one problem: mutual authentication on an untrusted network using a trusted third party.** Then it got piled on for thirty-three years. In 2026 NTLM is being switched off, the AS-REQ / AS-REP / TGS-REQ / TGS-REP skeleton is finally the single load-bearing authentication path for Windows, and the eleven attack primitives that exposed every joint of that skeleton between 2014 and 2022 are still mostly fixable by configuration, not by protocol. This is the companion to [NTLMless](/blog/ntlmless-the-death-of-ntlm-in-windows/): what happens to the protocol that takes over.
&lt;h2&gt;1. A Chain Without NTLM&lt;/h2&gt;
&lt;p&gt;Imagine a defender who has done every NTLM retrofit Microsoft has shipped. NTLM is disabled by default on the workstations. &lt;code&gt;RestrictNTLMInDomain&lt;/code&gt; is on at the domain controller. SMB signing is enforced. Extended Protection for Authentication is set on every IIS endpoint. ESC8 has been patched. The defender has read the &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLMless&lt;/a&gt; post and ticked every box.&lt;/p&gt;
&lt;p&gt;A low-privileged user on that network opens a PowerShell prompt. They run &lt;code&gt;Powermad&lt;/code&gt; to create a fresh computer account. The default &lt;code&gt;MachineAccountQuota&lt;/code&gt; is still &lt;code&gt;10&lt;/code&gt;, which means any authenticated domain user can create up to ten computer objects in Active Directory by design [@shenanigans-rbcd]. They then write a single LDAP attribute, &lt;code&gt;msDS-AllowedToActOnBehalfOfOtherIdentity&lt;/code&gt;, on a target file server they have any write permission against. They ask the Key Distribution Center for a service ticket via &lt;code&gt;Rubeus s4u&lt;/code&gt;, present that ticket to the target file server, and walk in as &lt;code&gt;Administrator&lt;/code&gt;. Total elapsed time: less than this paragraph. Total NTLM in the chain: zero.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The post-NTLM Resource-Based Constrained Delegation chain depends on three properties of Kerberos that are features, not bugs: (a) the default &lt;code&gt;MachineAccountQuota = 10&lt;/code&gt; setting on every fresh Active Directory forest, (b) the S4U2Proxy guarantee that always produces a forwardable TGS even when the input ticket was not forwardable, and (c) the absence of any KDC-side check on whether the requesting principal is a &quot;trusted delegator&quot;. All three are documented behaviours of the protocol. None of them is a CVE [@shenanigans-rbcd].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The chain has a name and a primary disclosure: Elad Shamir&apos;s &quot;Wagging the Dog&quot; post on shenaniganslabs.io, January 28, 2019 [@shenanigans-rbcd]. The weaponised tooling is GhostPack&apos;s Rubeus, the C# Kerberos toolset that ships ready-made commands for &lt;code&gt;s4u&lt;/code&gt;, &lt;code&gt;asktgt&lt;/code&gt;, &lt;code&gt;kerberoast&lt;/code&gt;, and &lt;code&gt;diamond&lt;/code&gt; [@ghostpack-rubeus]. The single-line elevation wrapper that splices together Powermad, KrbRelay, Rubeus, and an SCM bypass is &lt;code&gt;KrbRelayUp&lt;/code&gt;, published by Mor Davidovich (&quot;Dec0ne&quot;) on April 24, 2022; its README scopes itself as a universal no-fix local privilege escalation in Windows domain environments where LDAP signing is not enforced (and that is the default) [@krbrelayup].&lt;/p&gt;

sequenceDiagram
    participant U as Low-priv user
    participant DC as Domain Controller / KDC
    participant T as Target file server
    U-&amp;gt;&amp;gt;DC: Powermad: create machine account FAKE (machine account)
    U-&amp;gt;&amp;gt;DC: LDAP write set RBCD attribute on T to allow FAKE
    U-&amp;gt;&amp;gt;DC: AS-REQ for FAKE -&amp;gt; TGT
    U-&amp;gt;&amp;gt;DC: S4U2Self as Administrator (non-forwardable TGS returned)
    U-&amp;gt;&amp;gt;DC: S4U2Proxy with TGS returns forwardable TGS for cifs on T
    U-&amp;gt;&amp;gt;T: AP-REQ presenting Administrator TGS
    T-&amp;gt;&amp;gt;U: SYSTEM access on T
&lt;p&gt;Read the chain twice. The first read shows that every step is a documented Kerberos exchange. The second read shows that &lt;em&gt;removing NTLM did nothing to it&lt;/em&gt;. Restrict-NTLM, EPA, SMB signing, ESC8 -- the entire NTLM-retrofit catalogue has no edge against a Kerberos-only attack path that uses S4U2Self, S4U2Proxy, and the Resource-Based Constrained Delegation attribute exactly as Microsoft documented them in [@ms-kerberos-overview].&lt;/p&gt;
&lt;p&gt;This is the article&apos;s load-bearing thesis. &lt;em&gt;Removing NTLM did not remove the attack surface; it shifted the attack surface onto a protocol that is also thirty-three years old, also retrofitted, and now also the only load-bearing one.&lt;/em&gt; In October 2023, Matthew Palko, Microsoft&apos;s Principal Group Product Manager for Windows authentication, wrote the post that committed Microsoft publicly to deprecating NTLM and named the Kerberos features that would replace it [@ms-palko-evolution]. The NTLMless companion article walked through the NTLM-side mechanics of that transition. This one walks through the Kerberos side.&lt;/p&gt;
&lt;p&gt;The question that drives everything that follows is the question the chain above forces: &lt;em&gt;how did Windows arrive at a state where the most catastrophic post-NTLM Active Directory attack chain depends on Kerberos working exactly as the 1989 designers intended?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;2. Origins: Needham, Schroeder, Athena, and 1988&lt;/h2&gt;
&lt;p&gt;Kerberos is not new engineering. The story of Windows authentication in 2026 starts with two Xerox PARC researchers and a 1978 paper in Communications of the ACM.&lt;/p&gt;
&lt;p&gt;In December 1978, Roger M. Needham and Michael D. Schroeder published &quot;Using Encryption for Authentication in Large Networks of Computers&quot; in CACM 21(12), pages 993 to 999 [@needham-schroeder]. The paper is paywalled on the ACM Digital Library, but RFC 4120&apos;s own Background section names it as the parent protocol [@rfc4120] and the Wikipedia article on the Needham-Schroeder protocol preserves the message structure verbatim [@wiki-needham-schroeder]. The symmetric-key version of that protocol is five messages long, and it is the structural blueprint of every &quot;ticket from a trusted third party&quot; design that followed.&lt;/p&gt;
&lt;p&gt;$$A \to S:\ A, B, N_A$$
$$S \to A:\ {N_A, K_{AB}, B, {K_{AB}, A}&lt;em&gt;{K&lt;/em&gt;{BS}}}&lt;em&gt;{K&lt;/em&gt;{AS}}$$
$$A \to B:\ {K_{AB}, A}&lt;em&gt;{K&lt;/em&gt;{BS}}$$
$$B \to A:\ {N_B}&lt;em&gt;{K&lt;/em&gt;{AB}}$$
$$A \to B:\ {N_B - 1}&lt;em&gt;{K&lt;/em&gt;{AB}}$$&lt;/p&gt;
&lt;p&gt;&lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; are the principals; &lt;code&gt;S&lt;/code&gt; is the trusted third party; &lt;code&gt;K_AS&lt;/code&gt; and &lt;code&gt;K_BS&lt;/code&gt; are pre-shared long-term keys; &lt;code&gt;K_AB&lt;/code&gt; is the session key that &lt;code&gt;S&lt;/code&gt; mints for the conversation; &lt;code&gt;N_A&lt;/code&gt; and &lt;code&gt;N_B&lt;/code&gt; are nonces. The &quot;ticket&quot; is the part of the third message that &lt;code&gt;A&lt;/code&gt; cannot decrypt and just forwards to &lt;code&gt;B&lt;/code&gt;. That structure -- a server-issued cryptographic envelope intended for somebody else and opaque to the carrier -- is what becomes the Kerberos TGS thirty-eight years later.&lt;/p&gt;
&lt;p&gt;Three years later, in August 1981, Dorothy Denning and Giovanni Maria Sacco published &quot;Timestamps in Key Distribution Protocols&quot; in CACM 24(8), 533-536. The paper is also paywalled on dl.acm.org, but the Wikipedia secondary preserves the finding: the Needham-Schroeder symmetric protocol is vulnerable to a replay attack if an attacker recovers an old session key [@wiki-needham-schroeder]. Denning and Sacco proposed timestamps as the fix. This is the structural reason every Kerberos ticket carries a timestamp and every Kerberos network requires a synchronised time service today.&lt;/p&gt;

A Kerberos administrative boundary, written in uppercase like `CONTOSO.COM`, that scopes a set of principals (users, services, computers) sharing a single Key Distribution Center. Every Kerberos ticket names the issuing domain in its `EncTicketPart.crealm` and `EncTicketPart.cname` fields. Active Directory binds one Kerberos domain to one AD forest root by default [@ms-kerberos-overview].
&lt;p&gt;Between 1983 and 1991, MIT Project Athena -- the joint MIT, DEC, and IBM campus computing effort led by Jerome Saltzer -- needed a working authentication service for a distributed workstation network running over a hostile campus LAN. The Athena Technical Plan Section E.2.1, &quot;Kerberos Authentication and Authorization System&quot; [@mit-athena-plan], is the canonical internal design document. Steve Miller and Clifford Neuman did the protocol work; Jeffrey Schiller ran the network operations.&lt;/p&gt;
&lt;p&gt;In February 1988, MIT published two complementary artefacts. Bill Bryant wrote &quot;Designing an Authentication System: a Dialogue in Four Scenes&quot; -- a pedagogical script in which an engineer named Athena designs her way step by step from &quot;users type their password to every server&quot; to &quot;users obtain time-limited tickets from a trusted third party&quot;. Bryant&apos;s dialogue is the most cited pre-protocol document about why Kerberos exists in the shape it does [@mit-dialogue]. The same month, Jennifer Steiner, Clifford Neuman, and Jeffrey Schiller presented &quot;Kerberos: An Authentication Service for Open Network Systems&quot; at the USENIX Winter Conference in Dallas [@cerias-steiner1988]. The protocol that paper described -- later called Kerberos version 4 -- carried forward to v5 with ASN.1 encoding, extensibility hooks, and pre-authentication, but the AS / TGS / AP message-triple skeleton it specified is unchanged thirty-eight years later.&lt;/p&gt;
&lt;p&gt;On January 24, 1989, MIT shipped the first public release of Kerberos v4 [@wiki-kerberos]. Five years later, in September 1993, the IETF adopted Kerberos v5 as RFC 1510 [@rfc1510]. RFC 1510 added ASN.1 encoding, cross-domain trust, and an extensibility hook called PA-DATA that every Kerberos extension since has used. In July 2005, RFC 4120 replaced RFC 1510 as the Kerberos v5 standard [@rfc4120].&lt;/p&gt;

sequenceDiagram
    participant C as Client
    participant AS as Authentication Service
    participant TGS as Ticket-Granting Service
    participant S as Application Server
    C-&amp;gt;&amp;gt;AS: AS-REQ: identify yourself
    AS-&amp;gt;&amp;gt;C: AS-REP TGT encrypted to TGS, session key wrapped under client long-term key
    C-&amp;gt;&amp;gt;TGS: TGS-REQ: present TGT, ask for service ticket
    TGS-&amp;gt;&amp;gt;C: TGS-REP service ticket encrypted to S, session key wrapped under TGT session key
    C-&amp;gt;&amp;gt;S: AP-REQ: present service ticket
    S-&amp;gt;&amp;gt;C: AP-REP: mutual auth confirmation
&lt;p&gt;Kerberos in 2026 is the same protocol as Kerberos in 1988, with thirty-three years of extensions piled on top. The skeleton you draw on a whiteboard for a graduate seminar is exactly the skeleton a Windows 11 24H2 machine throws at a 2025 domain controller. The interesting question is what those thirty-three years of extensions did to the inside of every message.The default maximum clock skew between client and KDC in Windows Kerberos is five minutes (300 seconds), set by Group Policy &quot;Maximum tolerance for computer clock synchronization&quot; and documented in [@ms-kerberos-overview]. The five-minute window is the residue of Denning and Sacco&apos;s 1981 timestamp fix.&lt;/p&gt;
&lt;h2&gt;3. The Wire in 2026: Six Messages and an Encryption Matrix&lt;/h2&gt;
&lt;p&gt;Every Kerberos textbook draws the same six-message diagram you saw in Section 2. The diagram has been unchanged since 1988. What is different in 2026 is everything inside the messages.&lt;/p&gt;
&lt;p&gt;Look first at the AS-REQ. In raw RFC 4120 the AS-REQ carries a &lt;code&gt;req-body&lt;/code&gt; (client name, target name, requested lifetime, requested enctypes) and an optional &lt;code&gt;padata&lt;/code&gt; field [@rfc4120]. That &lt;code&gt;padata&lt;/code&gt; slot is the load-bearing extensibility hook of the entire protocol. Every Kerberos enhancement since 1993 has been a new PA-DATA type: &lt;code&gt;PA-ENC-TIMESTAMP&lt;/code&gt; (the encrypted-timestamp pre-auth blob), &lt;code&gt;PA-PK-AS-REQ&lt;/code&gt; (PKINIT [@rfc4556]), &lt;code&gt;PA-FX-FAST-REQUEST&lt;/code&gt; (FAST armoring [@rfc6113]), &lt;code&gt;PA-AS-FRESHNESS&lt;/code&gt; (PKINIT freshness [@rfc8070]). The skeleton survives only because the joints are extensible.&lt;/p&gt;

A `SEQUENCE OF { padata-type, padata-value }` field in the Kerberos AS-REQ and AS-REP messages, introduced in RFC 1510 (1993) and carried forward unchanged into RFC 4120 §5.2.7 (2005). PA-DATA is the only protocol-level hook by which a Kerberos client can prove possession of a credential before the KDC issues a Ticket-Granting Ticket, and the only hook by which an enhancement like FAST or PKINIT can attach new behaviour to the AS exchange without breaking compatibility with older clients [@rfc4120].
&lt;p&gt;The AS-REP returns the TGT. The TGT itself is encrypted under the TGS&apos;s long-term key, so the client cannot inspect it. What the client &lt;em&gt;can&lt;/em&gt; inspect is the &lt;code&gt;EncTicketPart&lt;/code&gt; flag bitfield wrapped in the TGT envelope. RFC 4120 §2 enumerates the ticket-flag positions, including &lt;code&gt;forwardable&lt;/code&gt;, &lt;code&gt;proxiable&lt;/code&gt;, &lt;code&gt;postdated&lt;/code&gt;, &lt;code&gt;renewable&lt;/code&gt;, &lt;code&gt;initial&lt;/code&gt;, &lt;code&gt;pre-authent&lt;/code&gt;, &lt;code&gt;hw-authent&lt;/code&gt;, &lt;code&gt;transited-policy-checked&lt;/code&gt;, and &lt;code&gt;ok-as-delegate&lt;/code&gt; [@rfc4120]. (&lt;code&gt;may-postdate&lt;/code&gt; looks like a sibling but is a &lt;code&gt;KDCOptions&lt;/code&gt; request bit per RFC 4120 §5.4.1, not a &lt;code&gt;TicketFlags&lt;/code&gt; bit.) Pay attention to &lt;code&gt;forwardable&lt;/code&gt;. In 2020, Jake Karnes of NetSPI demonstrated that an attacker who knew a service account&apos;s long-term key could decrypt the S4U2Self output ticket, set &lt;code&gt;forwardable = 1&lt;/code&gt;, re-encrypt, and feed the ticket back to the KDC&apos;s S4U2Proxy step. The KDC accepted it. The bypass is CVE-2020-17049 and the attack is called Bronze Bit [@cve-2020-17049] [@netspi-bronze-bit].&lt;/p&gt;
&lt;p&gt;Inside the ticket&apos;s &lt;code&gt;AuthorizationData&lt;/code&gt; field is the Microsoft-specific construction that turns Kerberos into a Windows authorisation system. The Privilege Attribute Certificate, defined in [MS-PAC] revision 26.0 [@ms-pac-overview] [@ms-pac-deeplink], carries the user&apos;s SID, their group SIDs, their logon name, timestamps, and three cryptographic signatures: a Server signature, a KDC signature, and -- since CVE-2022-37967 in November 2022 -- a Full PAC Signature that covers the entire encoded PAC structure instead of just the existing signatures [@cve-2022-37967].&lt;/p&gt;

A Microsoft-specific authorization data element that the Kerberos KDC attaches to every ticket it issues for a Windows principal. The PAC carries the user&apos;s SID, group SIDs, logon name, and timestamps, and is signed by the KDC&apos;s `krbtgt` key and by the target service&apos;s key. The PAC, not the Kerberos ticket itself, is what gives a Windows file server the access-control information it needs to make a permission decision. Defined in [MS-PAC] [@ms-pac-overview].

The KB article URL ends in `cve-2022-37967` and the body text begins by referring to &quot;CVE-2022-37966&quot;. This is not a typo in the citation -- it is a Microsoft filing artefact. November 2022 Patch Tuesday paired two Kerberos CVEs: CVE-2022-37967 (Full PAC Signature, KrbtgtFullPacSignature) and CVE-2022-37966 (default session-key encryption type). KB5021131 covers the deployment of the encryption-type bypass side. A sibling article, KB5020805, covers the Full PAC Signature side. When citing KB5021131 alongside the Full PAC Signature, both CVE numbers are relevant [@ms-kb-5021131] [@cve-2022-37967].
&lt;p&gt;Then there is the encryption matrix. Kerberos abstracts ciphers behind the RFC 3961 framework [@rfc3961], which defines an enctype as a tuple of (encrypt, decrypt, checksum, string-to-key, key-derivation) functions. The history of Windows Kerberos is the history of which enctypes were the default at any given time.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Enctype&lt;/th&gt;
&lt;th&gt;Number&lt;/th&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Status in 2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;DES-CBC-CRC&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;RFC 3961 [@rfc3961]&lt;/td&gt;
&lt;td&gt;Disabled by default since Server 2008 R2 [@ms-kile-227]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DES-CBC-MD5&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;RFC 3961 [@rfc3961]&lt;/td&gt;
&lt;td&gt;Disabled by default since Server 2008 R2 [@ms-kile-227]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RC4-HMAC&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;RFC 4757 [@rfc4757]&lt;/td&gt;
&lt;td&gt;Informational, not Standards Track; default-removed in mid-2026 per [@ms-beyond-rc4]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-128-CTS-HMAC-SHA1-96&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;RFC 3962 [@rfc3962]&lt;/td&gt;
&lt;td&gt;Default since Server 2008; cross-version compatible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-256-CTS-HMAC-SHA1-96&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;RFC 3962 [@rfc3962]&lt;/td&gt;
&lt;td&gt;Default since Server 2008; the mid-2026 destination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-128-CTS-HMAC-SHA256-128&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;RFC 8009 [@rfc8009]&lt;/td&gt;
&lt;td&gt;Specified in [MS-KILE] bit K [@ms-kile-227]; no default-enable timeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AES-256-CTS-HMAC-SHA384-192&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;RFC 8009 [@rfc8009]&lt;/td&gt;
&lt;td&gt;Specified in [MS-KILE] bit L [@ms-kile-227]; no default-enable timeline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Enctype 23 is the row that built every Kerberoasting career. Kannan Jaganathan, Larry Zhu, and John Brezak of Microsoft published RFC 4757 in December 2006 [@rfc4757]. The IESG note on the RFC is unusually candid: the document is &lt;em&gt;Informational&lt;/em&gt;, not Standards Track, because RC4-HMAC &quot;do[es] not provide all the required operations in the Kerberos cryptography framework [RFC 3961]&quot; and because of &quot;security concerns with the use of RC4 and MD4&quot;. The choice that made enctype 23 dangerous, however, was upstream of the RFC. To make Windows 2000&apos;s Kerberos rollout backward-compatible with the existing SAM password database, Microsoft set the RC4-HMAC long-term Kerberos key equal to the &lt;em&gt;NT hash of the user&apos;s password&lt;/em&gt; -- the same hash NTLM was already storing. As Microsoft&apos;s own October 2024 Kerberoasting guidance puts it verbatim: &quot;RC4 is more susceptible to the cyberattack because it uses no salt or iterated hash when converting a password to an encryption key&quot; [@ms-kerberoasting-guidance].&lt;/p&gt;

The function that converts a typed password into a Kerberos long-term symmetric key. For RC4-HMAC (enctype 23), `s2k(password) = MD4(UTF-16-LE(password))` -- the NT hash, no salt, no iteration. For AES-CTS-HMAC-SHA1-96 (enctypes 17 and 18), `s2k(password, salt) = PBKDF2-HMAC-SHA1(password, salt, 4096, dklen)` followed by RFC 3962 post-processing into a 128- or 256-bit AES key. The salt is the concatenation of the Kerberos domain name and the user principal name [@rfc3962].
&lt;p&gt;The cryptography in that definition is short enough to read end-to-end. Here it is in JavaScript using the Web Crypto API:&lt;/p&gt;
&lt;p&gt;{`
async function kerberosStringToKey256(password, salt) {
  const enc = new TextEncoder();
  const passKey = await crypto.subtle.importKey(
    &quot;raw&quot;,
    enc.encode(password),
    { name: &quot;PBKDF2&quot; },
    false,
    [&quot;deriveBits&quot;]
  );
  const rawBits = await crypto.subtle.deriveBits(
    {
      name: &quot;PBKDF2&quot;,
      salt: enc.encode(salt),
      iterations: 4096,
      hash: &quot;SHA-1&quot;,
    },
    passKey,
    256
  );
  const hex = [...new Uint8Array(rawBits)]
    .map((b) =&amp;gt; b.toString(16).padStart(2, &quot;0&quot;))
    .join(&quot;&quot;);
  return hex;
}&lt;/p&gt;
&lt;p&gt;const password = &quot;Summer2026!&quot;;
const salt = &quot;CONTOSO.COMalice&quot;;
const keyHex = await kerberosStringToKey256(password, salt);
console.log(&quot;PBKDF2-HMAC-SHA1 output (truncated AES-256 key):&quot;, keyHex);
`}&lt;/p&gt;
&lt;p&gt;That 32-byte output is the value LSA stores when an account is configured with &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; bit E set. When a Kerberoasting attacker steals the TGS-REP, what they crack offline is which password produces that key. The RFC 3962 post-processing -- a single round of &lt;code&gt;DK(key, &quot;kerberos&quot;)&lt;/code&gt; -- shapes the output to AES key length but does not slow the dictionary attack down. The dispositive defence is not in the cryptography; it is in the password (or, more precisely, in not having one at all -- the move to gMSA and dMSA replaces typed passwords with KDC-generated random secrets [@ms-gmsa] [@ms-dmsa]).
PBKDF2 at 4,096 iterations is well below modern PHC recommendations -- the 2023 OWASP guideline for PBKDF2-HMAC-SHA1 is 1.3 million iterations [@owasp-password-storage] -- but the 4,096 figure is wired into RFC 3962 and is the same on every supported Windows version. Service accounts using gMSA bypass this entirely: the gMSA&apos;s &quot;password&quot; is a 240-character random secret rotated every 30 days, derived by the Microsoft Key Distribution Service rather than entered by a human [@ms-gmsa].&lt;/p&gt;
&lt;p&gt;The wire in 2026 is therefore six messages and a matrix of seven enctypes. The protocol skeleton is forty years old. In 2014 a SANS instructor named Tim Medin gave a forty-five-minute talk that turned every one of those enctypes into a problem.&lt;/p&gt;
&lt;h2&gt;4. The Attack Cascade: 2014 to 2022&lt;/h2&gt;
&lt;p&gt;September 26-28, 2014. Louisville, Kentucky. DerbyCon 4. Talk slot T120. Tim Medin -- then at Counter Hack Challenges, also a SANS instructor -- walks on stage with a forty-five-minute talk titled &quot;Attacking Microsoft Kerberos: Kicking the Guard Dog of Hades&quot; [@irongeek-derbycon4]. The talk demonstrates that any authenticated domain user can request a TGS for any Service Principal Name in the directory, and that the service-portion of the returned ticket is encrypted under the SPN account&apos;s long-term key -- which, under RC4-HMAC enctype 23, is the NT hash of the password. Cracking the ciphertext is reduced to a dictionary attack against whatever password an admin set on the service account.&lt;/p&gt;
&lt;p&gt;That talk is the moment Kerberos becomes interesting to attackers. The next eight years play out as a cascade. Five generations, each one named after the canonical primitive that defined it, each one exposing a different structural property of the protocol, each one earning its own engineered Microsoft response years later.&lt;/p&gt;

A unique identifier for a service instance in Active Directory, written in the form `service-class/host:port/service-name` (for example `HTTP/web01.contoso.com`). Kerberos uses the SPN to look up which account holds the long-term key that decrypts the service ticket. Any account that has an SPN -- a user account that has had `setspn -A` run against it, every machine account in the directory, every gMSA -- is a candidate for Kerberoasting [@adsecurity-kerberoast].
&lt;h3&gt;Generation 1, 2014: Kerberoasting&lt;/h3&gt;
&lt;p&gt;Tim Medin&apos;s primitive [@irongeek-derbycon4]. Will Schroeder&apos;s PowerShell weaponisation as &lt;code&gt;Invoke-Kerberoast&lt;/code&gt; (later rolled into the C# Rubeus) [@ghostpack-rubeus]. Sean Metcalf&apos;s operational walkthrough on adsecurity.org [@adsecurity-kerberoast]. MITRE catalogued the technique in 2020 as ATT&amp;amp;CK T1558.003, which preserves the structural definition verbatim: &quot;Portions of these tickets may be encrypted with the RC4 algorithm, meaning the Kerberos 5 TGS-REP etype 23 hash of the service account associated with the SPN is used as the private key and is thus vulnerable to offline Brute Force attacks&quot; [@mitre-t1558-003].&lt;/p&gt;
&lt;p&gt;The structural insight is the part that matters. The TGS-REP is encrypted with the service account&apos;s &lt;em&gt;long-term&lt;/em&gt; password-derived key, so any domain user who can issue a TGS-REQ can mine ciphertext offline against any dictionary they care to assemble. The Kerberos protocol has no mechanism by which the KDC could tell whether the requesting user has any business asking for that SPN, because RFC 4120 has no concept of &quot;this service is for these users&quot;. Anyone with a TGT gets the service ticket.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s engineered response did not arrive until ten to twelve years later. Server 2012 introduced Group Managed Service Accounts: passwords randomised to 240 characters, derived by the Microsoft Key Distribution Service via &lt;code&gt;kdssvc.dll&lt;/code&gt;, rotated every 30 days, retrievable from a domain controller by member hosts that are explicitly authorised in &lt;code&gt;msDS-GroupMSAMembership&lt;/code&gt; [@ms-gmsa]. Server 2025 then introduced Delegated Managed Service Accounts (dMSA), which take the next structural step: the dMSA&apos;s secret is &quot;derived from the machine account credential&quot; held by the domain controller, and &quot;the secret can&apos;t be retrieved or found anywhere other than on the DC&quot; [@ms-dmsa]. The October 2024 Microsoft Security Blog formalised the Kerberoasting guidance in a single page that names RC4 as the load-bearing weakness and announces the deprecation [@ms-kerberoasting-guidance]. The December 2025 Beyond-RC4 announcement closed the cadence with a calendar date [@ms-beyond-rc4].&lt;/p&gt;
&lt;h3&gt;Generation 2, 2014-2017: Mimikatz Kerberos and AS-REP Roasting&lt;/h3&gt;
&lt;p&gt;Benjamin Delpy publishes &lt;code&gt;mimikatz&lt;/code&gt; 2.0 on April 6, 2014; the v2 banner inside the repository README reads verbatim &lt;code&gt;mimikatz 2.0 alpha (x86) release &quot;Kiwi en C&quot; (Apr 6 2014 22:02:03)&lt;/code&gt; [@mimikatz]. The Kerberos module contains two commands that define the era: &lt;code&gt;kerberos::golden&lt;/code&gt; (forge a TGT from the KRBTGT account&apos;s long-term key, granting Domain Admin equivalence indefinitely) and &lt;code&gt;kerberos::silver&lt;/code&gt; (forge a TGS from any service account&apos;s long-term key, granting impersonation of any user against that service).&lt;/p&gt;
&lt;p&gt;The structural insight: RFC 4120 has no online ticket validation [@rfc4120]. Once a ticket carries the right signatures, the service trusts it. Whoever holds a long-term key forges any ticket that key signs. Possession of a key collapses to ticket forgeability.&lt;/p&gt;
&lt;p&gt;Around 2017, the same team behind Rubeus publicises AS-REP Roasting [@ghostpack-rubeus]: the same offline-cracking primitive as Kerberoasting, but against any account whose &lt;code&gt;userAccountControl&lt;/code&gt; has &lt;code&gt;UF_DONT_REQUIRE_PREAUTH&lt;/code&gt; (the &lt;code&gt;DONT_REQ_PREAUTH&lt;/code&gt; flag) set. With pre-authentication disabled, the KDC will return an AS-REP encrypted under the user&apos;s password-derived key to &lt;em&gt;anyone&lt;/em&gt; who asks for it, no proof of password possession required. The dispositive Microsoft response was already in place: pre-authentication has been required by default for all new Active Directory accounts since Windows 2000, and the flag has to be deliberately cleared by an administrator. The remaining vulnerability is operational hygiene -- finding the handful of legacy accounts an organisation has left with pre-auth disabled.&lt;/p&gt;
&lt;h3&gt;Generation 3, 2018-2020: Delegation Abuse&lt;/h3&gt;
&lt;p&gt;Three primitives in three years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SpoolSample / PrinterBug.&lt;/strong&gt; Lee Christensen (tifkin_, SpecterOps) published the PoC on GitHub on October 5, 2018 [@spoolsample]. The MS-RPRN remote-procedure-call interface includes a method, &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt;, that any authenticated user can invoke against any host&apos;s spooler service to ask the spooler to &lt;em&gt;please call back&lt;/em&gt; to an attacker-controlled address. The spooler obediently authenticates outbound using the machine account&apos;s credentials. Combined with unconstrained Kerberos delegation on the attacker-controlled host, the inbound authentication captures the target machine&apos;s TGT.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wagging the Dog (RBCD).&lt;/strong&gt; Elad Shamir&apos;s January 28, 2019 post on shenaniganslabs.io [@shenanigans-rbcd]. The TL;DR of the post is the load-bearing structural disclosure: &quot;Resource-based constrained delegation does not require a forwardable TGS when invoking S4U2Proxy. S4U2Self works on any account that has an SPN, regardless of the state of the TrustedToAuthForDelegation attribute. S4U2Proxy always produces a forwardable TGS, even if the provided additional TGS in the request was not forwardable. By default, any domain user can abuse the MachineAccountQuota to create a computer account and set an SPN for it, which makes it even more trivial to abuse resource-based constrained delegation to mimic protocol transition&quot; [@shenanigans-rbcd]. Every clause of that TL;DR points at a documented behaviour. The chain in this article&apos;s Hook is built directly on top.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bronze Bit.&lt;/strong&gt; Jake Karnes at NetSPI; CVE-2020-17049; disclosed November 10, 2020 [@netspi-bronze-bit] [@cve-2020-17049]. The NVD entry preserves Microsoft&apos;s verbatim description: &quot;A security feature bypass vulnerability exists in the way Key Distribution Center (KDC) determines if a service ticket can be used for delegation via Kerberos Constrained Delegation (KCD). To exploit the vulnerability, a compromised service that is configured to use KCD could tamper with a service ticket that is not valid for delegation to force the KDC to accept it&quot; [@cve-2020-17049]. The bypass: any service in possession of its own long-term key can decrypt the S4U2Self output ticket, flip the &lt;code&gt;forwardable&lt;/code&gt; bit in &lt;code&gt;EncTicketPart&lt;/code&gt;, and re-encrypt with the same key. Pre-2020 the KDC&apos;s S4U2Proxy validation accepted the resulting ticket because nothing on the ticket independently attested whether the &lt;code&gt;forwardable&lt;/code&gt; flag had been set by the KDC or by the service itself. Microsoft&apos;s November 10, 2020 fix, per the NVD entry verbatim, &quot;addresses this vulnerability by changing how the KDC validates service tickets used with KCD&quot; so that the tampered flag is rejected [@cve-2020-17049]. The PAC signatures, contra a common framing, were never meant to cover the &lt;code&gt;EncTicketPart&lt;/code&gt; flag bits in the first place.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s engineered responses: the November 2020 Bronze Bit patch [@cve-2020-17049] tightened the KDC&apos;s S4U2Proxy ticket-validation step; KB5008383 (November 2021) [@ms-kb-5008383] issued the canonical &quot;set &lt;code&gt;ms-DS-MachineAccountQuota = 0&lt;/code&gt; for non-administrator users&quot; guidance; LDAP signing and channel binding work, ongoing since the &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLMless&lt;/a&gt; era, became the dispositive control against the relay variant of the chain.&lt;/p&gt;
&lt;h3&gt;Generation 4, 2021-2022: Certificate-Based Ticket Forgery and Kerberos Relay&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Certifried.&lt;/strong&gt; Oliver Lyak (ly4k) at IFCR disclosed CVE-2022-26923 to Microsoft, who patched on May 10, 2022 [@cve-2022-26923]. The attack exploited a quirk of how Active Directory Certificate Services (ADCS) bound a certificate&apos;s identity to an AD account when the certificate was used for PKINIT. Before the strong-mapping fix, AD&apos;s account-lookup at PKINIT time used the certificate&apos;s Subject Alternative Name (SAN) and matched the User Principal Name. If an attacker controlled a machine account, they could change the machine&apos;s &lt;code&gt;dNSHostName&lt;/code&gt; to match a domain controller&apos;s, request a certificate via the (overly-permissive) default &lt;code&gt;Machine&lt;/code&gt; template, and use the resulting certificate to PKINIT-authenticate to the KDC as that domain controller. Microsoft&apos;s response is documented end-to-end in KB5014754 [@ms-kb-5014754]: a new &quot;strong certificate mapping&quot; requirement that pins each issued certificate to a specific account SID via an X.509 extension (OID 1.3.6.1.4.1.311.25.2). The original release moved to Compatibility mode on May 10, 2022; full Enforcement mode took effect on February 11, 2025; Disabled-mode rollback was removed on April 11, 2023; the remaining Compatibility-mode fallback was removed on September 9, 2025 [@ms-kb-5014754].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KrbRelayUp.&lt;/strong&gt; Mor Davidovich (&lt;code&gt;Dec0ne&lt;/code&gt;), April 24, 2022 [@krbrelayup]. The README&apos;s universal-no-fix-LPE framing is preserved in the PullQuote below. The chain wraps &lt;code&gt;Powermad&lt;/code&gt; (machine account creation), &lt;code&gt;KrbRelay&lt;/code&gt; (Kerberos relay to LDAP), Rubeus (S4U2Self bypass of Protected Users, RBCD privilege addition), and &lt;code&gt;SCMUACBypass&lt;/code&gt; (a wrapper that uses the resulting ticket to open the local Service Control Manager and create a service running as &lt;code&gt;NT AUTHORITY\SYSTEM&lt;/code&gt;). The class of attack is &quot;Kerberos relay&quot; -- the post-NTLM cousin of NTLM-relay. The dispositive control is not a Kerberos patch; it is domain-wide LDAP signing plus channel binding plus Extended Protection for Authentication on ADCS Web Enrolment.&lt;/p&gt;

A universal no-fix local privilege escalation in windows domain environments where LDAP signing is not enforced (the default settings). -- Mor Davidovich, KrbRelayUp README, April 2022 [@krbrelayup]
&lt;h3&gt;Generation 5, 2022-2023: Forged-Ticket Sophistication&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Diamond Ticket.&lt;/strong&gt; Charlie Clark at Semperis co-authored a blog post in 2022 with Andrew Schwartz at TrustedSec disclosing the modern Diamond Ticket technique [@semperis-diamond] [@trustedsec-diamond]. The Semperis byline names the antecedent: a 2015 Black Hat EU presentation by Tal Be&apos;ery and Michael Cherny (&quot;Watching the Watchdog&quot;) that introduced the &quot;Diamond PAC&quot; idea. Verbatim from the Semperis post: &quot;Golden Ticket attacks take advantage of the ability to forge a ticket granting ticket (TGT) from scratch, Diamond Ticket attacks take advantage of the ability to decrypt and re-encrypt genuine TGTs requested from a domain controller (DC)&quot; [@semperis-diamond]. The structural insight is that a Diamond Ticket has a &lt;em&gt;legitimately issued, KDC-signed&lt;/em&gt; PAC at its base; only the privilege-claim fields inside the PAC are tampered. Before the November 2022 Full PAC Signature fix, the existing Server and KDC signatures only covered specific sub-structures, leaving room to modify the parts they did not sign.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sapphire Ticket.&lt;/strong&gt; Charlie Bromberg, also known online as &quot;Shutdown&quot;, at Synacktiv [@pgj11-diamond-sapphire] [@thehacker-recipes-sapphire]. The community wiki The Hacker Recipes, which Bromberg maintains, documents the Sapphire Ticket technique end-to-end at &lt;code&gt;thehacker.recipes/a-d/movement/kerberos/forged-tickets/sapphire&lt;/code&gt; [@thehacker-recipes-sapphire]. The verifiable third-party attribution lives at pgj11.com, which records verbatim: &quot;One brand new technique is Sapphire Ticket. Created by Charlie Shutdown (twitter.com/_nwodtuhs) this approach is more stealthy. You can create a TGT impersonating any user assembling real TGT and real PAC combining S4U2Self + U2U ... He extended Ticketer from Impacket to add this attack&quot; [@pgj11-diamond-sapphire]. The Sapphire Ticket bolts a &lt;em&gt;legitimately KDC-issued&lt;/em&gt; PAC (obtained by chaining the S4U2Self and User-to-User Kerberos extensions to request a service ticket &lt;em&gt;to oneself&lt;/em&gt; with the PAC of an arbitrary target user) onto a Diamond-style ticket. The result presents PAC signatures that the KDC itself produced. Unit 42&apos;s December 2022 &quot;Next-Gen Kerberos Attacks&quot; writeup is the secondary that joined Diamond and Sapphire into the same article and named them collectively the &quot;Precious Gemstones&quot; [@unit42-precious-gemstones].
Some secondary sources attribute Sapphire Ticket to Charlie Clark of Semperis. The misattribution probably stems from Clark&apos;s separate &quot;AS Requested STs&quot; post on the Semperis blog, which discusses a different technique exploiting unarmored machine-account AS-REQs and is not the Sapphire Ticket primary [@semperis-as-sts]. The verified Sapphire-Ticket originator is Charlie Bromberg (Shutdown, Synacktiv) per [@pgj11-diamond-sapphire].
The adsecurity.org URL &lt;code&gt;?p=2293&lt;/code&gt; is Sean Metcalf&apos;s &quot;Cracking Kerberos TGS Tickets Using Kerberoast -- Exploiting Kerberos to Compromise the Active Directory Domain&quot; (not Metcalf&apos;s separate KRBTGT-account post, which lives at a different URL). The page is the operational walkthrough that pairs with Tim Medin&apos;s 2014 DerbyCon disclosure [@adsecurity-kerberoast].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s engineered response to both Diamond and Sapphire was CVE-2022-37967, the KrbtgtFullPacSignature [@cve-2022-37967] [@ms-kb-5021131]. It is the first PAC-handling protocol change since Windows 2000&apos;s introduction of the PAC. After full enforcement, the KDC adds a &lt;em&gt;Full PAC Signature&lt;/em&gt; that covers the entire encoded PAC, not just the existing sub-signatures. Diamond and Sapphire variants that modify any PAC field beyond what the Server and KDC sub-signatures already covered will fail validation.&lt;/p&gt;

The accounts most vulnerable to Kerberoasting are those with weak passwords and those that use weaker encryption algorithms, especially RC4. RC4 is more susceptible to the cyberattack because it uses no salt or iterated hash when converting a password to an encryption key, allowing the cyberthreat actor to guess more passwords quickly. -- Microsoft Security Blog, October 11, 2024 [@ms-kerberoasting-guidance]
&lt;h3&gt;The Spine Table&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Structural Insight&lt;/th&gt;
&lt;th&gt;Microsoft Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;Kerberoasting [@irongeek-derbycon4]&lt;/td&gt;
&lt;td&gt;TGS-REP is encrypted with the SPN account&apos;s long-term key; offline-crackable&lt;/td&gt;
&lt;td&gt;gMSA (2012) [@ms-gmsa]; dMSA (2025) [@ms-dmsa]; Beyond-RC4 (2025-2026) [@ms-beyond-rc4]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2014-2017&lt;/td&gt;
&lt;td&gt;Golden / Silver Ticket [@mimikatz]; AS-REP Roasting [@ghostpack-rubeus]&lt;/td&gt;
&lt;td&gt;RFC 4120 has no online ticket validation [@rfc4120]; long-term key = forge equivalence&lt;/td&gt;
&lt;td&gt;KrbtgtFullPacSignature (2022) [@cve-2022-37967]; preauth-required default since Windows 2000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2018-2020&lt;/td&gt;
&lt;td&gt;SpoolSample [@spoolsample]; RBCD [@shenanigans-rbcd]; Bronze Bit [@cve-2020-17049]&lt;/td&gt;
&lt;td&gt;MS-RPRN coercion; S4U2Proxy always returns forwardable; pre-2020 KDC did not independently validate the EncTicketPart flags&lt;/td&gt;
&lt;td&gt;Bronze Bit patch (Nov 2020); KB5008383 MachineAccountQuota=0 (Nov 2021); LDAP signing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;Certifried [@cve-2022-26923]; KrbRelayUp [@krbrelayup]&lt;/td&gt;
&lt;td&gt;ADCS template SAN-binding ambiguity; LDAP defaults unsigned&lt;/td&gt;
&lt;td&gt;KB5014754 strong-mapping [@ms-kb-5014754]; LDAP signing + EPA on /certsrv/&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;Diamond [@semperis-diamond]; Sapphire [@pgj11-diamond-sapphire] [@unit42-precious-gemstones]&lt;/td&gt;
&lt;td&gt;PAC sub-signatures did not cover the encoded PAC structure&lt;/td&gt;
&lt;td&gt;KrbtgtFullPacSignature (CVE-2022-37967, Nov 2022) [@cve-2022-37967]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

timeline
    title Kerberos attack cascade
    section 2014
      Sep 2014 : Kerberoasting (Tim Medin, DerbyCon 4)
      Apr 2014 : Mimikatz 2.0 (Golden / Silver Tickets)
    section 2017
      2017 : AS-REP Roasting (Rubeus weaponisation)
    section 2018-2020
      Oct 2018 : SpoolSample (PrinterBug, Lee Christensen)
      Jan 2019 : Wagging the Dog / RBCD (Elad Shamir)
      Nov 2020 : Bronze Bit (Jake Karnes, NetSPI)
    section 2022
      Apr 2022 : KrbRelayUp (Mor Davidovich)
      May 2022 : Certifried (Oliver Lyak / ly4k)
      2022 : Diamond Ticket (Clark / Schwartz)
      2022 : Sapphire Ticket (Charlie Bromberg)
      Nov 2022 : KrbtgtFullPacSignature (Microsoft fix)
&lt;p&gt;Eight years. Eleven structural primitives. One protocol. By 2022 the cascade slowed, not because the protocol got better, but because every primitive a thirty-three-year-old design &lt;em&gt;could&lt;/em&gt; expose had been exposed. The 2022 Microsoft response, KrbtgtFullPacSignature, was the first one that targeted the &lt;em&gt;structural&lt;/em&gt; properties (PAC coverage of its own structure) rather than the per-primitive patches that defined the 2014-2020 era. To see why that was a turning point, it helps to see exactly what the defensive cadence looked like before then.&lt;/p&gt;
&lt;h2&gt;5. The Defensive Cadence Before 2023&lt;/h2&gt;
&lt;p&gt;Each of the eleven primitives in Section 4 shipped with a fix. By 2022 every named primitive &lt;em&gt;had&lt;/em&gt; a fix. And yet the cascade kept producing new primitives. Why?&lt;/p&gt;
&lt;p&gt;The answer is in the shape of the defensive controls. Walk them in chronological order.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Protected Users (Server 2012 R2, October 2013) [@ms-server-2012-r2].&lt;/strong&gt; A new security group that triggers five non-configurable client-side protections and four non-configurable domain-controller-side protections [@ms-protected-users]. The client side: CredSSP &quot;doesn&apos;t cache the user&apos;s plain text credentials&quot;; Windows Digest &quot;doesn&apos;t cache the user&apos;s plaintext credentials&quot;; &quot;NTLM stops caching the user&apos;s plaintext credentials or NT one-way function (NTOWF)&quot;; &quot;Kerberos stops creating Data Encryption Standard (DES) or RC4 keys ... or long-term keys after acquiring the initial Ticket Granting Ticket (TGT)&quot;; &quot;The system doesn&apos;t create a cached verifier at user sign-in or unlock&quot; [@ms-protected-users]. The domain-controller side, also verbatim: members &quot;cannot authenticate with NTLM authentication ... use DES or RC4 encryption types in Kerberos preauthentication ... delegate with unconstrained or constrained delegation ... renew Kerberos TGTs beyond their initial four-hour lifetime&quot; [@ms-protected-users]. The limit is the obvious one: Protected Users breaks every workflow that relied on delegation, RC4, or NTLM, and there are many such workflows still in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Authentication Policy Silos (Server 2012 R2).&lt;/strong&gt; A scope construct that lets administrators apply Protected-Users-equivalent constraints (no RC4, no unconstrained delegation, mandatory FAST) to tiered subsets of an organisation rather than per-account. The standard tier-zero / tier-one / tier-two split fits neatly under three silos [@ms-privileged-access].&lt;/p&gt;

A container of users, computers, and managed service accounts in Active Directory that scopes a single authentication policy. Members can be required to authenticate only from designated hosts, must use AES enctypes, may be excluded from delegation, and (when paired with FAST armoring) sign their AS-REQ inside a machine-account or anonymous-PKINIT armor. Available since Server 2012 R2; the operational granularity that Protected Users does not provide on its own [@ms-protected-users].
&lt;p&gt;&lt;strong&gt;Restricted Admin (2014) and Remote Credential Guard (2016) [@ms-remote-credential-guard].&lt;/strong&gt; The RDP-side companions that block credential exposure on the target host. Both work by changing what gets sent on the wire during a remote sign-in: Restricted Admin (Windows 8.1 / Server 2012 R2 era) uses the user&apos;s TGT to authenticate via Kerberos network logon, so no credentials reach the target; Remote Credential Guard (Windows 10 1607, August 2016) performs the same trick but for interactive sessions, redirecting CredSSP back to the originating workstation [@ms-remote-credential-guard].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Credential Guard (Windows 10 RTM, 2015) [@ms-credential-guard].&lt;/strong&gt; Virtualization-Based-Security-isolated LSASS: secrets that LSASS would otherwise hold in user-mode memory are moved into the LSAISO trustlet running in Virtual Trust Level 1. SYSTEM on the box cannot read VTL1 memory. Credential Guard is the ceiling against memory-side ticket and key theft, and is one of the cross-link points to the &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLMless&lt;/a&gt; companion article.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FAST armoring (RFC 6113, April 2011).&lt;/strong&gt; Sam Hartman and Larry Zhu&apos;s &quot;A Generalized Framework for Kerberos Pre-Authentication&quot; defines the FAST (Flexible Authentication Secure Tunneling) channel [@rfc6113]. The AS-REQ is wrapped in an outer armor envelope, keyed under the machine account&apos;s TGT (for a domain-joined client), an anonymous PKINIT TGT (for a non-domain-joined client), or a compound identity. The armor envelope encrypts the PA-ENC-TIMESTAMP blob and authenticates the entire request, closing the offline-cracking path that targets the encrypted-timestamp pre-auth. The limit: FAST is client opt-in, not on by default, and Server 2012 R2 domain functional level is the floor for compound identity. Many production environments still do not require FAST on their tier-zero accounts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;gMSA (Server 2012).&lt;/strong&gt; The dispositive Kerberoasting defence for service accounts [@ms-gmsa]. The Microsoft Key Distribution Service (&lt;code&gt;kdssvc.dll&lt;/code&gt;) computes a 240-character random password, rotated every 30 days, and member hosts authorised in &lt;code&gt;msDS-GroupMSAMembership&lt;/code&gt; can retrieve it from a domain controller. The decisive property that gMSA closes is the human-typed-password assumption: there is no password to remember, write down, or share.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LDAP signing and channel binding.&lt;/strong&gt; The dispositive KrbRelayUp defence. Set &lt;code&gt;LDAPServerIntegrity = 2&lt;/code&gt; to require signing on every LDAP bind, and &lt;code&gt;LdapEnforceChannelBinding = 2&lt;/code&gt; to require channel binding on TLS-bound LDAP connections. Both are off by default in older domain functional levels, which is exactly the default the [@krbrelayup] README is targeting when it calls itself &quot;no-fix&quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;KrbtgtFullPacSignature (November 2022).&lt;/strong&gt; The first PAC-handling protocol change since Windows 2000&apos;s introduction of the PAC. After full enforcement, every PAC carries an additional Full PAC Signature covering the entire encoded structure, not just sub-pieces; Diamond and Sapphire variants that previously evaded validation by tampering with un-covered fields now fail [@cve-2022-37967] [@ms-kb-5021131].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MachineAccountQuota = 0 guidance (KB5008383, November 2021) [@ms-kb-5008383].&lt;/strong&gt; The dispositive RBCD defence as a configuration: setting the directory-wide &lt;code&gt;ms-DS-MachineAccountQuota&lt;/code&gt; attribute on the domain root to zero prevents non-administrative users from creating computer accounts at all, which kills the first step of the chain in Section 1&apos;s Hook.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Each defensive control patches a primitive. No control patches the structural property of the protocol -- that any long-term symmetric key is forge-equivalent for every ticket type that key signs, and that the protocol&apos;s offline-validation guarantee makes online ticket revocation incompatible with the design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Defence&lt;/th&gt;
&lt;th&gt;Target Primitive&lt;/th&gt;
&lt;th&gt;Structural Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Protected Users [@ms-protected-users]&lt;/td&gt;
&lt;td&gt;Pass-the-Hash, Pass-the-Ticket, RC4 pre-auth&lt;/td&gt;
&lt;td&gt;Breaks delegation, RC4, and NTLM; four-hour TGT cap may break legacy apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication Policy Silo [@ms-protected-users]&lt;/td&gt;
&lt;td&gt;Per-tier scope of Protected-Users behaviour&lt;/td&gt;
&lt;td&gt;Requires Server 2012 R2 DFL; FAST armoring requires Server 2012 R2 too&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential Guard&lt;/td&gt;
&lt;td&gt;LSASS memory theft (Mimikatz &lt;code&gt;sekurlsa::&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Does not prevent ticket theft via legitimate Kerberos APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FAST (RFC 6113) [@rfc6113]&lt;/td&gt;
&lt;td&gt;PA-ENC-TIMESTAMP offline cracking&lt;/td&gt;
&lt;td&gt;Client opt-in; not on by default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gMSA [@ms-gmsa]&lt;/td&gt;
&lt;td&gt;Kerberoasting on service accounts&lt;/td&gt;
&lt;td&gt;Human-managed service accounts unaffected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LDAP signing + channel binding&lt;/td&gt;
&lt;td&gt;KrbRelayUp [@krbrelayup]&lt;/td&gt;
&lt;td&gt;Off by default in older domains&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KrbtgtFullPacSignature [@cve-2022-37967]&lt;/td&gt;
&lt;td&gt;Diamond and most Sapphire variants&lt;/td&gt;
&lt;td&gt;Does not stop Sapphire variants whose tampered PAC was issued legitimately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MachineAccountQuota = 0&lt;/td&gt;
&lt;td&gt;RBCD chain [@shenanigans-rbcd]&lt;/td&gt;
&lt;td&gt;Default value is &lt;code&gt;10&lt;/code&gt;; setting requires admin action&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Read the table the way an attacker reads it. Each row is necessary; no row is sufficient. The &quot;structural limit&quot; column is the next-attack catalogue. Protected Users does not stop a Diamond Ticket forged from a stolen KRBTGT key. Credential Guard does not stop the operator who has SYSTEM on a domain controller. FAST does not stop AS-REP Roasting (because AS-REP Roasting only happens on accounts with pre-auth disabled, where FAST is moot). gMSA does not protect a service account someone still manages manually with a Notes-saved password.&lt;/p&gt;
&lt;p&gt;The pattern is the answer to the section&apos;s opening question. Every control attacks one primitive -- a key, a flag, a coercion path, a ticket lifetime -- and none of them closes &lt;em&gt;the&lt;/em&gt; protocol-level structural property that any long-term symmetric key in the domain is forge-equivalent for any ticket type that key signs. By 2022 the engineering catalogue was complete. The 2023 announcement was the first plan that targeted the structure.&lt;/p&gt;
&lt;p&gt;What would a structural fix even look like, given that any &quot;online revocation&quot; change would also give up Kerberos&apos;s O(1) service-side validation, and given that any &quot;deprecate the long-term key&quot; change has to back-compat to clients that have not been touched since Server 2008? The October 2023 Palko post had answers.&lt;/p&gt;
&lt;h2&gt;6. The Breakthrough: Closing the Domainless Gap&lt;/h2&gt;
&lt;p&gt;October 11, 2023. Matthew Palko, Microsoft&apos;s Principal Group Product Manager for Windows authentication, publishes &quot;The evolution of Windows authentication&quot; on the Windows IT Pro Blog. The article&apos;s &lt;code&gt;&amp;lt;meta property=&quot;article:modified_time&quot;&amp;gt;&lt;/code&gt; reads &lt;code&gt;2023-11-11T01:30:49.108-08:00&lt;/code&gt; in the raw HTML; the description metadata reads &quot;Discover how we&apos;re securing authentication and reducing NTLM usage in Windows&quot; [@ms-palko-evolution]. It is the first time Microsoft commits publicly to deprecating NTLM, and the first time Microsoft names the three load-bearing engineering features that move Kerberos from &quot;domain-only&quot; to &quot;load-bearing-for-everything&quot;.&lt;/p&gt;
&lt;p&gt;The plan has four moving parts. Each one closes a specific reason that NTLM survived for thirty years.&lt;/p&gt;
&lt;h3&gt;IAKerb: Kerberos without KDC line-of-sight&lt;/h3&gt;
&lt;p&gt;The structural reason NTLM lived through Server 2003, Server 2008, Server 2012, and Server 2019 is that Windows had no Kerberos-equivalent path for the case where a client cannot reach a KDC. A laptop on a hotel network, a hybrid Azure-joined workstation that can reach the application server but not the AD DC, a workgroup machine attempting to access a domain file share -- all of those flowed back to NTLM by default, because Kerberos required a working AS-REQ to the domain controller before it could mint a TGT.&lt;/p&gt;
&lt;p&gt;IAKerb (Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API) closes that gap. The draft IETF specification, draft-ietf-kitten-iakerb, is by Benjamin Kaduk, Jim Schaad, Larry Zhu, and Jeffrey E. Altman [@iakerb-draft]. The mechanism is GSS-API encapsulation: the client wraps each AS-REQ, AS-REP, TGS-REQ, and TGS-REP message inside a GSS-API token addressed to the application server, and the application server proxies the token to the KDC the server &lt;em&gt;can&lt;/em&gt; reach. From the client&apos;s perspective, it is talking to the application server; from the KDC&apos;s perspective, the AS exchange came from the application server. The protocol&apos;s verbatim problem statement reads: &quot;encapsulating the Kerberos messages inside GSS-API tokens. With these extensions a client can obtain Kerberos tickets for services where the KDC is not accessible to the client, but is accessible to the application server&quot; [@iakerb-draft].&lt;/p&gt;

Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API. An extension to GSS-API Kerberos (RFC 4121) that encapsulates Kerberos AS / TGS exchanges inside GSS-API tokens between client and application server, so the application server can proxy them to a KDC the server can reach but the client cannot. Documented in the IETF draft `draft-ietf-kitten-iakerb` by Kaduk, Schaad, Zhu, and Altman [@iakerb-draft].

A Kerberos Key Distribution Center implemented as an in-process service inside the local Windows Security Authority (LSASS) on a workgroup or Azure-joined machine. The Local KDC issues tickets backed by the local SAM password database, exposing no Kerberos port to the network; clients reach it only through IAKerb encapsulation tunnelled through the application protocol. Closes the &quot;local account auth has no KDC&quot; gap that has kept NTLM alive for workgroups since Windows NT 3.1 [@ms-palko-evolution] [@fosdem-localkdc].
&lt;p&gt;MIT krb5 added IAKERB support fifteen years ago. The README for krb5-1.9, released December 22, 2010, says verbatim: &quot;Add support for IAKERB -- a mechanism for tunneling Kerberos KDC transactions over GSS-API, enabling clients to authenticate to services even when the clients cannot directly reach the KDC that serves the services&quot; [@mit-krb5-19-readme] [@mit-krb5-19-page]. The capability sat in MIT&apos;s mainline Kerberos for over a decade. Windows did not ship the equivalent because, until NTLM was on a deprecation path, Windows did not need it -- NTLM filled the line-of-sight gap. Once NTLM was on the road to removal, IAKerb stopped being optional.
The sixteen-year gap between MIT krb5-1.9 IAKERB (December 22, 2010) and Microsoft&apos;s planned H2 2026 broad enable is the cleanest evidence that Microsoft&apos;s NTLM deprecation is the &lt;em&gt;forcing function&lt;/em&gt; for the Kerberos refit, not a side effect. The specification was waiting for the customer demand to catch up.&lt;/p&gt;
&lt;h3&gt;Local KDC: Kerberos for the workgroup&lt;/h3&gt;
&lt;p&gt;The second structural reason NTLM survived was that Windows local accounts had no concept of &quot;domain&quot;. Without an AD domain, there was no KDC. Without a KDC, there were no Kerberos tickets. Local-account authentication therefore flowed through NT challenge-response (NTLMv2) by default.&lt;/p&gt;
&lt;p&gt;Local KDC closes this. The Local KDC, shipping in Windows 11 24H2 and Server 2025 with broad enablement targeted for H2 2026 [@ms-palko-evolution], is a Kerberos KDC built directly on top of the local SAM database. LSA derives an AES-256 long-term key from the local account&apos;s password rather than persisting the legacy RC4 NT hash. The Local KDC exposes no listening Kerberos port; clients reach it only through IAKerb encapsulation inside the application protocol (SMB, RDP, HTTP).&lt;/p&gt;
&lt;p&gt;The parallel open-source path was demonstrated by Alexander Bokovoy and Andreas Schneider at FOSDEM 2025, where they presented &quot;localkdc: A General Local Authentication Hub&quot; [@fosdem-localkdc]. The abstract reads verbatim: &quot;A local Kerberos Key Distribution Center (KDC) is not a new invention. It is a useful tool in combination with the Kerberos IAKerb extension but also allows to map SSO from a web authentication to local authentication or in a network environment isolated from the rest of the enterprise environment ... how use of NTLM in SMB protocol will be replaced by a localkdc in combination with IAKerb&quot; [@fosdem-localkdc]. Samba 4.21 carries the prototype implementation.&lt;/p&gt;

The Bokovoy / Schneider talk is the cleanest external evidence that Local KDC is a *protocol-level* architecture, not a Microsoft-proprietary one. Samba, Heimdal, MIT krb5, and Microsoft are converging on the same design: an in-process KDC, GSS-API-tunnelled Kerberos exchanges, AES-keyed local accounts. The IETF draft-ietf-kitten-iakerb specification [@iakerb-draft] is the shared standardisation layer.

Add support for IAKERB -- a mechanism for tunneling Kerberos KDC transactions over GSS-API, enabling clients to authenticate to services even when the clients cannot directly reach the KDC that serves the services. -- MIT krb5-1.9 release notes, December 22, 2010 [@mit-krb5-19-readme]
&lt;h3&gt;PKINIT and the freshness extension&lt;/h3&gt;
&lt;p&gt;The third gap NTLM filled was non-password credentials. Windows Hello for Business, smart cards, and Federal Information Processing Standard token logon all need to translate &quot;I hold this private key&quot; into &quot;I hold this Kerberos TGT&quot;. PKINIT (Public Key Cryptography for Initial Authentication in Kerberos), RFC 4556, by Larry Zhu (Microsoft) and Brian Tung (Aerospace Corporation), is the protocol for that [@rfc4556]. The AS-REQ carries a &lt;code&gt;PA-PK-AS-REQ&lt;/code&gt; PA-DATA element wrapping an &lt;code&gt;AuthPack&lt;/code&gt; CMS structure signed by the client&apos;s private key; the AS-REP carries the TGT keyed for the client to decrypt with either RSA key transport or Diffie-Hellman key exchange.&lt;/p&gt;
&lt;p&gt;The 2006 RFC 4556 PKINIT had a replay window: an attacker who recorded a &lt;code&gt;signedAuthPack&lt;/code&gt; could replay it indefinitely until the client&apos;s certificate expired. RFC 8070, &quot;PKINIT Freshness Extension,&quot; by Michiko Short, Seth Moore, and Peter Miller of Microsoft (February 2017) closed it [@rfc8070]. The AS-REP issues an opaque &lt;code&gt;PA-AS-FRESHNESS&lt;/code&gt; blob in a preliminary KDC-error round-trip; the client must echo the blob in its next signed AS-REQ; replays after the freshness window fail. Verbatim from RFC 8070 abstract: &quot;exchange an opaque data blob that a Key Distribution Center (KDC) can validate to ensure that the client is currently in possession of the private key during a PKINIT Authentication Service (AS) exchange&quot; [@rfc8070].&lt;/p&gt;
&lt;p&gt;Together, RFC 4556 plus RFC 8070 anchor every modern non-password Windows credential: Windows Hello for Business, smart-card logon, FIDO2 keys mediated by Windows Hello, and the upcoming Entra-issued cloud TGTs. The 2022 Certifried CVE [@cve-2022-26923] forced the &lt;em&gt;strong-mapping&lt;/em&gt; layer on top of all of this: every certificate used for PKINIT must carry an X.509 extension binding it to a specific AD account SID. KB5014754 [@ms-kb-5014754] tracks the rollout; see §4 for the full Compatibility / Enforcement / rollback-removal date sequence.&lt;/p&gt;
&lt;h3&gt;FAST armoring as default&lt;/h3&gt;
&lt;p&gt;The fourth gap was the trust assumption at the start of an AS-REQ: the encrypted-timestamp pre-auth blob, &lt;code&gt;PA-ENC-TIMESTAMP&lt;/code&gt;, is keyed under the client&apos;s password-derived key, which is offline-crackable on observation. FAST (RFC 6113) wraps the AS-REQ inside an armor envelope keyed under a separate key the attacker does not see [@rfc6113]. In a domain-joined client the armor key is derived from the machine account&apos;s TGT; in a non-domain-joined client it is derived from an anonymous PKINIT TGT; in a compound-identity scenario it is the combination of both.&lt;/p&gt;
&lt;p&gt;What changes in the 2023 plan is the &lt;em&gt;default-on&lt;/em&gt; posture: Authentication Policy Silos can now require FAST for every AS-REQ from a silo member, and Local KDC clients use anonymous PKINIT armoring out of the box because the SAM-derived long-term key is the only credential available and offline-crackability would be catastrophic.&lt;/p&gt;

sequenceDiagram
    participant C as Client (no KDC reach)
    participant S as Application Server
    participant KDC as KDC (reachable from S)
    C-&amp;gt;&amp;gt;S: GSS-API token: IAKerb (AS-REQ wrapper)
    S-&amp;gt;&amp;gt;KDC: AS-REQ (forwarded)
    KDC-&amp;gt;&amp;gt;S: AS-REP (forwarded)
    S-&amp;gt;&amp;gt;C: GSS-API token: IAKerb (AS-REP wrapper)
    C-&amp;gt;&amp;gt;S: GSS-API token: IAKerb (TGS-REQ wrapper)
    S-&amp;gt;&amp;gt;KDC: TGS-REQ (forwarded)
    KDC-&amp;gt;&amp;gt;S: TGS-REP (forwarded)
    S-&amp;gt;&amp;gt;C: GSS-API token: IAKerb (TGS-REP wrapper)
    C-&amp;gt;&amp;gt;S: AP-REQ presenting service ticket
    S-&amp;gt;&amp;gt;C: AP-REP -- session established
&lt;h3&gt;The Gap-to-Closure Mapping&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;NTLM-fallback gap&lt;/th&gt;
&lt;th&gt;Engineered closure&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;th&gt;Ship target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Client has no KDC line-of-sight&lt;/td&gt;
&lt;td&gt;IAKerb GSS-API encapsulation&lt;/td&gt;
&lt;td&gt;[@iakerb-draft]&lt;/td&gt;
&lt;td&gt;Windows 11 24H2 / Server 2025; broad enable H2 2026 [@ms-palko-evolution]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local accounts have no domain KDC&lt;/td&gt;
&lt;td&gt;Local KDC on SAM + AES-256 derivation&lt;/td&gt;
&lt;td&gt;[@ms-palko-evolution] [@fosdem-localkdc]&lt;/td&gt;
&lt;td&gt;Windows 11 24H2 / Server 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-password credentials need an AS path&lt;/td&gt;
&lt;td&gt;PKINIT (RFC 4556) + Freshness (RFC 8070) + strong mapping (KB5014754)&lt;/td&gt;
&lt;td&gt;[@rfc4556] [@rfc8070] [@ms-kb-5014754]&lt;/td&gt;
&lt;td&gt;Enforcement February 11, 2025; Disabled mode removed April 2023; Compatibility mode removed Sept 9, 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AS-REQ pre-auth is offline-crackable&lt;/td&gt;
&lt;td&gt;FAST armoring (RFC 6113) default-on in silos&lt;/td&gt;
&lt;td&gt;[@rfc6113]&lt;/td&gt;
&lt;td&gt;Available since Server 2012 R2; default-on with new silos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;After thirty-three years of layered extensions, Kerberos in 2026 is finally a single-protocol authentication path for every Windows scenario. Domain-joined, workgroup, Azure-joined without AD line-of-sight, local-account to local-account. The mechanism that closes the last gap -- IAKerb -- is a sixteen-year-old MIT protocol coming to Windows for the first time. What&apos;s left for Kerberos to fix is encryption-type hygiene, and a December 2025 Microsoft post named the calendar dates for that too.&lt;/p&gt;
&lt;h2&gt;7. The Beyond-RC4 Cadence&lt;/h2&gt;
&lt;p&gt;December 3, 2025. The Microsoft Windows Server Blog publishes &quot;Beyond RC4 for Windows authentication&quot; [@ms-beyond-rc4]. The post is short and specific. Verbatim: &quot;By mid-2026, we will be updating the domain controller default assumed supported encryption types. The assumed supported encryption types is applied to service accounts that do not have an explicit configuration defined. Secure Windows authentication does not require RC4; AES-SHA1 can be used across all supported Windows versions since it was introduced in Windows Server 2008&quot; [@ms-beyond-rc4]. For the first time in twenty years, RC4-HMAC is on a removal cadence with a calendar date and an enforcement CVE.&lt;/p&gt;
&lt;p&gt;The rollout has three phases.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 1, January 2026, audit only.&lt;/strong&gt; Domain controllers gain new fields in Event ID 4768 (TGT issued) and Event ID 4769 (TGS issued): &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt;, &lt;code&gt;Available Keys&lt;/code&gt;, and &lt;code&gt;Session Encryption Type&lt;/code&gt;. The fields tell an administrator, for each ticket issued, which enctypes the requesting account had configured and which one the KDC actually chose. Two new PowerShell auditing scripts ship in the &lt;code&gt;microsoft/Kerberos-Crypto&lt;/code&gt; GitHub repository: &lt;code&gt;List-AccountKeys.ps1&lt;/code&gt; enumerates every account and the enctype configuration on each; &lt;code&gt;Get-KerbEncryptionUsage.ps1&lt;/code&gt; parses the 4768 / 4769 log stream and prints accounts still requesting or being issued RC4 tickets [@ms-beyond-rc4]. Verbatim from the post: &quot;we have enhanced existing information within the Security Event Log and developed new PowerShell auditing scripts. These enhancements are available in Windows Server versions 2019, 2022, and 2025&quot; [@ms-beyond-rc4].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 2, April 2026, default flip.&lt;/strong&gt; The &quot;assumed&quot; &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; on accounts that have no explicit setting changes from &quot;anything the client asks for, including RC4&quot; to &quot;AES-SHA1 only&quot;. AES-SHA1 (RFC 3962 enctypes 17 and 18) has shipped on every supported Windows version since Server 2008 [@rfc3962], so the flip is theoretically backward-compatible with every domain-joined client; in practice the casualties are third-party Kerberos clients (legacy Linux MIT krb5 with RC4-only keytabs, network-attached-storage appliances stuck on older krb5 libraries, SQL Server linked servers with manually-configured service-principal RC4 entries).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Phase 3, mid-2026, enforcement.&lt;/strong&gt; RC4 tickets require explicit per-account opt-in. The enforcement boundary is &lt;em&gt;CVE-2026-20833&lt;/em&gt;, called out by name in the Microsoft post [@ms-beyond-rc4]. After that date, an account that has not had &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; explicitly written to include &lt;code&gt;0x4&lt;/code&gt; (RC4) will not be issued RC4 tickets, and DCs will reject any TGS-REQ that asks for one against an account configured AES-only.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The mid-2026 RC4-default removal is gated on CVE-2026-20833, named in the December 2025 &quot;Beyond RC4&quot; post as the enforcement boundary [@ms-beyond-rc4]. The audit window closes when this date lands. Production environments that have not migrated their service accounts to gMSA or explicitly set &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; will find Kerberos authentication failing for those accounts the day Phase 3 ships.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The interesting question is why the migration destination is AES-SHA1 (enctypes 17 and 18) and not AES-SHA2 (enctypes 19 and 20). RFC 8009 specifies AES-SHA2 [@rfc8009]; Microsoft&apos;s &lt;code&gt;[MS-KILE]&lt;/code&gt; §2.2.7 supported-encryption-types bit table includes bits K (&lt;code&gt;AES128-CTS-HMAC-SHA256-128&lt;/code&gt;) and L (&lt;code&gt;AES256-CTS-HMAC-SHA384-192&lt;/code&gt;) [@ms-kile-227]. Linux MIT krb5 has shipped RFC 8009 since version 1.15 (December 2016) [@mit-krb5-115]. Cross-domain interoperability between AES-SHA2 Windows and AES-SHA2 MIT works. The remaining work is purely Microsoft-side default enablement and the auditing infrastructure analogous to the RC4 cadence.&lt;/p&gt;
&lt;p&gt;The Beyond-RC4 post does not name an AES-SHA1 -&amp;gt; AES-SHA2 timeline at all. The audit-default-enforce cadence Microsoft has now demonstrated for RC4 -- audit instrumentation in event logs, default flip with backward-compatible enctypes, enforcement gated by a named CVE -- has no announced analogue for AES-SHA1 yet.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The cadence Microsoft has is audit, default, enforce. The RC4 to AES-SHA1 transition has all three: audit instrumentation in Phase 1, the default flip in Phase 2, and named enforcement via CVE-2026-20833 in Phase 3. The AES-SHA1 to AES-SHA2 transition has none. The [MS-KILE] bits exist; the cross-domain interoperability works; the Microsoft-side rollout is the missing piece.
The &lt;code&gt;microsoft/Kerberos-Crypto&lt;/code&gt; GitHub repository ships the two PowerShell auditing scripts (&lt;code&gt;List-AccountKeys.ps1&lt;/code&gt;, &lt;code&gt;Get-KerbEncryptionUsage.ps1&lt;/code&gt;) that the December 2025 post names as the Phase 1 instrumentation. They are the right tools for an administrator who wants to find their RC4-dependent service accounts before the audit window closes mid-2026 [@ms-beyond-rc4].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mid-2026 is the audit-window-closes date. The question for every AD operator is &lt;em&gt;which&lt;/em&gt; of their service accounts will still be requesting RC4 tickets when the default flips, and whether their detection tooling sees them in the window. Two quarters from now, the answer &quot;we&apos;ll just turn RC4 off and see what breaks&quot; stops being a defensible operating posture.&lt;/p&gt;

timeline
    title Beyond-RC4 rollout
    section Phase 1 -- Audit
      Jan 2026 : Event 4768 / 4769 fields msDS-SupportedEncryptionTypes Available Keys Session Encryption Type
      Jan 2026 : Kerberos-Crypto GitHub repo with List-AccountKeys.ps1 and Get-KerbEncryptionUsage.ps1
    section Phase 2 -- Default flip
      Apr 2026 : Assumed msDS-SupportedEncryptionTypes flips to AES-SHA1-only for accounts without explicit configuration
    section Phase 3 -- Enforcement
      Mid 2026 : CVE-2026-20833 enforcement boundary -- RC4 tickets require explicit per-account opt-in
&lt;h2&gt;8. What Removing NTLM Cannot Buy You&lt;/h2&gt;
&lt;p&gt;After everything in Section 6 and Section 7 ships, Kerberos in 2026 is still vulnerable to four classes of attack. None of them are protocol bugs; all of them are protocol &lt;em&gt;structure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kerberos has its own relay class.&lt;/strong&gt; The KrbRelayUp README explicitly scopes itself to Windows domain environments where LDAP signing is not enforced -- the post-NTLM cousin of NTLM-relay [@krbrelayup]. The relay primitive survives the move from NTLM to Kerberos because the attack does not target the authentication protocol -- it targets the LDAP protocol&apos;s lack of mandatory integrity, and any authenticated bind (Kerberos or NTLM) is fair game once the channel is unsigned. The dispositive control is LDAP signing plus channel binding domain-wide, plus Extended Protection for Authentication on every AD CS Web Enrolment endpoint. It is a configuration, not a protocol fix. The &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLMless&lt;/a&gt; companion article walks through the LDAP-side work in detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The long-term-key problem is intrinsic to symmetric Kerberos.&lt;/strong&gt; Whoever holds the &lt;code&gt;krbtgt&lt;/code&gt; account&apos;s long-term key forges any TGT (the Golden Ticket primitive). Whoever holds an SPN account&apos;s long-term key forges any TGS for that service (the Silver Ticket primitive). RFC 4120&apos;s offline-validation property [@rfc4120] &lt;em&gt;requires&lt;/em&gt; that the service trust the key alone -- the AP-REQ contains no callback to the KDC; the service decrypts the ticket, validates the signatures, and decides. Any change that adds an online &quot;is this ticket still valid?&quot; check also gives up Kerberos&apos;s O(1) service-side scaling and the offline-validation guarantee that makes the protocol cheap. Authentication Policy Silos, Protected Users, TPM-backed credentials, and Credential Guard all raise the cost of obtaining the key; they do not close the forge-equivalence property. Mathematically, if you have the key, you are the principal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The PAC is a signed vouching token, not a verified live query.&lt;/strong&gt; KrbtgtFullPacSignature [@cve-2022-37967] closes the &lt;em&gt;modification&lt;/em&gt; side of Diamond and Sapphire. It does not close the &lt;em&gt;staleness&lt;/em&gt; side. A user removed from &lt;code&gt;Domain Admins&lt;/code&gt; at 09:00 still presents service tickets attesting Domain Admin membership until the ticket expires (default 10 hours user TGT, 7 days renewable; Protected Users members are capped at 4 hours [@ms-protected-users]). The PAC vouching window is the residual stale-authorization gap. The defender&apos;s option is shorter ticket lifetimes or out-of-band ACL flips at the service tier; the protocol itself has no callback by which a service learns about a group-membership change before the ticket expires.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Domainless does not mean keyless.&lt;/strong&gt; Local KDC binds the SAM password to an AES-256 long-term key. The wire form of pass-the-hash is gone: there is no NT hash on the line, no &lt;code&gt;LMv2&lt;/code&gt; challenge response, no DES-CBC-MD5 keytab. But a &lt;code&gt;NT AUTHORITY\SYSTEM&lt;/code&gt;-level attacker on the box still recovers the AES key, because LSA must materialise that key in user-mode memory to hand it to Kerberos. The chip- and VBS-based countermeasures (TPM-backed credentials, Microsoft Pluton, Credential Guard) remain orthogonal and necessary; none of them is replaced by Local KDC.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; H2 2026 ships Kerberos as the load-bearing single authentication protocol; it does not ship a Kerberos in which (1) the Kerberos-relay class is closed, (2) long-term-key forge-equivalence is closed, (3) PAC staleness is closed, or (4) local-key recovery from a SYSTEM-level attacker on the box is closed. The arc is a transition between tradeoffs, not out of them.&lt;/p&gt;
&lt;/blockquote&gt;

The Phase-3-as-transition-between-tradeoffs framing is mirrored in the [NTLMless](/blog/ntlmless-the-death-of-ntlm-in-windows/) companion article&apos;s Section 8 -- the symmetric framing is deliberate. Read the two articles together as a paired diagnosis: NTLMless is the eulogy and the migration story; this article is the inheritance and the to-do list.
&lt;h2&gt;9. Open Problems and the 2026-2027 Edge&lt;/h2&gt;
&lt;p&gt;Five problems sit on the May-2026 research agenda. None has a shipping Microsoft answer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The AES-SHA1 to AES-SHA2 Windows-default timeline.&lt;/strong&gt; RFC 8009 [@rfc8009] is nine years old. The &lt;code&gt;[MS-KILE]&lt;/code&gt; §2.2.7 supported-encryption-types bit table already includes the AES-SHA2 bits K and L [@ms-kile-227]. Linux MIT krb5 shipped RFC 8009 in version 1.15 (December 2016) [@mit-krb5-115]. Cross-domain Kerberos interop between MIT clients and Windows DCs over AES-SHA2 works in the laboratory. What is missing is a Microsoft-side equivalent of the audit / default / enforce cadence already in place for the RC4 transition, especially because the hard part is not the cryptography but the long tail of third-party Kerberos clients and pre-2017 keytabs that an AES-SHA2 audit would have to enumerate before the default can flip. The 8009 cadence is the largest Windows-side cryptographic gap that has no announcement.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Quantum risk.&lt;/strong&gt; Kerberos symmetric primitives (AES-128 and AES-256) retain a Grover-bound effective security margin of 64 and 128 bits respectively, which is durable against the near-term cryptographically-relevant quantum computer. PKINIT is the exposed half: the CMS signature chains in &lt;code&gt;AuthPack&lt;/code&gt; are RSA or ECDSA per RFC 4556 §3.2 [@rfc4556], and both are broken by Shor&apos;s algorithm. Anonymous PKINIT, used for FAST armoring on non-domain-joined clients, has the same exposure. Microsoft has not announced a PKINIT-specific post-quantum cryptography plan; the Kerberos team&apos;s standardisation tracking sits on the IETF kitten working group&apos;s queue rather than on a shipping Windows roadmap. Cross-link to the post-quantum cryptography sibling article in this series.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;dMSA field-deployment maturity.&lt;/strong&gt; Server 2025 introduced Delegated Managed Service Accounts as the successor to gMSA [@ms-dmsa]. The protocol-level differences -- &quot;Authentication for dMSA is linked to the device identity ... dMSA uses a randomized secret (derived from the machine account credential) that is held by the Domain Controller (DC) to encrypt tickets&quot; -- close several gMSA gaps, including the multi-tenant-key problem. But the 14-day account-migration window, the four-ticket-lifetime startup state during which both the legacy account and the dMSA can authenticate, and the cross-domain plus cross-forest behaviours are still being shaken out in field deployments. As of the May 2026 reading, dMSA is shipping but not yet the default for new service accounts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-cloud Kerberos.&lt;/strong&gt; Kerberos Cloud Trust for Windows Hello for Business is the architectural piece that lets an Azure-joined laptop obtain TGTs from Entra ID rather than from an on-premises DC, with the on-premises DC trusting Entra&apos;s signatures via federation. Per [@ms-palko-evolution] the architecture is planned but unproven in the field at scale. The role of Local KDC in pure-Entra (no AD on-prem) deployments is still being defined. The trust graph for &quot;Local KDC + Entra ID + on-premises AD&quot; is one of the open architectural problems the Palko post mentions but does not yet detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Open-source IAKerb and Local KDC.&lt;/strong&gt; Samba&apos;s &lt;code&gt;localkdc&lt;/code&gt; work, demonstrated by Alexander Bokovoy and Andreas Schneider at FOSDEM 2025 [@fosdem-localkdc], is the most public open-source mirror of Microsoft&apos;s Local KDC plan. Heimdal has a partial implementation. MIT krb5 IAKERB has been shipping since krb5-1.9 on December 22, 2010 [@mit-krb5-19-readme] and is mature. The Local-KDC-on-the-SAM pattern is new to the Windows world specifically; in the open-source world the equivalent (a Kerberos KDC fed from a local user database) has existed in textbooks since Kerberos v4.&lt;/p&gt;
&lt;p&gt;Each of the five problems is a residual. Each is the next decade&apos;s research. None of them invalidates the Phase 3 shipping commitment. The article&apos;s load-bearing closing claim is honest about that: H2 2026 is a &lt;em&gt;transition&lt;/em&gt;, and what comes next will be its own multi-year cadence.&lt;/p&gt;
&lt;h2&gt;10. What an AD Engineer Should Do This Quarter&lt;/h2&gt;
&lt;p&gt;If you read nothing else from this article, read this. Seven controls; each one is tied to one primary Microsoft Learn or MSRC URL; each one closes one of the attack primitives in Section 4. Cross-link to the parallel practical-guide section in the &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLMless&lt;/a&gt; companion article.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Run the two PowerShell scripts in &lt;code&gt;microsoft/Kerberos-Crypto&lt;/code&gt;: &lt;code&gt;List-AccountKeys.ps1&lt;/code&gt; enumerates every account&apos;s configured enctypes; &lt;code&gt;Get-KerbEncryptionUsage.ps1&lt;/code&gt; parses your Event 4768 / 4769 stream and lists accounts still requesting or being issued RC4 tickets. The audit window closes mid-2026 when Phase 2 flips the default [@ms-beyond-rc4]. Every account on the list above is a Phase-3 production incident if you do nothing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Do not rely on the mid-2026 default flip. Explicitly write &lt;code&gt;msDS-SupportedEncryptionTypes&lt;/code&gt; with the value &lt;code&gt;0x18&lt;/code&gt; (AES-128 + AES-256, no RC4) on every service account that does not have a documented RC4 dependency. For service accounts that do, write &lt;code&gt;0x1C&lt;/code&gt; (AES-128 + AES-256 + RC4) and put a calendar reminder against the RC4 dependency so it gets remediated before Phase 3 [@ms-beyond-rc4].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Manually-managed service-account passwords are the Kerberoasting attack surface per [@ms-kerberoasting-guidance]. gMSA gives you 240-character KDS-derived passwords rotated every 30 days [@ms-gmsa]. dMSA on Server 2025 binds the account secret to the device identity and stores it only on the domain controller, where it can be further protected by Credential Guard [@ms-dmsa]. There is no service-account workflow gMSA or dMSA does not cover; the migration is operational, not architectural.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Setting &lt;code&gt;ms-DS-MachineAccountQuota&lt;/code&gt; on the domain root to zero kills the first step of the RBCD chain in Section 1 [@shenanigans-rbcd] and the KrbRelayUp chain [@krbrelayup]. The default value of 10 has been the de facto attack-surface enabler since Windows 2000. The control is one PowerShell line: &lt;code&gt;Set-ADDomain -Identity (Get-ADDomain) -Replace @&amp;amp;#123;&apos;ms-DS-MachineAccountQuota&apos;=0&amp;amp;#125;&lt;/code&gt;. The breakage surface is small: only legitimate computer-account bootstrap workflows that today rely on user-driven &lt;code&gt;djoin.exe&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Protected Users gives every member the five non-configurable client protections plus the 4-hour TGT cap [@ms-protected-users]. Wrap an Authentication Policy Silo around the same population to add mandatory FAST armoring [@rfc6113] and per-silo logon-from constraints. Both controls have been available since Server 2012 R2; the operational reason most environments still have not adopted them is the breakage in legacy delegation workflows. Audit and remediate those workflows; do not skip Protected Users.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Set &lt;code&gt;LDAPServerIntegrity = 2&lt;/code&gt; (require signing) and &lt;code&gt;LdapEnforceChannelBinding = 2&lt;/code&gt; (require channel binding on TLS-bound connections) via Group Policy. This is the dispositive KrbRelayUp defence [@krbrelayup] and the dispositive defence against any Kerberos-relay-class attack that targets the LDAP control plane. Pair with Extended Protection for Authentication on every AD CS Web Enrolment endpoint to close the Certifried-style certificate-issuance variant [@ms-kb-5014754].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Flight the &lt;code&gt;RC4DefaultDisablementPhase&lt;/code&gt; Group Policy setting in your Insider channel; pilot non-production AES-only configurations on a representative subset of service accounts; identify legacy NAS appliances, Linux MIT krb5 clients with keytabs older than 2017, and SQL Server linked-server SPNs before Phase 2 closes the audit window [@ms-beyond-rc4]. Phase 3 ships with CVE-2026-20833; production environments that have not run the audit will discover the dependency list the day enforcement lands.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Three quarters from now (mid-2026), every default in this list will have changed. Do the work in the audit window or do it in the post-flip ticket queue. The cost of an audit-window migration is a quarter of engineering time; the cost of a post-flip remediation is a sixty-minute outage on every undocumented RC4 dependency the directory holds. Cross-link to the &lt;a href=&quot;https://paragmali.com/blog/pluton-a-tpm-on-silicon-microsoft-can-patch/&quot; rel=&quot;noopener&quot;&gt;Pluton&lt;/a&gt;, TPM, and Credential Guard sibling articles for the hardware-backing layer that protects the long-term keys these controls assume.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

AES-SHA1 (RFC 3962 enctypes 17 and 18) is enough against the 2026 attack picture: there is no known cryptographic attack against AES-256-CTS-HMAC-SHA1-96 within Kerberos&apos;s threat model, and AES eliminates the salt-less / iteration-less Kerberoasting weakness of RC4-HMAC [@rfc3962] [@ms-kerberoasting-guidance]. AES-SHA2 (RFC 8009 enctypes 19 and 20) is the obvious next step and is supported by [MS-KILE] bits K and L [@ms-kile-227]. Quantum threats are not the immediate worry for symmetric Kerberos; the exposed surface is PKINIT, not the ticket cipher.The Grover speedup applied to AES-256 leaves an effective 128-bit security margin, which is durable for the lifetime of any current cryptographic system [@nist-pqc].

Yes, for delegation, and that is the point. Per [@ms-protected-users], members cannot use unconstrained or constrained delegation, cannot use DES or RC4 in Kerberos pre-auth, and have their TGT capped at four hours. Workflows that today rely on a domain admin&apos;s TGT being forwardable to a downstream service must be reworked. Use Authentication Policy Silos for the per-account scope where some delegation must remain.

Yes, with risk. The mid-2026 enforcement boundary CVE-2026-20833 [@ms-beyond-rc4] is the formal cutover. Disabling RC4 today by setting `msDS-SupportedEncryptionTypes` to `0x18` (AES-only) on accounts will work, but expect breakage from Linux clients with MIT krb5 keytabs older than 2017, network-attached-storage appliances with hard-coded RC4 entries, and SQL Server linked-server SPNs that have not been updated. The audit-then-migrate cadence in Section 10 is the operationally honest path.

No. It kills *unsigned-PAC* Golden Tickets and most Diamond and Sapphire variants that tampered with PAC fields outside the original sub-signatures [@cve-2022-37967]. If an attacker has the actual `krbtgt` long-term key, they still mint correctly-signed tickets -- the Full PAC Signature is computed with that same key. The defence is rapid `krbtgt` rotation (the dual-password scheme means you must rotate twice with an interval) plus Credential Guard to keep the key out of LSASS user-mode memory.

PKINIT [@rfc4556] exists, Active Directory Certificate Services exists, Windows Hello for Business is built on top of PKINIT. The reason &quot;everywhere&quot; was hard is Certifried (CVE-2022-26923) [@cve-2022-26923] and the strong-mapping retrofit [@ms-kb-5014754]: the original ADCS templates allowed a certificate&apos;s Subject Alternative Name to be set independently of the AD account that requested the certificate, which let an attacker mint a certificate claiming to be a domain controller. Strong mapping (the SID-binding X.509 extension) closed that, but the rollout took years to land in Enforcement mode (see §4 for the full date sequence).

It eliminates the *wire* form. There is no NT hash on the LSA-to-Local-KDC path; the long-term key is an AES-256 derivation. A SYSTEM-level attacker on the box still recovers that AES key, because LSA must hold it in user-mode memory to hand to the Kerberos SSP. The chip-side defences (TPM, Microsoft Pluton, Credential Guard) remain orthogonal and necessary per [@fosdem-localkdc]. Local KDC closes the relay-from-the-wire class, not the SYSTEM-on-the-box class.

Kerberos Cloud Trust for Windows Hello for Business issues TGTs from Entra ID and federates trust back to on-premises AD, so an Entra-joined laptop can present a domain-trusted Kerberos ticket to a file server it has never directly authenticated to. The on-premises KDC role is partially federated; the on-prem AD signs nothing for the Entra-issued TGT but trusts Entra&apos;s signature via Cloud Trust. Per [@ms-palko-evolution] the architecture is shipping in stages. The full story is its own article in this series.

Not in this decade. The architectural trajectory is &quot;Kerberos + PKINIT + FAST + Local KDC + IAKerb + Authentication Policy Silos + TPM-backed long-term keys&quot; -- not a replacement protocol. The closest thing to a replacement on the horizon is post-quantum PKINIT, which is more of a re-cipher than a re-protocol. The Kerberos message triple (AS-REQ, TGS-REQ, AP-REQ) is genuinely durable.Compared with the 28-year deprecation cycle NTLM took, replacing Kerberos would be a thirty-year project on the same precedent. Microsoft&apos;s stated direction is to harden the joints, not to throw out the skeleton.

The commands below assume Server 2019 or later with the `microsoft/Kerberos-Crypto` repo cloned locally. Run on a domain controller; output names every account whose configured `msDS-SupportedEncryptionTypes` allows RC4 or has no explicit setting (in which case it inherits the pre-Phase-2 default of &quot;anything goes&quot;). Cross-reference with the 4768 / 4769 audit stream from `Get-KerbEncryptionUsage.ps1` to identify which of those accounts is actually being issued RC4 tickets in practice.&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Enumerate accounts and configured enctypes
Import-Module ActiveDirectory
.\List-AccountKeys.ps1 -OutputCsv accounts.csv

# Parse 4768 / 4769 events for issued ticket enctypes
.\Get-KerbEncryptionUsage.ps1 -LookbackDays 30 -OutputCsv tickets.csv

# Join the two on account name -- the accounts that
# both have RC4-allowed AND were issued RC4 tickets
# are your Phase 3 incident list.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;kerberos-in-windows-the-other-half-of-ntlmless&quot; keyTerms={[
  { term: &quot;Kerberos Domain&quot;, definition: &quot;A Kerberos administrative boundary scoping principals and a single Key Distribution Center; written in uppercase like CONTOSO.COM.&quot; },
  { term: &quot;Ticket-Granting Ticket (TGT)&quot;, definition: &quot;A Kerberos ticket issued by the AS that the client uses to obtain service tickets from the TGS without re-presenting its password.&quot; },
  { term: &quot;Privilege Attribute Certificate (PAC)&quot;, definition: &quot;Microsoft-specific authorization data attached by the KDC to every Windows Kerberos ticket; carries the user&apos;s SID and group SIDs and is covered by three signatures after CVE-2022-37967.&quot; },
  { term: &quot;String-to-Key (s2k)&quot;, definition: &quot;The function converting a password into a Kerberos long-term symmetric key. RC4: MD4(UTF-16-LE(password)). AES: PBKDF2-HMAC-SHA1 at 4,096 iterations.&quot; },
  { term: &quot;Pre-authentication Data (PA-DATA)&quot;, definition: &quot;The extensibility hook in AS-REQ/AS-REP that every Kerberos enhancement since 1993 has used to layer new behaviour on the original protocol.&quot; },
  { term: &quot;Service Principal Name (SPN)&quot;, definition: &quot;A unique identifier for a service instance in AD; any account with an SPN is a Kerberoasting candidate.&quot; },
  { term: &quot;Authentication Policy Silo&quot;, definition: &quot;A scope construct in AD that applies Protected-Users-equivalent constraints to tiered subsets of accounts; enables mandatory FAST armoring per silo.&quot; },
  { term: &quot;IAKerb&quot;, definition: &quot;Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API; encapsulates AS/TGS exchanges inside GSS-API tokens so a client without KDC line-of-sight can authenticate via the application server.&quot; },
  { term: &quot;Local KDC&quot;, definition: &quot;An in-process Kerberos KDC on the local Windows host backed by the SAM database; closes the workgroup and Azure-joined no-KDC-line-of-sight gap that kept NTLM alive.&quot; },
  { term: &quot;Resource-Based Constrained Delegation (RBCD)&quot;, definition: &quot;A delegation model where the target service writes msDS-AllowedToActOnBehalfOfOtherIdentity to authorise who may use S4U2Proxy against it; the structural foundation of the post-NTLM RBCD chain in this article&apos;s Hook.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>kerberos</category><category>active-directory</category><category>windows-security</category><category>authentication</category><category>iakerb</category><category>rc4</category><category>rbcd</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>NTLMless: The Death of NTLM in Windows</title><link>https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/</link><guid isPermaLink="true">https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/</guid><description>Thirty years of pass-the-hash, NTLM relay, PetitPotam, and ESC8 -- and the Kerberos engineering that finally lets Microsoft turn NTLM off by default.</description><pubDate>Sun, 10 May 2026 00:00:00 GMT</pubDate><content:encoded>
**NTLM is the 30-year-old fallback authentication protocol that Active Directory still rests on whenever Kerberos cannot do the job -- and every consequential modern AD attack (pass-the-hash, NTLM relay, PetitPotam, ESC8) lives in that fallback path.** Microsoft&apos;s exit plan (IAKerb, Local KDC, NEGOEX, the Negotiate-everywhere refactor) closes the four reasons NTLM survived, and the January 2026 roadmap names &quot;disabled by default in the next major Windows release&quot; as Phase 3. This article tells the whole arc as one story: how NTLM works on the wire, every attack class against it, exactly what is being removed -- and what is not.
&lt;h2&gt;1. Eight Minutes&lt;/h2&gt;
&lt;p&gt;A defender has done every retrofit Microsoft has shipped over twenty years. SMB signing enforced on every member server. EPA enabled on every IIS endpoint. &lt;a href=&quot;https://paragmali.com/blog/the-windows-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; on. Restrict NTLM in audit mode. KB 5005413 applied to AD CS. An attacker with no credentials joins their network, runs &lt;code&gt;Coercer&lt;/code&gt; against a domain controller, and a handful of seconds later holds a Kerberos ticket-granting ticket for the Domain Admin account [@gh-coercer, @specterops-cert-preowned-blog]. Total elapsed time: less than the time it took you to read this paragraph. Total prerequisites for the chain: that NTLM still exists as a fallback path on Windows.&lt;/p&gt;
&lt;p&gt;The chain has a name. ESC8, from Will Schroeder and Lee Christensen&apos;s &quot;Certified Pre-Owned&quot; whitepaper, published June 17, 2021 [@specterops-cert-preowned-blog, @specterops-cert-preowned-pdf]. Its coercion primitive has another name. PetitPotam, from Lionel Gilles, published the next month. Together they take a fully retrofitted Active Directory environment to Domain Admin in four steps.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 1. &lt;strong&gt;Coerce.&lt;/strong&gt; Call &lt;code&gt;EfsRpcOpenFileRaw&lt;/code&gt; against any Windows server -- including a DC -- over LSARPC. The service, running as SYSTEM, NTLM-authenticates back to an attacker-controlled UNC path. No credentials required. 2. &lt;strong&gt;Relay.&lt;/strong&gt; &lt;code&gt;ntlmrelayx.py&lt;/code&gt; from Impacket sits on the listening side and forwards the live NTLM exchange to the AD CS Web Enrollment endpoint at &lt;code&gt;/certsrv/certfnsh.asp&lt;/code&gt; [@gh-impacket]. 3. &lt;strong&gt;Enroll.&lt;/strong&gt; The relayed authentication enrolls the DC&apos;s machine account for a client certificate against the &lt;code&gt;Machine&lt;/code&gt; template (or any default-enabled template that allows enrollment) [@specterops-cert-preowned-pdf]. 4. &lt;strong&gt;Forge.&lt;/strong&gt; The attacker uses the certificate to perform PKINIT against the KDC, obtains a TGT for the DC&apos;s machine account, and uses the DC machine account&apos;s TGT to DCSync the domain&apos;s hashes -- including the krbtgt hash -- achieving full domain compromise. Domain Admin in under ten minutes [@specterops-cert-preowned-blog].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pause on what is and is not true here. SMB signing did not fail; SMB signing was not in the chain. EPA failed because it was deployed on IIS authentication endpoints generally but the &lt;code&gt;/certsrv/&lt;/code&gt; deployment lagged [@ms-kb5005413]. Credential Guard did not fail; Credential Guard protects the NT-hash, and the attacker never touched a hash. Restrict NTLM in audit mode worked exactly as labelled: it audited.&lt;/p&gt;
&lt;p&gt;The retrofits are not wrong. They patch the named primitives. The chain exploits the &lt;em&gt;existence&lt;/em&gt; of the fallback path, not a primitive. Every protective control is honest about what it does and silent about what it does not.&lt;/p&gt;

sequenceDiagram
    autonumber
    actor A as Attacker (no creds)
    participant DC as Domain Controller
    participant R as ntlmrelayx listener
    participant CA as AD CS /certsrv/
    participant KDC as KDC (PKINIT)
    A-&amp;gt;&amp;gt;DC: EfsRpcOpenFileRaw -- UNC to attacker share
    DC-&amp;gt;&amp;gt;R: NTLM AUTHENTICATE (SYSTEM (DC machine account))
    R-&amp;gt;&amp;gt;CA: Relay NTLM, enroll Machine cert as DC
    CA--&amp;gt;&amp;gt;R: Client certificate for DC
    R-&amp;gt;&amp;gt;KDC: PKINIT AS-REQ with DC cert
    KDC--&amp;gt;&amp;gt;A: TGT for DC, request service tickets at will
&lt;p&gt;This is the question that drives the rest of the article: &lt;em&gt;how did Windows arrive at a state where the most catastrophic modern Active Directory attack chain depends on a thirty-year-old fallback nobody wants?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;2. Origins: Why NTLM Existed at All&lt;/h2&gt;
&lt;p&gt;Rewind to 1987. IBM and Microsoft ship LAN Manager 1.0 for OS/2. PCs are still mostly file-and-print islands on Token Ring or 10BASE-2 coax; networking exists, but &quot;domain&quot; is a word for what a single server controls. LAN Manager needs an authentication scheme that can run on hardware with 640 KB of RAM, no DES export licence, and roughly zero institutional knowledge about cryptography. What it produces, the LM hash, is a near-perfect snapshot of every constraint and assumption of its moment [@wp-lan-manager].&lt;/p&gt;
&lt;p&gt;The construction is short enough to write out. Take the password. Uppercase it. Pad or truncate to exactly fourteen ASCII characters. Split into two seven-byte halves. Convert each half into a 56-bit DES key (the eighth bit of each byte is a parity bit). Use each key to DES-encrypt the eight-byte constant &lt;code&gt;KGS!@#$%&lt;/code&gt;. Concatenate the two eight-byte ciphertexts. That is the LM hash [@wp-lan-manager, @wp-nt-lan-manager].&lt;/p&gt;

The LAN Manager password hash from 1987. Constructed by uppercasing the password, truncating or padding to 14 characters, splitting into two 7-byte halves, and DES-encrypting the constant `KGS!@#$%` with each half as a key. The two halves are independent, the password is case-insensitive, and there is no salt. Every property of this construction enables an attack class that survives into NTLMv2 [@wp-lan-manager].
&lt;p&gt;The eight-byte constant &lt;code&gt;KGS!@#$%&lt;/code&gt; is what you get when somebody types &quot;KGS&quot; and then mashes shift-1, shift-2, shift-3, shift-4, shift-5 on a 1980s American IBM keyboard. The constant is in the protocol because the protocol predates the cryptographic-engineering norm that constants should look random. It would not survive a 2026 design review; in 1987 nobody asked.&lt;/p&gt;
&lt;p&gt;Every choice tells a story about 1987. Uppercase, because some clients normalised case anyway and the developers wanted authentication to &quot;just work&quot; across mixed locale settings. Fourteen characters, because that was the field width DOS dictated. Two halves, because a 56-bit DES key already maxed out the practical computation; nobody was going to chain two DES operations through a feedback function with that much per-keystroke latency. No salt, because the deployment model was one server, one user database, and identical-password collisions were a feature for the help desk, not a leak.&lt;/p&gt;
&lt;p&gt;The result is password-equivalent: anyone who possesses the LM hash &lt;em&gt;is&lt;/em&gt; the user, forever, regardless of how the wire protocol presents the credential.&lt;/p&gt;
&lt;p&gt;Six years later, July 27, 1993, Windows NT 3.1 ships. NTLM(v1) arrives with it [@wp-nt-lan-manager]. The NT-hash is what you would design if you started over with mid-1990s assumptions but were not yet willing to abandon DES at the response layer. It is simpler than the LM hash and stronger in exactly one place: &lt;code&gt;NT-hash = MD4(UTF-16LE(password))&lt;/code&gt; [@wp-nt-lan-manager]. No truncation. No case folding. Sixteen bytes of output. The hash is still password-equivalent; what changes is that the &lt;em&gt;input&lt;/em&gt; to the hash is now whatever Unicode string the user typed, in full.&lt;/p&gt;
&lt;p&gt;The wire protocol around the NT-hash is the famous three-message handshake. NEGOTIATE from the client. CHALLENGE from the server (an eight-byte random nonce). AUTHENTICATE from the client, carrying a DES-based response computed from the NT-hash and the server challenge. The whole exchange is self-contained: nothing in the three messages binds the authentication to a particular transport, a particular client, a particular server, or a particular service [@ms-nlmp]. That property -- the absence of &lt;em&gt;binding&lt;/em&gt; -- is the property NTLM relay will eat for the next twenty-five years.&lt;/p&gt;

`MD4(UTF-16LE(password))`. Sixteen bytes. The single long-term secret that every NTLM authentication ever performed for a given user derives from. Possession of the NT-hash is mathematically equivalent to possession of the password for every authentication purpose. NTLMv2 changes the response computation but not the hash [@wp-nt-lan-manager].

timeline
    title NTLM and Windows authentication, 1987-2027
    1987 : LAN Manager 1.0 ships : LM hash construction
    1993 : Windows NT 3.1 : NTLMv1 + NT-hash MD4(UTF-16LE(pwd))
    1998 : NT 4.0 SP4 : NTLMv2 with HMAC-MD5 and AV_PAIRS
    2000 : Windows 2000 : Kerberos is the default; NTLM demoted to fallback
    2008 : MS08-068 patches SMB self-relay (CVE-2008-4037)
    2015 : Windows 10 RTM ships Credential Guard
    2019 : CVE-2019-1040 Drop the MIC (Simakov/Zinar)
    2021 : PetitPotam (Gilles) + ESC8 (Schroeder/Christensen)
    2023 : Palko commits to removing NTLM (October 11)
    2024 : NTLM marked deprecated (June); NTLMv1 removed in 24H2/Server 2025
    2025 : KB 5064479 enhanced NTLM auditing
    2026 : Phase 1 (audit) + IAKerb/Local KDC pre-release (Phase 2)
    2027 : Phase 3 -- NTLM disabled by default (next major Windows release)
&lt;p&gt;The third revision arrives with NT 4.0 Service Pack 4, October 1998. NTLMv2 throws away DES at the response layer and replaces it with HMAC-MD5. It introduces a &lt;em&gt;client&lt;/em&gt; challenge (so the response is no longer purely a function of the server&apos;s choice). It introduces AV_PAIRS, a small TLV structure carrying the target name, a timestamp, and -- in much later retrofits -- the channel binding hash and message integrity field [@ms-nlmp, @wp-nt-lan-manager]. NTLMv2 defeats pre-computation attacks against the response. It does not change the long-term secret. The NT-hash is still the NT-hash; possession is still authority.An intermediate variant, NTLM2 Session Security, shipped in NT 4.0 SP4 alongside NTLMv2 and is the dead end most often confused for v2. It added an 8-byte client challenge to the NTLMv1 DES envelope without touching the long-term hash, hoping to defeat pre-computation while preserving wire compatibility. It survived only as a transitional &lt;code&gt;LMCompatibilityLevel&lt;/code&gt; setting; nothing in the modern attack catalogue treats NTLM2 SS as a distinct target [@ms-nlmp].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;LM hash (1987)&lt;/th&gt;
&lt;th&gt;NTLMv1 (1993)&lt;/th&gt;
&lt;th&gt;NTLMv2 (1998)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Hash function for the long-term secret&lt;/td&gt;
&lt;td&gt;DES of constant with password halves&lt;/td&gt;
&lt;td&gt;MD4(UTF-16LE(password))&lt;/td&gt;
&lt;td&gt;MD4(UTF-16LE(password))&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Case-sensitive&lt;/td&gt;
&lt;td&gt;No (uppercase only)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max input length&lt;/td&gt;
&lt;td&gt;14 characters (truncated)&lt;/td&gt;
&lt;td&gt;Unlimited Unicode&lt;/td&gt;
&lt;td&gt;Unlimited Unicode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Salted&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Per-exchange client challenge + timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response keyed MAC&lt;/td&gt;
&lt;td&gt;DES (3 keys, 56-bit each)&lt;/td&gt;
&lt;td&gt;DES (3 keys, 56-bit each)&lt;/td&gt;
&lt;td&gt;HMAC-MD5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binds to target server name&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;AV_PAIR &lt;code&gt;MsvAvTargetName&lt;/code&gt; (retrofit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binds to TLS endpoint&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;AV_PAIR &lt;code&gt;MsvAvChannelBindings&lt;/code&gt; (retrofit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Possession of hash = authority&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The two production response constructions on top of the same NT-hash. NTLMv1 chains three 56-bit DES operations across `K1 = NT-hash[0:7]`, `K2 = NT-hash[7:14]`, `K3 = NT-hash[14:16] || \x00\x00\x00\x00\x00`, encrypting the eight-byte server challenge under each. The third sub-key has only 16 bits of real entropy. NTLMv2 replaces all three DES operations with one HMAC-MD5 over `server_challenge || client_challenge || timestamp || av_pairs`, keyed by `NTOWFv2 = HMAC_MD5(NT-hash, UNICODE(Upper(user) || domain))` [@ms-nlmp, @wp-nt-lan-manager].
&lt;p&gt;Then comes Windows 2000, and Kerberos. Microsoft&apos;s plan was simple: in a domain, Kerberos handles everything; NTLM stays around as a compatibility blanket for the cases Kerberos cannot cover yet [@microsoft-ntlm-overview]. The trouble was that &quot;the cases Kerberos cannot cover yet&quot; turned out to be a permanent set, not a transitional one. Twenty-three years later, the same four cases would be the table-of-contents of Microsoft&apos;s NTLM-removal plan [@palko-2023-evolution]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No domain-controller line-of-sight.&lt;/strong&gt; A laptop on a hotel Wi-Fi authenticating to a corporate file share through a VPN tunnel terminator has no Kerberos KDC to talk to. NTLM does not need one.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local accounts.&lt;/strong&gt; A user signing into a workgroup machine or a domain-joined machine&apos;s local SAM has no domain at all; Kerberos has nothing to authenticate against.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No service principal name.&lt;/strong&gt; Kerberos requires a known SPN for the target service. Connect to a server by raw IP, by an alias DNS name not yet in the SPN database, or by a CNAME the operator forgot to register -- there is no SPN, so Kerberos cannot run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard-coded NTLM.&lt;/strong&gt; Application code that calls &lt;code&gt;AcquireCredentialsHandleW(..., &quot;Ntlm&quot;, ...)&lt;/code&gt; or RPC code that asks for &lt;code&gt;RPC_C_AUTHN_WINNT&lt;/code&gt; directly bypasses the negotiator and forces NTLM regardless of what is available.&lt;/li&gt;
&lt;/ol&gt;

The Simple and Protected GSS-API Negotiation Mechanism. When two parties want to authenticate but do not know which security mechanism they share, SPNEGO offers a list and picks the best one both support. On Windows the SSPI provider is called `Negotiate`, and it has historically chosen Kerberos when possible and NTLM otherwise [@microsoft-ntlm-overview]. The &quot;otherwise&quot; path is where every modern NTLM attack lives.
&lt;p&gt;Each fallback case is one shutter through which NTLM continues to leak into a Kerberos-by-default world. &lt;em&gt;The demotion was supposed to be terminal. Why did the four fallback cases turn out to cover most of the real-world authentication surface, and what does that look like on the wire?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;3. The Wire: Three Messages and One Hash&lt;/h2&gt;
&lt;p&gt;Most defenders have never read an NTLM authentication off the wire. The cryptography is short enough to fit on one screen, and the structural property that drives the next 28 years of attacks is visible inside those three messages. The point of this section is to make that property impossible to miss.&lt;/p&gt;
&lt;h3&gt;NEGOTIATE, CHALLENGE, AUTHENTICATE&lt;/h3&gt;
&lt;p&gt;The client opens with &lt;code&gt;NEGOTIATE&lt;/code&gt;, advertising its capability flags: which signing modes it supports, whether it is willing to do session security, whether it is asking for extended session keys, and so on. The server replies with &lt;code&gt;CHALLENGE&lt;/code&gt;. The body of &lt;code&gt;CHALLENGE&lt;/code&gt; contains a single 64-bit nonce (the server challenge) and a TLV blob called &lt;code&gt;TargetInfo&lt;/code&gt;: a list of attribute-value pairs the server wants to bind into the authentication [@ms-nlmp].&lt;/p&gt;
&lt;p&gt;The client computes its response and sends &lt;code&gt;AUTHENTICATE&lt;/code&gt;. That message contains the user name, the workstation name, the response itself, the AV_PAIRS the client wants to echo back, a Message Integrity Code field (HMAC-MD5 of the concatenation of all three NTLM messages), and -- in EPA-enforced deployments -- a hash of the TLS endpoint certificate placed in the &lt;code&gt;MsvAvChannelBindings&lt;/code&gt; AV_PAIR [@ms-nlmp, @ms-epa-wcf].&lt;/p&gt;

sequenceDiagram
    autonumber
    participant C as Client
    participant S as Server
    C-&amp;gt;&amp;gt;S: NEGOTIATE (capability flags)
    S-&amp;gt;&amp;gt;C: CHALLENGE (server nonce 8B, TargetInfo AV_PAIRS)
    Note over C: NTOWFv2 = HMAC_MD5(NT-hash, UNICODE(Upper(user) plus domain))
    Note over C: NTProofStr = HMAC_MD5(NTOWFv2, ServerChallenge plus temp) where temp = version plus Z(6) plus Time plus ClientChallenge plus Z(4) plus ServerName plus Z(4)
    C-&amp;gt;&amp;gt;S: AUTHENTICATE (user, NTProofStr, temp, MIC, CBT)
    Note over S: Server replays the same HMAC_MD5 with its copy of the NT-hash to verify
&lt;h3&gt;The NTLMv2 response, verbatim&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;[MS-NLMP]&lt;/code&gt; §3.3.2 gives the response algorithm in three lines of pseudocode [@ms-nlmp]:&lt;/p&gt;
&lt;p&gt;$$\text{NTOWFv2} = \text{HMAC-MD5}\big(\text{NT-hash},\ \text{UNICODE}(\text{Upper(user)} \mathbin{|} \text{domain})\big)$$&lt;/p&gt;
&lt;p&gt;$$\text{temp} = \text{Responserversion} \mathbin{|} \text{HiResponserversion} \mathbin{|} Z(6) \mathbin{|} \text{Time} \mathbin{|} \text{ClientChallenge} \mathbin{|} Z(4) \mathbin{|} \text{ServerName} \mathbin{|} Z(4)$$&lt;/p&gt;
&lt;p&gt;$$\text{NTProofStr} = \text{HMAC-MD5}\big(\text{NTOWFv2},\ \text{ServerChallenge} \mathbin{|} \text{temp}\big)$$&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;temp&lt;/code&gt; byte string carries two version bytes, six zero bytes, the 8-byte FILETIME, the 8-byte client challenge, four zero bytes, the AV_PAIR list the spec calls &lt;code&gt;ServerName&lt;/code&gt;, and a final four zero bytes. The client sends &lt;code&gt;NTProofStr || temp&lt;/code&gt; as the response. The server, which holds its own copy of &lt;code&gt;NT-hash&lt;/code&gt; for the user (cached or fetched from the domain controller), recomputes the same three lines and checks equality. That is the entire response protocol.&lt;/p&gt;
&lt;p&gt;Notice what &lt;code&gt;NTOWFv2&lt;/code&gt; is. It is a function of two inputs: the NT-hash, and a normalised user/domain string. Both inputs are static once the user logs in. &lt;em&gt;Knowing the NT-hash is sufficient to compute every NTLMv2 response forever, against every server, for every challenge, until the password changes&lt;/em&gt; [@wp-pass-the-hash].Why is HMAC-MD5 considered fine for the response side but considered weak for the &lt;em&gt;key&lt;/em&gt; side? The response side is being asked: given a known key, can a verifier check a freshly computed tag? HMAC-MD5 still answers that without a known break. The key side is being asked: given a stolen 16-byte value, how hard is it to mount a precomputation attack on candidate passwords? MD4 of UTF-16LE is so cheap on modern GPUs that an 8-character password is in the minutes-to-hours range. Hashcat lists NetNTLMv2 (mode 5600) as the practical attack format and benchmarks NTLM cracking accordingly.&lt;/p&gt;
&lt;h3&gt;AV_PAIRS, MIC, and channel binding -- retrofits all the way down&lt;/h3&gt;
&lt;p&gt;AV_PAIRS is a TLV structure. The server places target NetBIOS, target DNS, a timestamp, and various flags into the &lt;code&gt;TargetInfo&lt;/code&gt; of &lt;code&gt;CHALLENGE&lt;/code&gt;. The client echoes the structure into &lt;code&gt;AUTHENTICATE&lt;/code&gt; and adds two retrofit fields when both ends agree to use them [@ms-nlmp]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MsvAvFlags&lt;/code&gt;&lt;/strong&gt; is a bit field signalling that the client has computed a MIC and is therefore willing to bind all three NTLM messages together.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;MsvAvChannelBindings&lt;/code&gt;&lt;/strong&gt; holds a hash of the server&apos;s TLS endpoint certificate when the authentication is happening over an HTTPS-style transport that the client can see. This is the Extended Protection for Authentication (EPA) channel-binding-token mechanism [@ms-epa-wcf].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The MIC field itself is added to &lt;code&gt;AUTHENTICATE&lt;/code&gt;. It is &lt;code&gt;HMAC_MD5(ExportedSessionKey, NEGOTIATE || CHALLENGE || AUTHENTICATE)&lt;/code&gt;. &lt;code&gt;ExportedSessionKey&lt;/code&gt; coincides with &lt;code&gt;SessionBaseKey&lt;/code&gt; in the common case; when &lt;code&gt;NTLMSSP_NEGOTIATE_KEY_EXCH&lt;/code&gt; is set, the client generates a random session key, encrypts it under &lt;code&gt;KeyExchangeKey&lt;/code&gt;, and &lt;code&gt;ExportedSessionKey&lt;/code&gt; is the random key. The MIC always uses &lt;code&gt;ExportedSessionKey&lt;/code&gt;, and it is intended to make tampering with any of the three messages detectable [@ms-nlmp].&lt;/p&gt;

A length-prefixed TLV list carried inside the `TargetInfo` byte string of NTLM `CHALLENGE` and the AV-list byte string of `AUTHENTICATE`. AV_PAIRS hold the target server names, a timestamp, the `MsvAvFlags`, the `MsvAvChannelBindings` (EPA), and the optional `MsvAvTargetName` (SPN). NTLMv2 reserved AV_PAIRS in 1998 but most of the fields are 2009-2019-era retrofits onto the original wire format [@ms-nlmp].

A 16-byte HMAC-MD5, keyed by `ExportedSessionKey`, computed over the concatenation of the NTLM `NEGOTIATE`, `CHALLENGE`, and `AUTHENTICATE` messages and embedded in `AUTHENTICATE`. (`ExportedSessionKey` equals `SessionBaseKey` unless `NTLMSSP_NEGOTIATE_KEY_EXCH` is negotiated; the MIC always uses the exported key.) Introduced as a retrofit so that a man-in-the-middle relay could not silently strip the signing-required flags from the negotiate phase. Drop-the-MIC (CVE-2019-1040) demonstrated that the *presence* of the MIC was itself a negotiated property and could be stripped [@ms-nlmp, @nvd-cve-2019-1040].

A hash of the server&apos;s TLS endpoint certificate placed in `MsvAvChannelBindings` so the authentication is bound to the specific TLS channel the client believed it was talking over. When both ends enforce CBT, an attacker who terminates one TLS channel and opens a different TLS channel to the real server cannot reuse the captured NTLM response. Microsoft documents three enforcement modes: None, Partial, and Full [@ms-epa-wcf].
&lt;h3&gt;Run it&lt;/h3&gt;
&lt;p&gt;The whole thing fits in a few dozen lines of JavaScript. The point of the runnable demo is not to teach you to crack hashes; it is to make the password-equivalence claim land as code rather than as an assertion.&lt;/p&gt;
&lt;p&gt;{`
// Demonstrates the [MS-NLMP] NTLMv2 response algorithm.
//
// The point: NTProofStr is a deterministic function of the NT-hash plus
// values that travel in the clear or that the attacker controls. If you
// possess the NT-hash, you can compute NTProofStr for any (challenge,
// client_challenge, timestamp, av_pairs). That is the protocol-level
// proof of password-equivalence.
//
// In a real client, NT-hash = MD4(UTF-16LE(password)). MD4 is removed from
// most modern browser/Node crypto providers, so we use a precomputed
// NT-hash for password &quot;Summer2026!&quot; and focus on the structural property
// that matters: knowledge of those 16 bytes is sufficient forever.&lt;/p&gt;
&lt;p&gt;const crypto = require(&quot;crypto&quot;);&lt;/p&gt;
&lt;p&gt;// Precomputed NT-hash for password &quot;Summer2026!&quot; (16 bytes, hex):
//   reference value verified against impacket&apos;s NTOWFv1() helper offline.
const ntHash = Buffer.from(&quot;41aed72cec76816423703d8e545eea31&quot;, &quot;hex&quot;);&lt;/p&gt;
&lt;p&gt;const user = &quot;alice&quot;, domain = &quot;CONTOSO&quot;;&lt;/p&gt;
&lt;p&gt;// NTOWFv2 = HMAC-MD5(NT-hash, UNICODE(Upper(user) || domain))
const userDomain = Buffer.from((user.toUpperCase() + domain), &quot;utf16le&quot;);
const ntowfv2 = crypto.createHmac(&quot;md5&quot;, ntHash).update(userDomain).digest();&lt;/p&gt;
&lt;p&gt;// NTProofStr = HMAC-MD5(NTOWFv2, ServerChallenge || temp)
// where temp = ResponserVersion(0x01) || HiResponserVersion(0x01) || Z(6) ||
//              Time(8) || ClientChallenge(8) || Z(4) || ServerName || Z(4)
const serverChal = Buffer.from(&quot;0123456789abcdef&quot;, &quot;hex&quot;);
const clientChal = Buffer.from(&quot;fedcba9876543210&quot;, &quot;hex&quot;);
const ts = Buffer.alloc(8);                       // any 8-byte FILETIME
const serverName = Buffer.from(&quot;00000000&quot;, &quot;hex&quot;); // empty AV_PAIR list
const tempBuf = Buffer.concat([
  Buffer.from(&quot;0101000000000000&quot;, &quot;hex&quot;),           // version 1.1 || Z(6)
  ts, clientChal,
  Buffer.from(&quot;00000000&quot;, &quot;hex&quot;),                 // Z(4)
  serverName,
  Buffer.from(&quot;00000000&quot;, &quot;hex&quot;),                 // Z(4)
]);
const ntProofStr = crypto.createHmac(&quot;md5&quot;, ntowfv2)
  .update(Buffer.concat([serverChal, tempBuf])).digest();&lt;/p&gt;
&lt;p&gt;console.log(&quot;NT-hash    :&quot;, ntHash.toString(&quot;hex&quot;));
console.log(&quot;NTOWFv2    :&quot;, ntowfv2.toString(&quot;hex&quot;));
console.log(&quot;NTProofStr :&quot;, ntProofStr.toString(&quot;hex&quot;));
console.log(&quot;&quot;);
console.log(&quot;Now change serverChal/clientChal/ts and rerun: NTProofStr changes,&quot;);
console.log(&quot;but only the &lt;em&gt;first&lt;/em&gt; line of input (the NT-hash) is a secret. The&quot;);
console.log(&quot;rest travels in the clear inside the three NTLM messages. Possessing&quot;);
console.log(&quot;ntHash IS possessing the credential -- forever, on every server.&quot;);
`}&lt;/p&gt;
&lt;p&gt;The demo prints three lines, then a punchline. The lines are not impressive; the punchline is.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The NT-hash is not a credential; it &lt;em&gt;is&lt;/em&gt; the credential. Knowing the hash IS authentication. Every pass-the-hash tool ever written, from Paul Ashton&apos;s modified Samba in 1997 to the present, is a different packaging of the same realisation: an authentication that is a deterministic function of a static secret turns possession of that secret into permanent authority [@wp-pass-the-hash].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If possession of the hash is the protocol, the last 28 years of attacks are not surprises -- they are obvious next steps. What are those steps?&lt;/p&gt;
&lt;h2&gt;4. The Three-Decade Attack Cascade&lt;/h2&gt;
&lt;p&gt;Five generations of attacks. Each one is named, each one is dated, each one took Microsoft years to respond to, and each Microsoft response always closed the &lt;em&gt;primitive&lt;/em&gt; and left the &lt;em&gt;class&lt;/em&gt; alive. They are not five surprises; they are five logical consequences of the wire protocol you just read.&lt;/p&gt;
&lt;h3&gt;Generation 1 -- 1997: Pass-the-Hash (Paul Ashton)&lt;/h3&gt;
&lt;p&gt;The first published exploit of password-equivalence comes from Paul Ashton, posted to the Bugtraq mailing list in 1997. Ashton ships a patch against the Samba SMB client that takes a 16-byte NT-hash directly on the command line, &lt;em&gt;instead&lt;/em&gt; of asking for a cleartext password [@wp-pass-the-hash]. The patch is a one-paragraph change against an open-source codebase, and that fact -- the brevity of the change -- is the lesson.&lt;/p&gt;
&lt;p&gt;The NTLM response function has no input that depends on knowing the plaintext password. Replacing the plaintext-password input with a literal NT-hash input does not change the bytes that go on the wire. The server cannot tell the difference.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response, for more than a decade, is &lt;em&gt;do not lose your hashes&lt;/em&gt;. There is no protocol fix because there is no protocol bug to fix; the design is doing exactly what it was designed to do. The response is operational guidance: tier your admins, scrub LSASS, do not run privileged sessions on workstations.&lt;/p&gt;
&lt;h3&gt;Generation 2 -- 2001: NTLM Relay (Sir Dystic / SMBRelay)&lt;/h3&gt;
&lt;p&gt;If you do not have to &lt;em&gt;steal&lt;/em&gt; the hash to use the credential, you also do not have to &lt;em&gt;steal&lt;/em&gt; the live exchange. You can simply &lt;em&gt;relay&lt;/em&gt; it. On March 31, 2001, at the @lanta.con conference, Sir Dystic of the Cult of the Dead Cow (Josh Buchbinder) releases SMBRelay: a small program that accepts an SMB connection on port 139, opens a second SMB connection back to &lt;em&gt;another&lt;/em&gt; server, and shuttles the NEGOTIATE / CHALLENGE / AUTHENTICATE messages between the two sides [@cdc-smbrelay].&lt;/p&gt;
&lt;p&gt;The attack works because the three NTLM messages are not bound to a particular client, server, or service. Whoever sits between them can replay the credential against whatever destination the attacker chooses, as that user, for the duration of the exchange.The colourful provenance matters. The Cult of the Dead Cow released SMBRelay alongside Back Orifice 2000; &quot;Sir Dystic&quot; is the same Josh Buchbinder who later wrote the SMBProxy authentication-relay framework. The point is not the chrome -- it is that the relay class was disclosed publicly &lt;em&gt;at a conference&lt;/em&gt; in 2001, with working code on the cDc website, and Microsoft did not ship a fix for the trivial case (self-relay) until November 2008 [@cdc-smbrelay].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response is incomplete and slow. SMB signing exists from Windows 2000 onward, but it is off by default on member servers for more than a decade [@ms-smb-signing]. MS08-068, in November 2008, finally patches the &lt;em&gt;self-relay&lt;/em&gt; case (CVE-2008-4037): the SMB server now refuses to accept an authentication that the client itself just generated against the same server [@nvd-cve-2008-4037]. NVD notes that reliable sources report the original fix as insufficient for CVE-2000-0834 -- meaning the patch closed exactly the self-relay case and nothing else [@nvd-cve-2008-4037]. Seven years to fix the simplest variant; the &lt;em&gt;cross-server&lt;/em&gt; relay class is still wide open.&lt;/p&gt;
&lt;h3&gt;Generation 3 -- 2008-2014: Credential Theft as a Service&lt;/h3&gt;
&lt;p&gt;By 2008, the operational guidance &quot;do not lose your hashes&quot; stops being defensible. On February 29, 2008, Hernan Ochoa releases the Pass-the-Hash Toolkit v1.3, two native Windows binaries called &lt;code&gt;iam.exe&lt;/code&gt; and &lt;code&gt;whosthere.exe&lt;/code&gt; that read the NT-hash out of LSASS memory and inject it into a new logon session. PtH stops being a Linux-and-Samba trick and becomes a Windows-everywhere reality.&lt;/p&gt;
&lt;p&gt;Three years later, Benjamin Delpy publishes &lt;a href=&quot;https://paragmali.com/blog/windows-access-control-25-years-of-attacks/&quot; rel=&quot;noopener&quot;&gt;Mimikatz&lt;/a&gt;. The first version is closed-source, released in May 2011 [@wired-greenberg-mimikatz]. By April 6, 2014, the GitHub repository goes public with the version string &quot;mimikatz 2.0 alpha (x86) release &apos;Kiwi en C&apos; (Apr 6 2014 22:02:03)&quot; [@gh-mimikatz]. The repo description is a near-perfect summary of what LSASS is to an attacker: &quot;extract plaintexts passwords, hash, PIN code and kerberos tickets from memory. mimikatz can also perform pass-the-hash, pass-the-ticket or build Golden tickets&quot; [@gh-mimikatz]. LSASS becomes the universal credential oracle.Delpy did not intend Mimikatz to be a weapon. Wired&apos;s Andy Greenberg documents the trajectory in detail: Delpy &quot;released it publicly in May 2011, but as a closed source program.&quot; In mid-2011, Delpy learned for the first time that Mimikatz had been used in an intrusion of an unnamed foreign government network. That September, it appeared again in the landmark DigiNotar hack. An unidentified man was found at his laptop in his Moscow conference hotel room -- the stranger apologised and quickly left, claiming a wrong room. A second man in a dark suit later demanded a copy of Mimikatz on a USB drive. He went open-source partly fearing for his own safety after the hotel confrontations, and partly to make the security industry confront what lived in LSASS [@wired-greenberg-mimikatz].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response is structural and specific. Credential Guard ships in Windows 10 RTM (Enterprise and Education editions), July 29, 2015 [@ms-credential-guard]. It uses Virtualization-Based Security to isolate &lt;code&gt;lsaiso.exe&lt;/code&gt; in VTL1 within the same root partition; the kernel can no longer read NTLM hashes or Kerberos TGTs even at SYSTEM-level privilege. Protected Users and Restricted Admin in Server 2012 R2 / Windows 8.1 narrow the surface further. LSASS-as-PPL adds a process-protection layer between user-mode debuggers and the LSASS address space [@ms-credential-guard].&lt;/p&gt;
&lt;p&gt;Credential Guard works -- against the credential-&lt;em&gt;theft&lt;/em&gt; class. It does nothing against credential-&lt;em&gt;use&lt;/em&gt;. An attacker who never extracts a hash, because they never need to, sails right past it. Relay does not need the hash. Coercion does not need the hash. ESC8 does not need the hash. That is the next generation.&lt;/p&gt;
&lt;h3&gt;Generation 4 -- 2018-2021: Forced-Authentication Coercion&lt;/h3&gt;
&lt;p&gt;In 2018 at DerbyCon 8, Lee Christensen releases SpoolSample, known publicly as &quot;PrinterBug.&quot; The GitHub description is exact: &quot;PoC tool to coerce Windows hosts authenticate to other machines via the MS-RPRN RPC interface&quot; [@gh-spoolsample]. The trick is that the Print Spooler service runs as SYSTEM, accepts a remote RPC call (&lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt;) that takes a UNC path, and dutifully NTLM-authenticates back to whatever path the caller named -- on behalf of the machine account. Any Windows service running as SYSTEM that accepts a UNC path is a confused deputy that will authenticate on demand.&lt;/p&gt;

Microsoft&apos;s initial classification of SpoolSample was *authenticated-only / by design*: a caller needed valid domain credentials to reach the spooler endpoint, and authenticated callers triggering machine-account authentications was deemed within spec. The classification held through 2018, 2019, and most of 2020. PetitPotam broke it, because PetitPotam used MS-EFSRPC over LSARPC, which accepts *unauthenticated* binds on a domain controller&apos;s named-pipe interface. With the authentication requirement gone, &quot;by design&quot; stopped being a coherent defence. Microsoft started shipping fixes.
&lt;p&gt;Marina Simakov and Yaron Zinar of Preempt (now CrowdStrike) publish &quot;Drop the MIC&quot; on June 11, 2019. The vulnerability is CVE-2019-1040: a tampering bug where &quot;a man-in-the-middle attacker is able to successfully bypass the NTLM MIC (Message Integrity Check) protection&quot; [@crowdstrike-drop-the-mic, @nvd-cve-2019-1040]. The bypass works by stripping the &lt;code&gt;NTLMSSP_NEGOTIATE_SIGN&lt;/code&gt; and &lt;code&gt;NTLMSSP_NEGOTIATE_ALWAYS_SIGN&lt;/code&gt; flags from the initial &lt;code&gt;NEGOTIATE&lt;/code&gt;, removing the MIC field from &lt;code&gt;AUTHENTICATE&lt;/code&gt;, and removing the &lt;code&gt;Version&lt;/code&gt; field that drives MIC detection.&lt;/p&gt;
&lt;p&gt;Servers that should have required a MIC silently accept the modified message. The MIC -- the retrofit integrity layer that was supposed to make tampering detectable -- turns out to be itself untethered to the negotiation [@crowdstrike-drop-the-mic].&lt;/p&gt;
&lt;p&gt;Lionel Gilles (topotam77) publishes PetitPotam in July 2021, CVE-2021-36942. The GitHub repository description reads: &quot;PoC tool to coerce Windows hosts to authenticate to other machines via MS-EFSRPC EfsRpcOpenFileRaw or other functions&quot;. The decisive new property compared to SpoolSample is that PetitPotam needs &lt;em&gt;no credentials&lt;/em&gt; against a domain controller: LSARPC accepts unauthenticated binds, so the coercion can be triggered by an attacker who has merely joined the network.&lt;/p&gt;
&lt;p&gt;In 2022, Remi Gascou (p0dalirius) publishes Coercer, a Python script that consolidates the coercion class across MS-RPRN, MS-EFSR, MS-DFSNM, MS-FSRVP, and many more RPC interfaces. The README describes it succinctly: &quot;A python script to automatically coerce a Windows server to authenticate on an arbitrary machine through many methods&quot; [@gh-coercer].&lt;/p&gt;
&lt;h3&gt;Generation 5 -- 2021: ADCS Web-Enrollment Relay (ESC8)&lt;/h3&gt;
&lt;p&gt;On June 17, 2021, Will Schroeder and Lee Christensen of SpecterOps publish &quot;Certified Pre-Owned,&quot; a whitepaper and matching blog post that maps eight new attack classes against Active Directory Certificate Services [@specterops-cert-preowned-blog, @specterops-cert-preowned-pdf]. ESC1 through ESC7 are template and configuration weaknesses. ESC8 is the keystone of this article.&lt;/p&gt;
&lt;p&gt;ESC8 says: AD CS Web Enrollment endpoints (&lt;code&gt;/certsrv/&lt;/code&gt;) accept NTLM authentication. Coerce a server&apos;s machine account to authenticate to your relay listener; relay the authentication to &lt;code&gt;/certsrv/&lt;/code&gt;; enroll the relayed identity for a machine-template certificate; use that certificate to perform PKINIT against the KDC and request a TGT [@specterops-cert-preowned-blog]. The NTLM-vs-Kerberos boundary stops being a meaningful one. NTLM is the protocol on the front side of the attack; Kerberos is the trust token on the back side; the certificate is the conduit between them.&lt;/p&gt;
&lt;p&gt;The point of ESC8 is not just that it works. The point is that it works against a perfectly retrofitted environment. SMB signing did not enter the chain. LDAP signing did not enter the chain. EPA was supposed to enter the chain on the &lt;code&gt;/certsrv/&lt;/code&gt; side but was unevenly deployed. Credential Guard never had a hash to protect.&lt;/p&gt;

flowchart TD
    A[Gen 1 -- 1997 Pass-the-Hash&lt;br /&gt;Paul Ashton, modified Samba]
    A --&amp;gt; A1[Response: operational guidance&lt;br /&gt;Do not lose your hashes]
    A1 --&amp;gt; B[Gen 2 -- 2001 SMBRelay&lt;br /&gt;Sir Dystic, atlanta.con]
    B --&amp;gt; B1[Response: MS08-068 2008&lt;br /&gt;Patches self-relay only]
    B1 --&amp;gt; C[Gen 3 -- 2008-2014 LSASS extraction&lt;br /&gt;Ochoa PtH Toolkit, Delpy Mimikatz]
    C --&amp;gt; C1[Response: Credential Guard 2015&lt;br /&gt;Closes theft; not use]
    C1 --&amp;gt; D[Gen 4 -- 2018-2021 Coercion&lt;br /&gt;SpoolSample, Drop-the-MIC, PetitPotam, Coercer]
    D --&amp;gt; D1[Response: KB 5005413, EPA&lt;br /&gt;Closes primitive; not class]
    D1 --&amp;gt; E[Gen 5 -- 2021 ESC8&lt;br /&gt;Schroeder/Christensen Certified Pre-Owned]
    E --&amp;gt; E1[Response: remove NTLM]

sequenceDiagram
    autonumber
    actor A as Attacker
    participant V as &quot;Victim SYSTEM service (Spooler, EFSR, DFSNM)&quot;
    participant R as Attacker NTLM relay
    participant T as &quot;Target service (LDAP, SMB, certsrv)&quot;
    A-&amp;gt;&amp;gt;V: RPC call with UNC path \\attacker\share
    V-&amp;gt;&amp;gt;R: NTLM NEGOTIATE (as machine account)
    R-&amp;gt;&amp;gt;T: Open new authenticated session
    T-&amp;gt;&amp;gt;R: NTLM CHALLENGE
    R-&amp;gt;&amp;gt;V: Forward CHALLENGE
    V-&amp;gt;&amp;gt;R: NTLM AUTHENTICATE (signed by machine account)
    R-&amp;gt;&amp;gt;T: Forward AUTHENTICATE -- T treats attacker session as the victim
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Primitive&lt;/th&gt;
&lt;th&gt;Public date&lt;/th&gt;
&lt;th&gt;Microsoft response&lt;/th&gt;
&lt;th&gt;What survived&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1. Pass-the-Hash&lt;/td&gt;
&lt;td&gt;Use the hash directly&lt;/td&gt;
&lt;td&gt;1997, Paul Ashton, Bugtraq [@wp-pass-the-hash]&lt;/td&gt;
&lt;td&gt;Operational guidance&lt;/td&gt;
&lt;td&gt;Hash is still password-equivalent on the wire&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. NTLM relay (SMB)&lt;/td&gt;
&lt;td&gt;Forward live exchange&lt;/td&gt;
&lt;td&gt;March 31, 2001, Sir Dystic, @lanta.con [@cdc-smbrelay]&lt;/td&gt;
&lt;td&gt;MS08-068 (Nov 2008) -- self-relay only [@nvd-cve-2008-4037]&lt;/td&gt;
&lt;td&gt;Cross-server, cross-protocol relay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. LSASS extraction&lt;/td&gt;
&lt;td&gt;Steal hashes from memory&lt;/td&gt;
&lt;td&gt;Feb 2008 (Ochoa); May 2011 closed / Apr 2014 open (Delpy) [@gh-mimikatz, @wired-greenberg-mimikatz]&lt;/td&gt;
&lt;td&gt;Credential Guard (Jul 29, 2015) [@ms-credential-guard]&lt;/td&gt;
&lt;td&gt;Hash &lt;em&gt;use&lt;/em&gt; outside LSASS path; SYSTEM-level Mimikatz on the SAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Coercion&lt;/td&gt;
&lt;td&gt;Make SYSTEM authenticate on demand&lt;/td&gt;
&lt;td&gt;2018 SpoolSample [@gh-spoolsample]; 2019 Drop-the-MIC [@crowdstrike-drop-the-mic, @nvd-cve-2019-1040]; 2021 PetitPotam; 2022 Coercer [@gh-coercer]&lt;/td&gt;
&lt;td&gt;Per-interface patches; KB 5005413 EPA recipe [@ms-kb5005413]&lt;/td&gt;
&lt;td&gt;The pattern of &quot;SYSTEM holds an unanchored credential&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5. ESC8 ADCS Web Enrollment relay&lt;/td&gt;
&lt;td&gt;NTLM coerce -&amp;gt; /certsrv/ -&amp;gt; TGT via PKINIT&lt;/td&gt;
&lt;td&gt;June 17, 2021, Schroeder/Christensen, &quot;Certified Pre-Owned&quot; [@specterops-cert-preowned-blog, @specterops-cert-preowned-pdf]&lt;/td&gt;
&lt;td&gt;KB 5005413; AD CS hardening; eventually Phase 3 of NTLM removal&lt;/td&gt;
&lt;td&gt;Kerberos relay class on the other side (KrbRelay/KrbRelayUp) [@gh-krbrelayup]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

KrbRelayUp -- a universal no-fix local privilege escalation in windows domain environments where LDAP signing is not enforced (the default settings). -- Dec0ne, KrbRelayUp README [@gh-krbrelayup]
&lt;p&gt;The reader who started Section 4 believing &quot;if I patch each named NTLM attack, the protocol is safe&quot; finishes Section 4 believing something else. Every retrofit patches a &lt;em&gt;primitive&lt;/em&gt;; none addresses the &lt;em&gt;existence&lt;/em&gt; of the fallback path. The next attack is always one cross-protocol step away. The retrofit strategy is structurally incapable of closing the class.&lt;/p&gt;
&lt;p&gt;By the end of 2021, NTLM-the-protocol cannot be removed because four use cases require it, and NTLM-the-fallback cannot be kept because ESC8 turned it into a domain-takeover oracle. Something has to change. What?&lt;/p&gt;
&lt;h2&gt;5. The Retrofit Strategy and Its Funeral&lt;/h2&gt;
&lt;p&gt;Before naming the answer, name the strategy that failed. Microsoft&apos;s defensive cadence between 2001 and 2021 splits into three families, each effective against a named primitive, each defeated by an unanchored cousin of that primitive.&lt;/p&gt;
&lt;h3&gt;Family A -- Per-protocol message authentication&lt;/h3&gt;
&lt;p&gt;SMB signing. LDAP signing and sealing. The idea is to anchor the &lt;em&gt;content&lt;/em&gt; of each authenticated request inside a per-session signature derived from the authentication. SMB signing introduces an HMAC over every SMB message keyed by a per-session &lt;code&gt;SigningKey&lt;/code&gt;; LDAP signing and sealing do the equivalent for LDAP operations [@ms-smb-signing].&lt;/p&gt;
&lt;p&gt;Family A works when the &lt;em&gt;target&lt;/em&gt; protocol enforces it. SMB-to-SMB relay against an SMB server with required signing fails; LDAP-to-LDAP relay against an LDAP server with required signing fails. The strategy assumes the attacker stays in the same protocol family. Cross-protocol relay -- SMB authentication relayed to LDAP, or SMB authentication relayed to &lt;code&gt;/certsrv/&lt;/code&gt; -- defeats it. The MS-EFSR coercion can produce an authentication that originates &quot;as if from SMB&quot; and gets accepted by an unrelated HTTPS service that ignores the SMB signing flag entirely [@nvd-cve-2019-1040, @specterops-cert-preowned-blog].&lt;/p&gt;
&lt;h3&gt;Family B -- Per-channel binding tokens and the MIC&lt;/h3&gt;
&lt;p&gt;EPA (channel binding) and the NTLMv2 MIC are the response to cross-protocol relay. Both try to tie the authentication to &lt;em&gt;the specific channel&lt;/em&gt; the client believes it is using. EPA places a hash of the TLS endpoint certificate into the &lt;code&gt;MsvAvChannelBindings&lt;/code&gt; AV_PAIR; an HTTPS server with EPA required compares it to its own certificate&apos;s hash and rejects the authentication if they do not match [@ms-epa-wcf]. The MIC binds all three NTLM messages together so a relay cannot strip the signing-required flags from &lt;code&gt;NEGOTIATE&lt;/code&gt; after the client sets them [@ms-nlmp].&lt;/p&gt;
&lt;p&gt;Family B works when both ends agree to enforce. Drop-the-MIC (CVE-2019-1040) demonstrated that the &lt;em&gt;presence&lt;/em&gt; of the MIC was negotiated and could be stripped, so a server that supported MIC-less clients silently accepted MIC-less messages from a relay [@crowdstrike-drop-the-mic, @nvd-cve-2019-1040]. EPA suffers from the same enforcement-asymmetry: when an IIS endpoint runs with &lt;code&gt;policyEnforcement=&quot;None&quot;&lt;/code&gt; or &lt;code&gt;&quot;Partial&quot;&lt;/code&gt;, the binding is not checked. KB 5005413 published the explicit &lt;code&gt;&amp;lt;extendedProtectionPolicy policyEnforcement=&quot;Always&quot; /&amp;gt;&lt;/code&gt; recipe for &lt;code&gt;/certsrv/&lt;/code&gt; because field deployments had been running with weaker settings [@ms-kb5005413].&lt;/p&gt;
&lt;h3&gt;Family C -- Credential isolation&lt;/h3&gt;
&lt;p&gt;Credential Guard. LSASS-as-PPL. Protected Users. Restricted Admin. These attack the &lt;em&gt;theft&lt;/em&gt; surface. Credential Guard moves the NT-hash into &lt;code&gt;lsaiso.exe&lt;/code&gt; inside VTL1; the kernel can no longer read it. Microsoft now ships it enabled by default on domain-joined, non-DC systems running Windows 11 22H2 and Server 2025 on hardware that meets the requirements [@ms-credential-guard].&lt;/p&gt;
&lt;p&gt;Family C is honest about what it covers. It does nothing about coercion flows that never touch the NT-hash. PetitPotam and ESC8 do not need a hash; the relay session uses the live NTLM exchange and is never persisted. Credential Guard cannot help.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Family&lt;/th&gt;
&lt;th&gt;What it closes&lt;/th&gt;
&lt;th&gt;What it does not close&lt;/th&gt;
&lt;th&gt;Defeating attack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;A. Per-protocol message auth (SMB/LDAP signing)&lt;/td&gt;
&lt;td&gt;Same-protocol relay against the target&lt;/td&gt;
&lt;td&gt;Cross-protocol relay; targets that do not enforce&lt;/td&gt;
&lt;td&gt;LDAP relay from SMB coercion [@nvd-cve-2019-1040]; ESC8 relay to /certsrv/&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B. Channel binding (EPA) + MIC&lt;/td&gt;
&lt;td&gt;Same-channel relay through TLS termination&lt;/td&gt;
&lt;td&gt;MIC stripping in negotiation; EPA at None/Partial; non-TLS targets&lt;/td&gt;
&lt;td&gt;Drop-the-MIC [@nvd-cve-2019-1040]; under-enforced EPA [@ms-kb5005413]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C. Credential isolation (Credential Guard, LSASS-PPL)&lt;/td&gt;
&lt;td&gt;Hash theft from running LSASS&lt;/td&gt;
&lt;td&gt;Hash &lt;em&gt;use&lt;/em&gt; in live relay; SAM extraction from disk; coercion&lt;/td&gt;
&lt;td&gt;ESC8 + PetitPotam [@specterops-cert-preowned-blog]; SAM hive offline [@ms-credential-guard]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Every retrofit Microsoft has shipped against NTLM attacks one &lt;em&gt;primitive&lt;/em&gt; of NTLM. None address the &lt;em&gt;existence&lt;/em&gt; of NTLM as a fallback path. ESC8 was the funeral of the retrofit strategy because ESC8 turned a fully retrofitted environment into a domain takeover without defeating any retrofit.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &quot;Certified Pre-Owned&quot; did not break a Microsoft fix; it composed the existing infrastructure. The chain assumes SMB signing is on, EPA is on (somewhere), and Credential Guard is on. It still works, because none of those controls cover the path that goes Coercer -&amp;gt; NTLM relay -&amp;gt; AD CS Web Enrollment -&amp;gt; PKINIT. After 2021, the question stopped being &quot;what&apos;s the next retrofit?&quot; and became &quot;what does it take to remove the fallback?&quot; [@specterops-cert-preowned-blog, @ms-kb5005413].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To remove ESC8 without rebuilding AD CS, Microsoft has to remove NTLM. To remove NTLM, Microsoft has to remove the four reasons NTLM existed as a fallback in the first place. What does that look like in shippable form?&lt;/p&gt;
&lt;h2&gt;6. The Breakthrough: Closing the Fallback&lt;/h2&gt;
&lt;p&gt;October 11, 2023. Matthew Palko, Windows IT Pro Blog. &quot;The evolution of Windows authentication.&quot; For the first time in twenty-three years, Microsoft publicly commits to &lt;em&gt;removing&lt;/em&gt; NTLM, not restricting it, and names the three load-bearing features that make removal possible [@palko-2023-evolution].&lt;/p&gt;
&lt;p&gt;The plan starts where every honest plan starts -- by stating the problem in its own words. There are four fallback reasons NTLM persisted: no DC line-of-sight, no domain at all (local accounts), no SPN for the target, and hard-coded NTLM in application code [@palko-2023-evolution]. Each gets an engineered answer. The four-to-three correspondence (three protocols plus one refactor) is the new architecture.&lt;/p&gt;

Our end goal is eliminating the need to use NTLM at all to help improve the security bar of authentication for all Windows users. -- Matthew Palko, Microsoft Windows IT Pro Blog, October 11, 2023 [@palko-2023-evolution]
&lt;h3&gt;IAKerb -- closing &quot;no DC line-of-sight&quot;&lt;/h3&gt;
&lt;p&gt;IAKerb stands for &lt;em&gt;Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API&lt;/em&gt;. The IETF draft has a four-author list -- Benjamin Kaduk, Jim Schaad, Larry Zhu, and Jeffrey E. Altman -- and a quiet history [@draft-ietf-kitten-iakerb].&lt;/p&gt;
&lt;p&gt;The premise is simple. A client wants to authenticate to an application server with Kerberos but cannot reach a KDC -- maybe the client is behind a firewall, maybe the KDC is only reachable from the server&apos;s side of a VPN. IAKerb wraps the Kerberos &lt;code&gt;AS-REQ&lt;/code&gt; and &lt;code&gt;TGS-REQ&lt;/code&gt; messages inside GSS-API tokens and asks the application server to proxy them to a KDC that the server &lt;em&gt;can&lt;/em&gt; reach. The client never opens a direct TCP/UDP connection to a KDC; the application server acts as the carrier.&lt;/p&gt;

The honesty duty: IAKerb&apos;s IETF draft (`draft-ietf-kitten-iakerb`) was marked &quot;Dead WG Document&quot; on August 29, 2019, by Robbie Harwood [@draft-ietf-kitten-iakerb]. Harwood&apos;s note read, roughly, that IAKerb was historical at that point and the working group had no interest left. The last revision (`-03`) is from March 30, 2017, by Benjamin Kaduk. Microsoft is now reviving the protocol in 2023-2026 for Windows 11 and Windows Server 2025 -- without acknowledging the dead-WG status in its own blog posts. This is the gap between an IETF standards-track document and what a vendor ships; the article reports both [@draft-ietf-kitten-iakerb, @palko-2023-evolution].

Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API. A GSS-API-wrapped Kerberos exchange in which the client cannot reach a KDC directly and the application server proxies `AS-REQ` / `TGS-REQ` on the client&apos;s behalf. Defined by `draft-ietf-kitten-iakerb` (IETF kitten WG, currently a Dead WG Document). MIT Kerberos has shipped IAKerb since 1.9 (released February 2011); Apple ships `GSS_IAKERB_MECHANISM` since macOS 10.14. Microsoft is implementing IAKerb in Windows 11 / Server 2025 [@draft-ietf-kitten-iakerb, @palko-2023-evolution, @ms-cuomo-ad2025].
&lt;h3&gt;Local KDC -- closing &quot;no domain at all&quot;&lt;/h3&gt;
&lt;p&gt;Local accounts in the machine SAM have never had a KDC. Workgroup machines have no domain at all. Both cases force NTLM today. The fix is conceptually trivial: run a tiny Kerberos KDC against the local SAM, exposed only through IAKerb-wrapped exchanges so the wire protocol is the same as the trust-traversing case [@palko-2023-evolution, @ms-cuomo-ad2025].&lt;/p&gt;
&lt;p&gt;This is the late-adopter move that surprises Linux-side practitioners. MIT Kerberos has had IAKerb since 1.9 (released February 2011). Samba has been working on a &lt;code&gt;localkdc&lt;/code&gt; for years. At FOSDEM 2025 (February 2, 2025), Alexander Bokovoy and Andreas Schneider gave a talk explicitly framed as &quot;localkdc -- a general local authentication hub&quot; [@cryptomilk-localkdc]. Schneider&apos;s companion blog post the next week summarised the work: a parallel local-authentication hub for Linux that interoperates with the IAKerb wire format Windows is now adopting [@cryptomilk-localkdc].&lt;/p&gt;

A small Kerberos Key Distribution Center process that runs against a machine&apos;s local user database (the SAM on Windows; a file or sssd on Linux) and is exposed only through IAKerb. It lets local-account authentications use Kerberos under the same Negotiate / NEGOEX wire envelope used by domain authentications -- removing one of the four reasons NTLM persisted. Shipping in Windows 11 / Server 2025 [@palko-2023-evolution, @ms-cuomo-ad2025]; parallel Linux/Samba work coordinated under the FOSDEM 2025 `localkdc` umbrella [@cryptomilk-localkdc].
&lt;h3&gt;NEGOEX -- carrying IAKerb under the existing &lt;code&gt;Negotiate&lt;/code&gt; API&lt;/h3&gt;
&lt;p&gt;You do not want to teach every application a new SSPI provider. Existing code calls &lt;code&gt;AcquireCredentialsHandle(&quot;Negotiate&quot;, ...)&lt;/code&gt;; that should keep working, and IAKerb should be one of the mechanisms &lt;code&gt;Negotiate&lt;/code&gt; is willing to pick. The piece of plumbing that makes this possible is NEGOEX: SPNEGO Extended Negotiation [@ms-negoex, @draft-zhu-negoex].&lt;/p&gt;
&lt;p&gt;NEGOEX adds a pair of meta-data messages on top of the standard SPNEGO &lt;code&gt;NegTokenInit&lt;/code&gt; / &lt;code&gt;NegTokenResp&lt;/code&gt; exchange, so that mechanisms (like IAKerb) that need a richer negotiation can ride inside the &lt;code&gt;Negotiate&lt;/code&gt; envelope. The Microsoft Open Specification &lt;code&gt;[MS-NEGOEX]&lt;/code&gt; is currently at revision 4.0 (April 23, 2024), with the original revision dated July 9, 2020 [@ms-negoex]. The expired Microsoft IETF draft &lt;code&gt;draft-zhu-negoex&lt;/code&gt; from January 2011 is the historical anchor; four Microsoft authors -- Michiko Short, Larry Zhu, Kevin Damour, and Dave McPherson -- are listed verbatim in the draft metadata [@draft-zhu-negoex].&lt;/p&gt;
&lt;p&gt;A correction is owed here. Scope notes inherited from earlier in this project cited &quot;RFC 8143&quot; as the NEGOEX standard. RFC 8143 is actually titled &quot;Using Transport Layer Security (TLS) with Network News Transfer Protocol (NNTP)&quot; and updates RFC 4642; it has nothing to do with NEGOEX [@rfc-8143]. The correct primary references for NEGOEX are &lt;code&gt;[MS-NEGOEX]&lt;/code&gt; and &lt;code&gt;draft-zhu-negoex&lt;/code&gt;, both used consistently throughout this article [@ms-negoex, @draft-zhu-negoex].&lt;/p&gt;

The SPNEGO Extended Negotiation security mechanism. Adds a meta-data exchange inside the SPNEGO envelope so that richer mechanisms (like IAKerb) can be negotiated without changing the SSPI surface. Primary sources: Microsoft Open Specification `[MS-NEGOEX]` revision 4.0 (April 2024); expired IETF draft `draft-zhu-negoex` (January 2011). Despite a common scope-doc error, RFC 8143 is *not* NEGOEX; RFC 8143 is &quot;Using TLS with NNTP&quot; [@ms-negoex, @draft-zhu-negoex, @rfc-8143].
&lt;h3&gt;Negotiate-everywhere refactor -- closing &quot;hard-coded NTLM&quot;&lt;/h3&gt;
&lt;p&gt;The last fallback case is the most prosaic: application code that calls &lt;code&gt;AcquireCredentialsHandleW(..., &quot;Ntlm&quot;, ...)&lt;/code&gt; or RPC code that asks for &lt;code&gt;RPC_C_AUTHN_WINNT&lt;/code&gt;. Both bypass &lt;code&gt;Negotiate&lt;/code&gt; and force NTLM no matter what is on the wire. The fix is editorial -- audit Windows internals, replace each hard-coded &lt;code&gt;Ntlm&lt;/code&gt; call with &lt;code&gt;Negotiate&lt;/code&gt; -- and very large in surface area. Dan Cuomo&apos;s &quot;Active Directory improvements in Windows Server 2025&quot; post summarises the Windows Server Summit 2024 session in one sentence: &quot;we have created completely new Kerberos features to minimize use of NTLM in your environments. This session explains and demonstrates IAKerb, Local KDC, IP SPN, and the roadmap to the end of NTLM&quot; [@ms-cuomo-ad2025].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Fallback reason&lt;/th&gt;
&lt;th&gt;Closure mechanism&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;th&gt;Ship target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;No DC line-of-sight&lt;/td&gt;
&lt;td&gt;IAKerb (GSS-wrapped Kerberos through the app server)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;draft-ietf-kitten-iakerb&lt;/code&gt; (Dead WG, revived by Microsoft) [@draft-ietf-kitten-iakerb]&lt;/td&gt;
&lt;td&gt;Windows 11 / Server 2025 [@palko-2023-evolution, @ms-cuomo-ad2025]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No domain at all (local accounts)&lt;/td&gt;
&lt;td&gt;Local KDC over IAKerb&lt;/td&gt;
&lt;td&gt;Palko 2023; Samba &lt;code&gt;localkdc&lt;/code&gt; parallel [@palko-2023-evolution]&lt;/td&gt;
&lt;td&gt;Windows 11 / Server 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No SPN&lt;/td&gt;
&lt;td&gt;IP-SPN policy under Negotiate&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[MS-NEGOEX]&lt;/code&gt;; Cuomo 2024 session [@ms-negoex, @ms-cuomo-ad2025]&lt;/td&gt;
&lt;td&gt;Windows Server 2025&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard-coded NTLM&lt;/td&gt;
&lt;td&gt;Audit + replace &lt;code&gt;AcquireCredentialsHandle(&quot;Ntlm&quot;)&lt;/code&gt; with &lt;code&gt;Negotiate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Palko 2023 [@palko-2023-evolution]&lt;/td&gt;
&lt;td&gt;Editorial, ongoing through Phase 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

flowchart LR
    R1[No DC line-of-sight] --&amp;gt; M1[IAKerb&lt;br /&gt;draft-ietf-kitten-iakerb]
    R2[No domain at all&lt;br /&gt;local accounts] --&amp;gt; M2[Local KDC&lt;br /&gt;over IAKerb]
    R3[No SPN for target] --&amp;gt; M3[IP-SPN policy&lt;br /&gt;under Negotiate]
    R4[Hard-coded NTLM&lt;br /&gt;in app code] --&amp;gt; M4[Negotiate-everywhere&lt;br /&gt;refactor]
    M1 --&amp;gt; N[NEGOEX&lt;br /&gt;SPNEGO extension]
    M2 --&amp;gt; N
    M3 --&amp;gt; N
    N --&amp;gt; P[Negotiate SSPI&lt;br /&gt;same call sites]

sequenceDiagram
    autonumber
    participant C as Client (no KDC reach)
    participant S as Application server (KDC reach)
    participant K as KDC
    C-&amp;gt;&amp;gt;S: SPNEGO NegTokenInit with NEGOEX MetaData, mechs=[Kerberos, IAKerb]
    S--&amp;gt;&amp;gt;C: NegTokenResp, server picks IAKerb
    C-&amp;gt;&amp;gt;S: IAKerb token wrapping AS-REQ
    S-&amp;gt;&amp;gt;K: AS-REQ
    K--&amp;gt;&amp;gt;S: AS-REP
    S--&amp;gt;&amp;gt;C: IAKerb token wrapping AS-REP -&amp;gt; client now has TGT
    C-&amp;gt;&amp;gt;S: IAKerb token wrapping TGS-REQ for service ticket
    S-&amp;gt;&amp;gt;K: TGS-REQ
    K--&amp;gt;&amp;gt;S: TGS-REP (service ticket)
    S--&amp;gt;&amp;gt;C: IAKerb token wrapping TGS-REP
    Note over C,S: From now on, ordinary AP-REQ / AP-REP over Kerberos -- no NTLM needed
&lt;p&gt;What does this mean for Linux and macOS clients in a Windows domain? IAKerb is a GSS-API mechanism, and MIT&apos;s &lt;code&gt;krb5&lt;/code&gt; library shipped IAKerb in 1.9 (released February 2011) -- well before Microsoft. Apple&apos;s Heimdal-derived GSS framework has shipped &lt;code&gt;GSS_IAKERB_MECHANISM&lt;/code&gt; since macOS 10.14 (Mojave, 2018). The cross-platform interoperability story is therefore &lt;em&gt;better&lt;/em&gt; in 2026 than it has been in years: a Linux client using MIT 1.9+ or an Apple client using macOS 10.14+ can already speak IAKerb to a Windows Server 2025 Local KDC. The parallel Samba &lt;code&gt;localkdc&lt;/code&gt; effort closes the symmetric case: a Linux machine acting as the IAKerb server [@cryptomilk-localkdc].&lt;/p&gt;
&lt;p&gt;The reader who started Section 6 believing &quot;NTLM is too entrenched to remove&quot; finishes Section 6 believing something else. The entrenchment is &lt;em&gt;exactly four&lt;/em&gt; named cases, and &lt;em&gt;each one&lt;/em&gt; has been given an engineered answer. Removal is now a sequencing problem, not an architecture problem.&lt;/p&gt;
&lt;p&gt;The engineering existed by October 2023. The shipping commitment came in January 2026. What is Microsoft actually shipping, and on what schedule?&lt;/p&gt;
&lt;h2&gt;7. The Three-Phase Roadmap&lt;/h2&gt;
&lt;p&gt;January 29, 2026. The Windows IT Pro Blog publishes &quot;Advancing Windows security: Disabling NTLM by default&quot; under the byline &lt;code&gt;mariam_gewida&lt;/code&gt; [@gewida-2026-disabling]. The post documents Microsoft&apos;s published roadmap and opens with a caveat that the rest of this article works hard not to forget.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &quot;Disabling NTLM by default does not mean completely removing NTLM from Windows yet... during phase 3, NTLM will remain present in the OS and can be explicitly re-enabled via policy if you still need it.&quot; -- mariam_gewida, &quot;Advancing Windows security: Disabling NTLM by default,&quot; Microsoft Windows IT Pro Blog, January 29, 2026 [@gewida-2026-disabling]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The plan has three phases. They are sequenced; each phase produces the inputs the next phase needs.&lt;/p&gt;
&lt;h3&gt;Phase 1 (now) -- Audit&lt;/h3&gt;
&lt;p&gt;Phase 1 is auditing. The deliverable is enhanced NTLM logging in Windows 11 24H2 and Windows Server 2025, documented in KB 5064479 (published July 11, 2025) [@ms-kb5064479]. The new logging surface is &lt;code&gt;Applications and Services Logs &amp;gt; Microsoft &amp;gt; Windows &amp;gt; NTLM &amp;gt; Operational&lt;/code&gt;, gated by two GPOs called &quot;NTLM Enhanced Logging&quot; and &quot;Log Enhanced Domain-wide NTLM Logs.&quot; For each NTLM authentication, the event tells the administrator three things: &lt;em&gt;who&lt;/em&gt; called (the process), &lt;em&gt;why&lt;/em&gt; (the negotiated SSPI provider chose NTLM), and &lt;em&gt;where&lt;/em&gt; (the target service). The KB also names per-event warning classes for NTLMv1, MIC-less, and EPA-not-supported authentications [@ms-kb5064479].&lt;/p&gt;
&lt;p&gt;Phase 1 also closes the oldest residual: NTLMv1. Microsoft&apos;s deprecation page added an NTLM entry in June 2024 with verbatim language: &quot;All versions of NTLM, including LANMAN, NTLMv1, and NTLMv2, are no longer under active feature development and are deprecated. Use of NTLM will continue to work in the next release of Windows Server and the next annual release of Windows. Calls to NTLM should be replaced by calls to Negotiate&quot; [@ms-deprecated-features].&lt;/p&gt;
&lt;p&gt;The same row adds: &quot;NTLMv1 is removed starting in Windows 11, version 24H2 and Windows Server 2025&quot; -- the November 2024 update note [@ms-deprecated-features]. The KB 4090105 pre-24H2 NTLMv1 auditing surface (Event ID 4624 with &lt;code&gt;Package Name (NTLM only): NTLM V1&lt;/code&gt;) remains valid for legacy environments [@ms-ntlmv1-dc-audit].&lt;/p&gt;
&lt;h3&gt;Phase 2 (H2 2026) -- IAKerb + Local KDC + Negotiate-first refactor in pre-release&lt;/h3&gt;
&lt;p&gt;Phase 2 puts the engineered closures from Section 6 into pre-release. IAKerb and Local KDC ship for Windows Insiders and Server preview channels. The Negotiate-first refactor lands -- Microsoft&apos;s own subsystems audit their &lt;code&gt;AcquireCredentialsHandleW(&quot;Ntlm&quot;, ...)&lt;/code&gt; and &lt;code&gt;RPC_C_AUTHN_WINNT&lt;/code&gt; call sites and replace them with &lt;code&gt;Negotiate&lt;/code&gt; calls. Per-machine policy controls for NTLM scope make finer-grained restriction possible. IP-SPN policy lands so the &quot;no SPN&quot; case can be closed without naming every server by FQDN [@gewida-2026-disabling, @ms-cuomo-ad2025].&lt;/p&gt;
&lt;p&gt;The Microsoft outreach mechanism for Phase 2 is the &lt;code&gt;ntlm@microsoft.com&lt;/code&gt; mailbox; the January 2026 post names it explicitly as the channel for surfacing cross-forest, federated, and ISV-edge cases that need engineering help before Phase 3 [@gewida-2026-disabling].&lt;/p&gt;
&lt;h3&gt;Phase 3 (next major Windows / Windows Server release) -- Disabled by default&lt;/h3&gt;
&lt;p&gt;Phase 3 is the default-off flip. Network NTLM authentication is disabled by default in the next major Windows and Windows Server release. The disablement is a configuration, not a binary removal: NTLM remains in the OS, callable through &lt;code&gt;Negotiate&lt;/code&gt; only when a policy explicitly re-enables it for a named scope [@gewida-2026-disabling]. The Hacker News&apos; summary of the roadmap published February 2026 documents the same three-phase structure for industry-press consumption [@thn-2026-ntlm-phaseout].&lt;/p&gt;

flowchart LR
    P1[Phase 1 -- NOW&lt;br /&gt;KB 5064479 enhanced auditing&lt;br /&gt;NTLMv1 removed in 24H2 / WS2025] --&amp;gt; P2
    P2[Phase 2 -- H2 2026&lt;br /&gt;IAKerb + Local KDC pre-release&lt;br /&gt;Negotiate-first refactor&lt;br /&gt;Per-machine NTLM scope policy] --&amp;gt; P3
    P3[Phase 3 -- next major Windows&lt;br /&gt;Network NTLM disabled by default&lt;br /&gt;Re-enablement requires explicit policy]
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Deliverable&lt;/th&gt;
&lt;th&gt;Date / target&lt;/th&gt;
&lt;th&gt;Prerequisite&lt;/th&gt;
&lt;th&gt;Primary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Phase 1&lt;/td&gt;
&lt;td&gt;Enhanced NTLM auditing&lt;/td&gt;
&lt;td&gt;KB 5064479, July 11, 2025&lt;/td&gt;
&lt;td&gt;Windows 11 24H2 / Server 2025&lt;/td&gt;
&lt;td&gt;[@ms-kb5064479]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 1&lt;/td&gt;
&lt;td&gt;NTLMv1 removal&lt;/td&gt;
&lt;td&gt;Windows 11 24H2 / Server 2025, November 2024&lt;/td&gt;
&lt;td&gt;NTLM family deprecation (June 2024)&lt;/td&gt;
&lt;td&gt;[@ms-deprecated-features]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2&lt;/td&gt;
&lt;td&gt;IAKerb + Local KDC pre-release&lt;/td&gt;
&lt;td&gt;H2 2026, Windows Insider channel&lt;/td&gt;
&lt;td&gt;Phase 1 audit data identifies callers&lt;/td&gt;
&lt;td&gt;[@gewida-2026-disabling, @ms-cuomo-ad2025]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2&lt;/td&gt;
&lt;td&gt;Negotiate-first refactor of Windows subsystems&lt;/td&gt;
&lt;td&gt;H2 2026&lt;/td&gt;
&lt;td&gt;Phase 1 audit data&lt;/td&gt;
&lt;td&gt;[@palko-2023-evolution, @gewida-2026-disabling]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2&lt;/td&gt;
&lt;td&gt;IP-SPN policy for &quot;no SPN&quot; case&lt;/td&gt;
&lt;td&gt;Windows Server 2025 + flighting&lt;/td&gt;
&lt;td&gt;NEGOEX in Negotiate&lt;/td&gt;
&lt;td&gt;[@ms-cuomo-ad2025]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3&lt;/td&gt;
&lt;td&gt;Network NTLM disabled by default&lt;/td&gt;
&lt;td&gt;Next major Windows / Server release&lt;/td&gt;
&lt;td&gt;All Phase 2 features GA&lt;/td&gt;
&lt;td&gt;[@gewida-2026-disabling]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Phase 3 is the first default configuration in 30 years that does not include NTLM. It is &lt;em&gt;not&lt;/em&gt; the first configuration in 30 years without authentication-relay attacks. Why not?&lt;/p&gt;
&lt;h2&gt;8. What Disabling NTLM Cannot Buy You&lt;/h2&gt;
&lt;p&gt;A blunt section. Phase 3 is real progress. It is not the end of authentication attacks on Windows. Three structural ceilings survive the transition; the article will not pretend otherwise.&lt;/p&gt;
&lt;h3&gt;Disabled is not removed&lt;/h3&gt;
&lt;p&gt;Phase 3 still ships NTLM in the OS. The default is off; the policy lockout is exactly as strong as the domain&apos;s tier-0 administrative segregation, not stronger. An attacker who reaches a domain controller with Group Policy edit rights can flip the policy and re-enable NTLM for the scope they want. The wording in the January 2026 post is precise: &quot;during phase 3, NTLM will remain present in the OS and can be explicitly re-enabled via policy if you still need it&quot; [@gewida-2026-disabling].&lt;/p&gt;
&lt;p&gt;This is the design choice Microsoft has to make, because removing NTLM binaries entirely would brick every third-party application that hard-codes &lt;code&gt;Ntlm&lt;/code&gt; and every legacy device that has not been firmware-updated since 2018. &quot;Disabled by default with policy override&quot; is the only configuration that has any chance of getting deployed.&lt;/p&gt;
&lt;h3&gt;Kerberos has its own relay class&lt;/h3&gt;
&lt;p&gt;The relay &lt;em&gt;class&lt;/em&gt; does not depend on NTLM. KrbRelay, KrbRelayUp, RBCD abuse, unconstrained-delegation abuse, S4U2Self / S4U2Proxy chains -- the entire taxonomy survives the move to Kerberos with different named primitives. Dec0ne&apos;s KrbRelayUp README, quoted at the end of Section 4, calls the class a universal no-fix local privilege escalation; the rest of the README enumerates the LDAP-signing default and the RBCD primitive that drive the post-NTLM relay surface [@gh-krbrelayup].&lt;/p&gt;
&lt;p&gt;What changes is the protocol. What does not change is that an application server that receives an authenticated message without enforcing message integrity or channel binding can be coerced into accepting an attacker-relayed authentication. The named primitives change. The class survives.&lt;/p&gt;
&lt;h3&gt;Local SAM hashes remain password-equivalent&lt;/h3&gt;
&lt;p&gt;The Local KDC reads the SAM. An attacker with SYSTEM-level access to the same machine reads the SAM too. Once they have the hash in hand, they can either feed it to a Local KDC running on a machine they control, or they can attempt offline cracking. IAKerb does not change either of those facts; what it changes is whether the &lt;em&gt;wire&lt;/em&gt; exposes the password-equivalent secret. Defence in depth -- &lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;TPM&lt;/a&gt;-backed key wrapping, Credential Guard for VBS isolation of process credentials, &lt;a href=&quot;https://paragmali.com/blog/bitlocker-on-windows-architecture-attacks-and-the-limits-of-/&quot; rel=&quot;noopener&quot;&gt;BitLocker&lt;/a&gt; for the cold-boot scenario -- remains necessary [@ms-credential-guard].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Phase 3 is a transition between tradeoffs, not a transition out of them. The exit from NTLM-the-protocol is not the exit from the authentication-relay class, or from the chip-layer credential class. The arc closes one specific 30-year-old attack surface and opens different conversations about the next.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the structural classes survive, what practical problems remain that an administrator should worry about between today and Phase 3?&lt;/p&gt;
&lt;h2&gt;9. Open Problems and the 2026-2027 Edge&lt;/h2&gt;
&lt;p&gt;Five named problems sit between Phase 1 (now) and Phase 3 GA. Each one has a primary source and a &quot;best partial result&quot; available today.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ESC8 field deployment of EPA on &lt;code&gt;/certsrv/&lt;/code&gt; is uneven.&lt;/strong&gt; Microsoft published KB 5005413 on July 23, 2021 with the dispositive recipe: &lt;code&gt;&amp;lt;extendedProtectionPolicy policyEnforcement=&quot;Always&quot; /&amp;gt;&lt;/code&gt; on every &lt;code&gt;/certsrv/&lt;/code&gt; virtual directory, plus disabling plain HTTP. Server 2025 hardening pushes EPA to required-by-default in many AD CS templates. Many environments are not on Server 2025 yet, and CISA&apos;s Known Exploited Vulnerabilities catalog still lists CVE-2021-36942 as actively exploited. CVE-2022-26925 (&quot;Windows LSA Spoofing Vulnerability&quot;) is the LSARPC NTLM-relay variant that emerged after the initial PetitPotam patches; it is on the same KEV list [@ms-kb5005413].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Third-party and legacy-app hard-coded NTLM.&lt;/strong&gt; Microsoft&apos;s Negotiate-everywhere refactor covers Microsoft&apos;s own code. Independent software vendors must do the same audit for theirs. Phase 1&apos;s enhanced auditing surface (KB 5064479) is the practical instrument for identifying the callers: every NTLM authentication carries the calling process name and a reason code [@ms-kb5064479]. The post-Phase-3 default-off configuration will surface these as outages on any environment that has not run the audit first.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-forest and federated IAKerb edges.&lt;/strong&gt; Single-forest IAKerb is well-defined. Multi-forest, federated, and partner-trust scenarios get implementation-defined quickly: NEGOEX has to carry IAKerb tokens through &lt;code&gt;Negotiate&lt;/code&gt; across trust boundaries where the proxying server may not be in the same forest as the KDC. Microsoft&apos;s &lt;code&gt;ntlm@microsoft.com&lt;/code&gt; outreach mailbox exists precisely to surface these edge cases before Phase 3 [@draft-ietf-kitten-iakerb, @gewida-2026-disabling].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Linux and macOS parallel.&lt;/strong&gt; MIT Kerberos has had IAKerb since 1.9 (released February 2011). Apple ships &lt;code&gt;GSS_IAKERB_MECHANISM&lt;/code&gt; since macOS 10.14. The Samba and &lt;code&gt;localkdc&lt;/code&gt; effort from Bokovoy and Schneider (FOSDEM 2025) is the parallel open-source path: a Linux machine that can act as the IAKerb application server for a Windows client, or vice versa, under the same &lt;code&gt;Negotiate&lt;/code&gt; envelope [@cryptomilk-localkdc]. The interoperability story should be &lt;em&gt;better&lt;/em&gt; in 2026-2027 than it has been in twenty years.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Policy pressure.&lt;/strong&gt; EU NIS2 mandates cybersecurity risk-management measures for entities in critical sectors; the Cyber Resilience Act adds mandatory security requirements for products with digital elements. Both frameworks make legacy authentication a documented compliance concern. Deprecation of NTLM under Microsoft&apos;s own deprecation page (&lt;code&gt;ms-deprecated-features&lt;/code&gt;) gives a clean audit surface that did not exist before; an organisation can point to KB 5064479 audit data showing NTLM call sites with named callers and target services, and demonstrate progress on retirement [@ms-deprecated-features].The EU regulatory framing here is touched lightly because the primary texts (NIS2 Directive, Cyber Resilience Act) are extensive regulatory documents this article does not quote verbatim beyond the European Commission&apos;s official summaries. The relevant connection is operational: deprecation pages and audit logs give compliance teams an artifact for &quot;we are retiring this class of credential under a published deprecation,&quot; which is the kind of evidence regulators ask for.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All five problems converge to one question for the AD engineer reading this article: &lt;em&gt;what should I do this quarter?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;10. What an AD Engineer Should Do This Quarter&lt;/h2&gt;
&lt;p&gt;Six numbered actions, ordered by impact. No filler, no compliance boilerplate.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is the prerequisite. Without Who/Why/Where data, Phase 3 surfaces breakage as outage. Enable the &quot;NTLM Enhanced Logging&quot; and &quot;Log Enhanced Domain-wide NTLM Logs&quot; GPOs on every domain controller and member server you operate. Subscribe to the &lt;code&gt;Applications and Services Logs &amp;gt; Microsoft &amp;gt; Windows &amp;gt; NTLM &amp;gt; Operational&lt;/code&gt; channel. Identify every process that initiates NTLM, the reason &lt;code&gt;Negotiate&lt;/code&gt; declined Kerberos, and the target service. Triage by call volume and criticality [@ms-kb5064479].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Set &lt;code&gt;LDAPClientIntegrity = 2&lt;/code&gt; and &lt;code&gt;LdapEnforceChannelBinding = 2&lt;/code&gt; on every domain controller. This closes SMB-to-LDAP relay regardless of whether the originating authentication was NTLM or Kerberos. KrbRelayUp&apos;s existence makes this &lt;em&gt;more&lt;/em&gt; urgent post-NTLM, not less: the relay class on Kerberos uses the same un-anchored LDAP target [@gh-krbrelayup].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The KB 5005413 recipe is verbatim: add &lt;code&gt;&amp;lt;extendedProtectionPolicy policyEnforcement=&quot;Always&quot; /&amp;gt;&lt;/code&gt; to the authentication element of the IIS virtual directory and disable plain HTTP. &lt;code&gt;/certsrv/&lt;/code&gt; is the dispositive ESC8 target. Web Enrollment proxy endpoints (&lt;code&gt;/certenroll/&lt;/code&gt;, &lt;code&gt;/adpolicyprovider_cep_kerberos/&lt;/code&gt; and similar) are the second tier. Audit every IIS authentication endpoint in the estate and confirm &lt;code&gt;policyEnforcement=&quot;Always&quot;&lt;/code&gt; is the value, not &lt;code&gt;&quot;None&quot;&lt;/code&gt; or &lt;code&gt;&quot;Partial&quot;&lt;/code&gt; [@ms-kb5005413].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Print Spooler service is the single highest-impact MS-RPRN coercion surface. Disabling Spooler on every server that does not actually print closes the entire &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt; coercion class on those hosts. Microsoft&apos;s hardening guidance and the PrintNightmare disclosures (2021) made this an explicit recommendation [@gh-spoolsample].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Coercer&apos;s scan mode is the canonical defensive auditing tool: it inventories which RPC coercion methods a given server still answers. Run it against every server you operate, in scan mode. The output is a list of unauthenticated and authenticated coercion endpoints to either patch, disable, or compensate around. Treat unauthenticated endpoints (LSARPC, &lt;code&gt;\PIPE\lsarpc&lt;/code&gt;) as P0 [@gh-coercer].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Microsoft&apos;s preferred sequence: Windows Insider flighting -&amp;gt; pilot non-production NTLM-off configurations -&amp;gt; identify hard-coded &lt;code&gt;Ntlm&lt;/code&gt; SSPI calls in your in-house code -&amp;gt; stage Phase-3 rollout against your audit data. If you wait, the cut-over surfaces breakage as outage. If you audit, the cut-over is uneventful [@gewida-2026-disabling].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Phase 1 audit is the load-bearing piece. Action 1 produces the data that makes Actions 2-6 prioritise correctly. The following snippet sketches the audit-event query logic an administrator would express in PowerShell -- the JavaScript runs the same logic so you can think through edge cases interactively.&lt;/p&gt;
&lt;p&gt;{`
// Sketch of the triage logic an administrator would run against
// &quot;Applications and Services Logs &amp;gt; Microsoft &amp;gt; Windows &amp;gt; NTLM &amp;gt; Operational&quot;
// after enabling the KB 5064479 enhanced auditing GPOs. The point of running
// this in JavaScript is to make the rules explicit so you can think through
// edge cases without standing up a Windows event channel.&lt;/p&gt;
&lt;p&gt;const sampleEvents = [
  { process: &quot;C:\\app\\legacy.exe&quot;,      reason: &quot;NoSPN&quot;,          target: &quot;ldap/dc01.example.local&quot;, count: 142 },
  { process: &quot;C:\\Program Files\\Backup\\agent.exe&quot;, reason: &quot;ExplicitNtlm&quot;,   target: &quot;cifs/backup02.example.local&quot;, count: 9 },
  { process: &quot;C:\\Windows\\System32\\spoolsv.exe&quot;,   reason: &quot;NoDcReach&quot;,      target: &quot;cifs/attacker.example.local&quot;, count: 1 },
  { process: &quot;C:\\Windows\\System32\\lsass.exe&quot;,     reason: &quot;LocalAccount&quot;,   target: &quot;host\\WORKGROUP-PC01&quot;,   count: 38 },
  { process: &quot;C:\\Windows\\System32\\svchost.exe&quot;,   reason: &quot;NoSPN&quot;,          target: &quot;host/aliased.example.local&quot;, count: 7 },
];&lt;/p&gt;
&lt;p&gt;function triage(events) {
  const out = [];
  for (const e of events) {
    let severity = &quot;info&quot;;
    let actions = [];
    if (e.reason === &quot;ExplicitNtlm&quot;) {
      severity = &quot;high&quot;;
      actions.push(&quot;Fix caller: replace AcquireCredentialsHandle(&apos;Ntlm&apos;) with &apos;Negotiate&apos;&quot;);
    }
    if (e.reason === &quot;NoSPN&quot;) {
      severity = &quot;medium&quot;;
      actions.push(&quot;Register an SPN for the target or enable IP-SPN policy&quot;);
    }
    if (e.reason === &quot;LocalAccount&quot;) {
      severity = &quot;medium&quot;;
      actions.push(&quot;Plan Local KDC enrollment in Phase 2 pilot&quot;);
    }
    if (/spoolsv\.exe$/i.test(e.process) &amp;amp;&amp;amp; /attacker/i.test(e.target)) {
      severity = &quot;critical&quot;;
      actions.push(&quot;Suspicious: Spooler authenticating to non-domain UNC. Likely coercion attempt -- isolate, then disable Spooler on this host&quot;);
    }
    out.push({ process: e.process, severity, actions });
  }
  return out;
}&lt;/p&gt;
&lt;p&gt;for (const row of triage(sampleEvents)) {
  console.log(`[${row.severity.toUpperCase()}] ${row.process}`);
  for (const a of row.actions) console.log(&quot;    -&amp;gt; &quot; + a);
}
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; - &lt;strong&gt;&lt;code&gt;LMCompatibilityLevel = 5&lt;/code&gt; without audit.&lt;/strong&gt; Forcing NTLMv2-only on every DC is correct as an endpoint, but flipping it without first running KB 5064479 audit will outage legacy applications that still attempt NTLMv1 [@ms-kb5064479]. - &lt;strong&gt;&lt;code&gt;RestrictNTLM:Deny&lt;/code&gt; without exceptions.&lt;/strong&gt; The Restrict NTLM family of GPOs supports per-server exemptions. Going straight to &lt;code&gt;Deny&lt;/code&gt; without an exemption list is the classic outage path. - &lt;strong&gt;EPA on HTTPS-only while leaving plain HTTP enabled.&lt;/strong&gt; KB 5005413 explicitly requires &lt;em&gt;both&lt;/em&gt; &lt;code&gt;policyEnforcement=&quot;Always&quot;&lt;/code&gt; and disabling plain HTTP on &lt;code&gt;/certsrv/&lt;/code&gt;. Leaving HTTP up makes the EPA enforcement moot [@ms-kb5005413]. - &lt;strong&gt;Trusting Credential Guard against coercion.&lt;/strong&gt; Credential Guard protects against credential &lt;em&gt;theft&lt;/em&gt;. It does not protect against ESC8, PetitPotam, or any other relay-of-live-authentication chain [@ms-credential-guard].&lt;/p&gt;
&lt;/blockquote&gt;

On a non-production Windows 11 Insider machine, the per-machine NTLM scope policy lives under `HKLM\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0`. Microsoft&apos;s pre-release documentation will name the value used to gate the Phase 2 IAKerb / Local KDC behaviours; consult the Windows Insider release notes that ship with the Phase 2 flight rather than hard-coding a value here -- the keys are subject to change up to GA. Use the `ntlm@microsoft.com` outreach channel for any environment-specific question [@gewida-2026-disabling].
&lt;p&gt;This is the work. The Phase 3 deadline is the next major Windows release; the Phase 1 audit window is right now. If you wait, the cut-over surfaces breakage as outage. If you audit, the cut-over is uneventful.&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

No. NTLMv2 is the version Drop-the-MIC, PetitPotam, and ESC8 all attack [@nvd-cve-2019-1040, @specterops-cert-preowned-blog]. The HMAC-MD5 response is strong against the response side, but the password-equivalence of the NT-hash and the lack of binding to the underlying transport are the structural properties every modern attack exploits. NTLMv2 is the *least bad* NTLM, not a safe NTLM.

Phase 1 controls let you *audit*. Phase 2 features (IAKerb, Local KDC, IP-SPN, the Negotiate refactor) are what make disabling *survivable* for most organisations. If you go straight to `RestrictNTLM:Deny` without running the KB 5064479 audit first, you will outage legacy applications and possibly your help-desk laptops. The honest answer is: audit now, pilot Phase 2 in H2 2026, default-off at Phase 3 [@gewida-2026-disabling, @ms-kb5064479].

No. Credential Guard fixes credential *theft* from LSASS. It does nothing about credential *use* (relay), coercion (PetitPotam), or cross-protocol chains (ESC8). It is necessary -- ESC8 + Mimikatz is worse than ESC8 alone -- but it is not sufficient against the relay class [@ms-credential-guard].

No. KrbRelay and KrbRelayUp demonstrate the relay *class* survives on Kerberos. What changes is the named primitives, not the existence of relay. Defence is the same shape after Phase 3 as before: LDAP signing and channel binding everywhere, EPA enforced on every authentication endpoint, message integrity required at every level [@gh-krbrelayup].

Because the four fallback reasons (no DC, local accounts, no SPN, hard-coded NTLM) had no engineered answer until IAKerb, Local KDC, NEGOEX, and the Negotiate refactor existed in shippable form. The standards work, the IETF drafts (one of which was marked Dead WG Document in 2019 and is being revived), the MIT 1.9 parity, and the Apple precedent all had to exist before Microsoft had a credible removal path that did not break enterprise deployments [@palko-2023-evolution, @draft-ietf-kitten-iakerb].

Yes. MIT Kerberos has had IAKerb since 1.9 (released February 2011). Apple ships `GSS_IAKERB_MECHANISM` since macOS 10.14 (Mojave, 2018). The Samba `localkdc` effort from Bokovoy and Schneider (FOSDEM 2025) is the parallel open-source path for a Linux local KDC. Heterogeneous Windows-domain estates with Linux file servers and macOS clients are positioned to interoperate with Phase 3 *better* than they did with NTLMv2 [@cryptomilk-localkdc].
&lt;p&gt;NTLM was the answer to a 1987 problem and a 1993 problem. It survived because removing it required engineering four orthogonal capabilities that did not exist. They exist now. The next major Windows release ships without it on by default. The attacks that follow it -- KrbRelayUp, RBCD chains, S4U2Self abuse, certificate-template misconfiguration -- target a different protocol with a different vocabulary. The relay &lt;em&gt;class&lt;/em&gt; persists. The protocol it targets is no longer NTLM.&lt;/p&gt;
&lt;p&gt;If you read this article as part of a sequence, the prior pieces cover the &lt;a href=&quot;https://paragmali.com/blog/windows-access-control-25-years-of-attacks/&quot; rel=&quot;noopener&quot;&gt;access-control model&lt;/a&gt; (&lt;code&gt;SeAccessCheck&lt;/code&gt; and its inputs), the chip-layer credential story (TPM, &lt;a href=&quot;https://paragmali.com/blog/pluton-a-tpm-on-silicon-microsoft-can-patch/&quot; rel=&quot;noopener&quot;&gt;Pluton&lt;/a&gt;, Credential Guard, BitLocker), and the &lt;a href=&quot;https://paragmali.com/blog/windows-app-identity-33-year-reinvention/&quot; rel=&quot;noopener&quot;&gt;application-identity layer&lt;/a&gt; (Authenticode, signed binaries, AppLocker, smart application control). NTLM removal is one strand of the broader move from &quot;trust the perimeter&quot; to &quot;tie every credential to a token, a chip, or a Kerberos ticket whose lifetime you can name.&quot; Each strand by itself is incomplete; together they are how the next decade of Windows authentication looks.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;ntlmless-the-death-of-ntlm-in-windows&quot; keyTerms={[
  { term: &quot;LM hash&quot;, definition: &quot;1987 LAN Manager hash. Uppercase the password, pad/truncate to 14 characters, split into two 7-byte halves, DES-encrypt KGS!@#$% with each half. Password-equivalent, case-insensitive, no salt.&quot; },
  { term: &quot;NT-hash&quot;, definition: &quot;MD4(UTF-16LE(password)). Sixteen bytes. The long-term secret every NTLM response derives from. Possession equals authority.&quot; },
  { term: &quot;NTLMv2&quot;, definition: &quot;HMAC-MD5 response over server_challenge || client_challenge || timestamp || av_pairs, keyed by NTOWFv2 = HMAC_MD5(NT-hash, UNICODE(Upper(user)||domain)). Ships in NT 4.0 SP4, October 1998.&quot; },
  { term: &quot;SPNEGO / Negotiate&quot;, definition: &quot;The GSS-API negotiation mechanism Windows uses to pick between Kerberos and NTLM. The Windows SSPI provider is called Negotiate.&quot; },
  { term: &quot;MIC&quot;, definition: &quot;Message Integrity Code -- HMAC-MD5 keyed by ExportedSessionKey over the concatenation of all three NTLM messages. Defeated by Drop-the-MIC (CVE-2019-1040).&quot; },
  { term: &quot;EPA / CBT&quot;, definition: &quot;Extended Protection for Authentication / Channel Binding Token. A hash of the TLS endpoint certificate placed in the MsvAvChannelBindings AV_PAIR.&quot; },
  { term: &quot;Pass-the-Hash&quot;, definition: &quot;Using a stolen NT-hash directly as the credential, without ever knowing the cleartext password. First published by Paul Ashton in 1997.&quot; },
  { term: &quot;NTLM relay&quot;, definition: &quot;Forwarding a live NTLM exchange between a victim client and a third-party target. First public PoC: Sir Dystic&apos;s SMBRelay (March 31, 2001).&quot; },
  { term: &quot;Coercion&quot;, definition: &quot;Causing a Windows service running as SYSTEM to NTLM-authenticate to an attacker-controlled destination via an RPC method that takes a UNC path. SpoolSample (2018), PetitPotam (2021), Coercer (2022).&quot; },
  { term: &quot;ESC8&quot;, definition: &quot;Coerced NTLM relayed to AD CS Web Enrollment (/certsrv/), yielding a certificate that yields a TGT via PKINIT. Schroeder + Christensen, Certified Pre-Owned, June 17, 2021.&quot; },
  { term: &quot;IAKerb&quot;, definition: &quot;Initial and Pass Through Authentication Using Kerberos V5 and the GSS-API. Lets a client with no KDC reach proxy AS-REQ / TGS-REQ through an application server.&quot; },
  { term: &quot;Local KDC&quot;, definition: &quot;A small Kerberos KDC against the local SAM, exposed via IAKerb. Shipping in Windows 11 / Server 2025.&quot; },
  { term: &quot;NEGOEX&quot;, definition: &quot;SPNEGO Extended Negotiation. Adds a meta-data exchange inside the SPNEGO envelope so IAKerb can be negotiated under Negotiate. NOT RFC 8143 (which is NNTP+TLS); the correct primaries are [MS-NEGOEX] and draft-zhu-negoex.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>ntlm</category><category>kerberos</category><category>active-directory</category><category>pass-the-hash</category><category>ntlm-relay</category><category>petitpotam</category><category>esc8</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>