<?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: credential-theft</title><description>Posts tagged credential-theft.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:15 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/credential-theft/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>Mimikatz and the Credential-Theft Decade: The Windows Security Wars Part 3 (2009-2014)</title><link>https://paragmali.com/blog/mimikatz-and-the-credential-theft-decade-the-windows-securit/</link><guid isPermaLink="true">https://paragmali.com/blog/mimikatz-and-the-credential-theft-decade-the-windows-securit/</guid><description>Microsoft killed the rootkit class with AppLocker, Secure Boot, ELAM, and AppContainer. Then a side project in C named Mimikatz proved the wrong layer had been hardened.</description><pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate><content:encoded>
**2009-2014 was Windows security&apos;s parallel-revolution decade.** Microsoft shipped AppLocker, Secure Boot, ELAM, AppContainer, and in-box Defender [@ms-applocker; @ms-secure-boot; @ms-elam], retiring the rootkit class and the unsigned-bootloader class. In the same window, Stuxnet burned four Windows zero-days [@symantec-stuxnet-dossier-v14] against Iranian centrifuges and Benjamin Delpy released Mimikatz, which extracted every cached credential from LSASS in one command [@mimikatz-github; @greenberg-mimikatz-wired]. The defensive playbook closed per-binary attack surface while attackers pivoted up the trust stack to the credential layer that hardened binaries still had to trust. By November 11, 2014, Microsoft had acknowledged in product (Restricted Admin RDP, LSA Protected Process, KB2871997&apos;s WDigest opt-out) [@kb2871997; @ms-lsa-protection] and in print (the Mitigating Pass-the-Hash whitepaper v1 December 2012 and v2 July 2014) [@ms-pth-v1-landing; @ms-pth-v2] that the in-VTL0 LSASS model was structurally indefensible against an admin-privileged attacker on the same host. The architectural answer -- Virtualisation-Based Security and Credential Guard in Windows 10 1507 [@ms-credential-guard] -- ships eight months outside the window and opens Part 4.
&lt;h2&gt;1. Two Continents, Eleven Months Apart&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites.&lt;/strong&gt; This article assumes the reader has the pre-2009 Windows-security context covered by &lt;a href=&quot;https://paragmali.com/blog/two-months-without-code-the-windows-security-wars-part-1-199/&quot; rel=&quot;noopener&quot;&gt;Part 1&lt;/a&gt; and &lt;a href=&quot;https://paragmali.com/blog/eight-primitives-one-worm-the-windows-security-wars-part-2-2/&quot; rel=&quot;noopener&quot;&gt;Part 2&lt;/a&gt;, a working mental model of the Windows process / token / privilege-ring architecture (LSASS, NTLM, Kerberos AS-REQ/TGS-REQ, NTFS DACLs, EPROCESS internals, PCRs, SLAT, VTL0/VTL1), and familiarity with MS-NLMP section 3.3.2 NTLMv2 if you have not seen the construction before [@ms-nlmp-ntlmv2]. The graduate-seminar baseline is &lt;em&gt;Windows Internals&lt;/em&gt; 6e Parts 1 and 2 [@windows-internals-6e-p1; @windows-internals-6e-p2].&lt;/p&gt;
&lt;p&gt;June 17, 2010. An antivirus analyst at VirusBlokAda in Minsk named Sergey Ulasen receives a sample from an Iranian customer whose Windows boxes are rebooting on their own [@zetter-countdown-to-zero-day]. The dropper carries valid Authenticode signatures from Realtek Semiconductor and JMicron Technology [@symantec-stuxnet-dossier-v14]. The worm propagates via a previously unknown LNK shortcut bug that fires when Windows merely &lt;em&gt;displays&lt;/em&gt; the icon of a crafted file [@ms-bulletin-ms10-046]. Eleven months later, in May 2011, a French government IT engineer named Benjamin Delpy publishes a closed-source proof-of-concept called Mimikatz that pulls NT hashes and Kerberos tickets out of the LSASS process memory of every Windows box he has ever logged into and prints them to the operator&apos;s console in one command [@greenberg-mimikatz-wired; @wikipedia-mimikatz]. The conventional history puts these two events on different pages of different books. This article argues they are the two visible faces of a single structural shift.&lt;/p&gt;
&lt;p&gt;The shift is easy to state and easy to underrate. &lt;em&gt;Defensive success at one layer reliably produces attacker innovation at the next layer up.&lt;/em&gt; Microsoft spent the 2009-2014 window shipping the most ambitious per-binary hardening programme of any commercial operating system in history -- AppLocker, ASLR improvements, BitLocker To Go, UEFI Secure Boot, Measured Boot, Early Launch Antimalware, AppContainer, the WinRT sandbox, and in-box Windows Defender [@ms-applocker; @ms-secure-boot; @ms-elam; @windows-internals-6e-p1]. The programme worked. It killed the unsigned-bootloader rootkit class, the pre-antivirus-launch malware class, and the in-process Internet Explorer rendering pwnage class. None of those primitives stopped Stuxnet on a Windows 7 host with USB enabled, and none of them stopped Mimikatz on any host where an administrator opened a console.&lt;/p&gt;
&lt;p&gt;The reason is structural, not engineering. Every per-binary mitigation prevents the &lt;em&gt;wrong&lt;/em&gt; code from running. Stuxnet&apos;s win32k.sys kernel exploit and Mimikatz&apos;s &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; command did not need to be wrong code. They needed to be the &lt;em&gt;right&lt;/em&gt; code -- code an administrator chose to run, or a signed driver Microsoft itself had allowed to load -- running where the credentials lived. The credentials lived in the memory of a long-lived user-mode service called LSASS, and they lived there by design because the single sign-on contract requires the operating system to re-authenticate the user to network servers without re-prompting [@ms-credentials-processes]. The mitigation surface and the attack surface were not at the same layer.&lt;/p&gt;

timeline
    title 2009-2014 Windows Security Split Screen
    section Defender
        Oct 22 2009 : Windows 7 GA: AppLocker, ASLR improvements, BitLocker To Go
        Oct 26 2012 : Windows 8 GA: Secure Boot, ELAM, AppContainer, in-box Defender
        Oct 17 2013 : Windows 8.1: Restricted Admin RDP, LSA Protected Process
        May 13 2014 : KB2871997: WDigest opt-out, Restricted Admin back-port
        Nov 11 2014 : MS14-066 Schannel patch closes the window
    section Attacker
        Jan 12 2010 : Operation Aurora disclosed (single IE 0-day, espionage)
        Jun 17 2010 : VirusBlokAda identifies Stuxnet from an Iranian customer sample
        Dec 27 2010 : Dang and Ferrie present Stuxnet analysis at 27C3 Berlin
        May 2011 : Delpy releases Mimikatz (closed source)
        Aug 1 2013 : Duckwall and Campbell BlackHat USA Pass-the-Hash 2
        Apr 6 2014 : Mimikatz GitHub repository created
        Aug 7 2014 : Delpy and Duckwall BlackHat USA Golden Ticket reveal
&lt;p&gt;If both events were faces of the same shift, what was the shift? To see it, we have to start with what Microsoft was actually shipping.&lt;/p&gt;
&lt;h2&gt;2. The Hardening Decade: What Microsoft Was Doing 2009-2014&lt;/h2&gt;
&lt;p&gt;The popular story of 2009-2014 is that Microsoft was asleep while the Russians ate their lunch. That story is wrong. Microsoft shipped, in a single five-year window, more new platform-security primitives than the company had shipped in the previous decade combined. The problem was not the engineering. The problem was that the entire programme was orthogonal to the credential layer.&lt;/p&gt;
&lt;h3&gt;2.1 Windows 7 (October 22, 2009): per-binary control, finally&lt;/h3&gt;
&lt;p&gt;Windows 7 was the first Microsoft client operating system shipped after the &lt;a href=&quot;https://paragmali.com/blog/two-months-without-code-the-windows-security-wars-part-1-199/&quot; rel=&quot;noopener&quot;&gt;Trustworthy Computing memo&lt;/a&gt; had finished one full Secure Development Lifecycle revolution. The headline platform addition was &lt;strong&gt;AppLocker&lt;/strong&gt;, an application-control framework that let administrators allow or deny executables, scripts, MSI installers, DLLs, and packaged apps by publisher, file hash, or path [@ms-applocker]. Rules were authored in Group Policy and enforced by the Application Identity service. The rule-collection design was the first time a Microsoft Windows shipped a coherent allowlisting story rather than a bag of registry knobs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;AppLocker&lt;/a&gt; carried two structural gaps that took years to live down. First, the DLL rule collection was off by default. Enabling it broke application compatibility on almost every real estate. Second, the Application Identity service ran as a normal Windows service, which meant an attacker who reached LocalSystem could &lt;code&gt;sc stop AppIDSvc&lt;/code&gt; and degrade enforcement open until the next reboot.This admin-stoppable-service gap is the design lesson that becomes the brief for Windows Defender Application Control&apos;s kernel-enforced policy model in Part 4 of this series. A third structural gap matters for the credential-theft era this article documents. AppLocker&apos;s publisher- and path-rule design decisions assume the file-system DACL stack enforces a clean read-allow / write-deny split for low-privileged users [@ms-applocker-design]. It does not.&lt;/p&gt;
&lt;p&gt;The well-known operator bypass on a default Windows 7 install proceeds in four steps. Step one: identify a directory whose path matches the AppLocker default &lt;code&gt;%WINDIR%\*&lt;/code&gt; allow rule for non-administrators (&lt;code&gt;%WINDIR%\Tasks&lt;/code&gt; is the canonical example because it ships with permissive ACLs to let the Task Scheduler service write child files). Step two: drop the unsigned payload binary into that directory. Step three: invoke the binary by full path. Step four: observe that AppLocker&apos;s path-rule engine consults the configured policy rather than the file&apos;s actual DACL stack and permits execution because the parent directory matches the allow-rule glob. The bypass exists because AppLocker&apos;s rule evaluation and NTFS&apos;s DACL stack live on two independent rails that disagree about which paths a non-administrator may write; the cleanup that closes this class of bypass landed in Windows Defender Application Control, which is the Part 4 story.&lt;/p&gt;
&lt;p&gt;AppLocker killed the per-binary &quot;double-click an unsigned EXE on a managed desktop&quot; attack class on every estate that deployed it, which turned out to be a strikingly small fraction of the Fortune 500.&lt;/p&gt;
&lt;p&gt;Windows 7 also tightened the in-process mitigation surface. Address Space Layout Randomisation got a new opt-in &lt;em&gt;ForceASLR&lt;/em&gt; flag callable via the loader&apos;s &lt;code&gt;MitigationOptions&lt;/code&gt; field, letting administrators force randomisation even on EXEs and DLLs that had been compiled without the &lt;code&gt;/DYNAMICBASE&lt;/code&gt; linker switch [@windows-internals-6e-p1].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BitLocker To Go for removable media&lt;/strong&gt; finally gave administrators a defensible answer to the lost-USB-stick incident report. The on-disk format is a Full Volume Encryption v2 (FVE2) volume encrypted with plain AES-CBC; unlike fixed-disk &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; on Vista and original-release Windows 7, BitLocker To Go &lt;em&gt;disables&lt;/em&gt; the Elephant Diffuser on removable drives so the small unencrypted &lt;em&gt;discovery volume&lt;/em&gt; at the start of the device can ship &lt;code&gt;BitLockerToGo.exe&lt;/code&gt;, the Windows XP / Vista &lt;em&gt;BitLocker To Go Reader&lt;/em&gt; that supports plain AES-CBC only [@ms-bitlocker-configure]. The Reader prompts for one of three key protectors: a password, a smart card, or an automatic-unlock recovery key escrowed by Group Policy to Active Directory. The discovery-volume design is the operational concession that lets a 2009 administrator hand a BitLocker-To-Go stick to a vendor running Windows XP SP3 without giving the vendor a usable plaintext copy; the diffuser drop is the cryptographic concession that makes the Reader compatibility story possible. The threat-model concession that BitLocker To Go does not cover is the unattended-laptop / cold-boot attack class against the &lt;em&gt;primary&lt;/em&gt; disk&apos;s TPM-released VMK [@ms-bitlocker-countermeasures], which is the Evil-Maid territory Joanna Rutkowska and Alex Tereshkin demonstrated against TrueCrypt full-disk encryption in October 2009 [@rutkowska-evil-maid-2009] and which BitLocker would not fully answer until pre-boot PIN enforcement matured.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DirectAccess&lt;/strong&gt; shipped as an always-on, certificate-anchored, IPsec-over-IPv6 tunnelled successor to traditional VPNs. The architectural design used a dual-tunnel model [@ms-directaccess-design-guide]: an &lt;em&gt;infrastructure tunnel&lt;/em&gt; established at machine boot using a machine certificate, which gave the client reach-back to domain controllers, DNS, and management infrastructure &lt;em&gt;before&lt;/em&gt; any user had logged on; and an &lt;em&gt;intranet tunnel&lt;/em&gt; established at user logon using user credentials, which carried application traffic to the internal corporate network.&lt;/p&gt;
&lt;p&gt;Because DirectAccess required end-to-end IPv6 in an era when public IPv6 was a rounding error, the design layered three transition technologies in priority order: 6to4 (for clients with a public IPv4 address), Teredo (for clients behind NAT), and IP-HTTPS (a TLS-encapsulated IPv6 transport that worked across any environment that allowed outbound HTTPS, included specifically as the fallback for hotel and conference networks that blocked native IPv6 and UDP-Teredo). The always-on-before-logon property is what made DirectAccess operationally distinct from a traditional VPN: a help-desk-recoverable password reset, a Group Policy push, or a software-distribution job could reach a remote machine the instant it had Internet connectivity, with no user action required.DirectAccess was later quietly deprecated in favour of Always On VPN and Microsoft Tunnel; the architectural lesson it carries is that certificate-anchored client trust scales operationally only when the certificate lifecycle is automated end-to-end.&lt;/p&gt;
&lt;p&gt;What this killed: the per-binary &quot;unsigned EXE on a managed desktop&quot; class. What it did not touch: anything inside an LSASS-holding process tree.&lt;/p&gt;
&lt;h3&gt;2.2 Windows 8 (October 26, 2012): the boot chain and the sandbox&lt;/h3&gt;
&lt;p&gt;Windows 8 is the year the per-binary playbook reached architectural maturity. Four primitives shipped at once, and they all aim at distinct points on the trust stack.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UEFI Secure Boot&lt;/strong&gt; anchors the boot chain in firmware. The Platform Key, signed Key Exchange Keys, and the signature database &lt;code&gt;db&lt;/code&gt; together require the firmware to verify the signature of every UEFI driver, every option ROM, and the operating-system loader before transferring control [@ms-secure-boot; @ms-bulletin-ms10-046]. A revocation database &lt;code&gt;dbx&lt;/code&gt; lets Microsoft retire keys and binaries that have been compromised. Windows 8 was the first Microsoft client operating system whose Logo certification required &lt;a href=&quot;https://paragmali.com/blog/secure-boot-in-windows-the-chain-from-sector-zero-to-userini/&quot; rel=&quot;noopener&quot;&gt;Secure Boot&lt;/a&gt; enablement by default; the chain is anchored to the UEFI 2.3.1 Errata C specification (June 2012).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Measured Boot&lt;/strong&gt; complements Secure Boot. Each stage of the boot chain extends a SHA-256 measurement into Platform Configuration Registers 0 through 7 of the Trusted Platform Module, and the TPM event log records what was measured [@windows-internals-6e-p1]. BitLocker can then bind its Volume Master Key release to a specific PCR profile, so a tampered bootloader will not yield the disk key on next boot. Secure Boot decides whether the code is allowed to run; &lt;a href=&quot;https://paragmali.com/blog/measured-boot-the-tcg-event-log-from-srtm-to-pcr-bound-bitlo/&quot; rel=&quot;noopener&quot;&gt;Measured Boot&lt;/a&gt; decides whether to release secrets to the code that ran.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Early Launch Antimalware (ELAM)&lt;/strong&gt; is the first boot-start driver loaded after the kernel. ELAM gets to inspect, classify, and refuse subsequent boot-start drivers via the &lt;code&gt;BDCB_CLASSIFICATION&lt;/code&gt; enumeration, which returns Good, Bad, Unknown, or BadButCritical [@ms-elam].Microsoft&apos;s own ELAM driver, WdBoot.sys, ships with Windows Defender; third-party antivirus vendors such as McAfee, Symantec, CrowdStrike, and SentinelOne ship their own ELAM drivers post-2014. ELAM services themselves run as a Protected Process Light, which prevents lower-signer-level code from injecting into the antimalware engine. ELAM killed the rootkit-loaded-before-AV class that had defined kernel-mode malware tradecraft since the early 2000s.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AppContainer&lt;/strong&gt; introduces the LowBox access token. Each Modern (Metro) Windows Runtime app receives a token with a per-package security identifier and a vector of capability SIDs; resource access checks intersect the capability set with the resource&apos;s discretionary access control list [@windows-internals-6e-p1]. The model is structurally similar to iOS entitlements: the kernel refuses any access the manifest did not declare. Windows 8 also ships the in-box &lt;a href=&quot;https://paragmali.com/blog/the-defenders-dilemma-microsoft-antivirus/&quot; rel=&quot;noopener&quot;&gt;Windows Defender&lt;/a&gt; (replacing the optional Microsoft Security Essentials), and Internet Explorer 10 runs Enhanced Protected Mode inside an &lt;a href=&quot;https://paragmali.com/blog/appcontainer-and-lowbox-tokens-windowss-capability-sandbox/&quot; rel=&quot;noopener&quot;&gt;AppContainer&lt;/a&gt;, killing the in-process IE-rendering pwnage class that had dominated browser-borne malware for a decade.&lt;/p&gt;
&lt;p&gt;A word on branding discipline. Windows 8&apos;s sandbox is correctly named WinRT plus AppContainer plus Modern (Metro) apps. &lt;em&gt;UWP&lt;/em&gt; (Universal Windows Platform) is the Windows 10 brand introduced July 29, 2015; calling any Windows 8 deliverable UWP is a category error.&lt;/p&gt;
&lt;p&gt;What this killed: unsigned-bootloader rootkits (Secure Boot), pre-AV-launch malware (ELAM), in-process IE-rendering pwnage (AppContainer plus Enhanced Protected Mode). What it did not touch: LSASS.&lt;/p&gt;
&lt;h3&gt;2.3 Windows 8.1 and Server 2012 R2 (October 17, 2013): the first counter-pivot&lt;/h3&gt;
&lt;p&gt;Windows 8.1 is where Microsoft first lands product-level controls that &lt;em&gt;directly&lt;/em&gt; answer credential-replay tradecraft.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Restricted Admin RDP&lt;/strong&gt; changes the protocol so that the client never sends the user&apos;s plaintext password to the server&apos;s LSASS [@kb2871997]. Instead, the server issues a network challenge that the client signs with its local NT hash. The classic credential-disclosure-at-server failure mode (a foothold on the RDP server learns every administrator&apos;s plaintext password as they log in) is closed. The replay failure mode is not, but Section 6 evaluates that honestly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LSA Protected Process&lt;/strong&gt; loads the LSASS process as a Protected Process Light with the signer level &lt;code&gt;PsProtectedSignerLsa&lt;/code&gt;. Once Protected, even a process running as NT AUTHORITY\SYSTEM cannot call &lt;code&gt;OpenProcess(PROCESS_VM_READ)&lt;/code&gt; against LSASS [@ms-lsa-protection]. The flag is enabled by setting &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\Lsa\RunAsPPL&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;. The architectural intuition is right; the bypass class lives in kernel mode and gets evaluated in Section 6.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Restricted Admin RDP and LSA Protected Process are the first product-level Microsoft acknowledgements that the credential layer needed its own defensive rail, distinct from the per-binary playbook. Together they foreshadow the architectural pivot that ships in Windows 10 1507 as Virtualisation-Based Security and Credential Guard [@ms-credential-guard]. The full evaluation of both controls -- what they accomplish, what they leave open, and why -- is the subject of Section 6.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Every primitive above stops the wrong code from running. The threat model is about to move on.&lt;/p&gt;
&lt;h2&gt;3. Stuxnet: The Nation-State Zero-Day Reveal&lt;/h2&gt;
&lt;h3&gt;3.1 Discovery timeline&lt;/h3&gt;
&lt;p&gt;Sergey Ulasen&apos;s June 17, 2010 sample at VirusBlokAda is the public discovery date [@zetter-countdown-to-zero-day]. The worm had been operating in the wild since at least 2009. Within weeks, Kaspersky, Symantec, and ESET independently confirmed the family. By September 2010, Ralph Langner at Langner Communications had identified the payload&apos;s specific target: Siemens Step 7 industrial-control software running on S7-300 programmable logic controllers, programmed to manipulate the rotor speeds of cascade-mounted gas centrifuges at the Natanz uranium enrichment facility in Iran [@langner-to-kill-a-centrifuge].&lt;/p&gt;
&lt;p&gt;On December 27, 2010, Bruce Dang of Microsoft&apos;s Security Response Center and Peter Ferrie co-presented &quot;Adventures in Analyzing Stuxnet&quot; at the 27th Chaos Communication Congress (27C3) in Berlin [@dang-ferrie-27c3].The venue is 27C3, not 29C3, and Dang&apos;s affiliation is Microsoft MSRC, not Symantec; the talk is the canonical engineering primary for the win32k.sys keyboard-layout kernel exploit. Their first-hand engineering walkthrough of the win32k.sys kernel exploit is the canonical record of how Stuxnet escalated privilege on patched Windows 7 systems. In February 2011, Nicolas Falliere, Liam O Murchu, and Eric Chien of Symantec Security Response published the v1.4 W32.Stuxnet Dossier, which enumerated the four Windows zero-days, the two stolen Authenticode certificates, and the Step 7 / S7-300 payload [@symantec-stuxnet-dossier-v14]. Ralph Langner&apos;s November 2013 &quot;To Kill a Centrifuge&quot; closed the analytical loop by identifying not one but two distinct centrifuge-attacks bundled into the same worm: an earlier rotor-overpressure attack and the later rotor-speed manipulation attack [@langner-to-kill-a-centrifuge].&lt;/p&gt;
&lt;h3&gt;3.2 The four zero-days&lt;/h3&gt;
&lt;p&gt;The Symantec dossier&apos;s accounting of Stuxnet&apos;s Windows zero-days is the canonical inventory. There were four, used across the worm&apos;s propagation and escalation surfaces, &lt;strong&gt;not&lt;/strong&gt; chained in a single sequential exploit.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bulletin&lt;/th&gt;
&lt;th&gt;CVE&lt;/th&gt;
&lt;th&gt;Role in the worm&lt;/th&gt;
&lt;th&gt;Patch date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MS10-046&lt;/td&gt;
&lt;td&gt;CVE-2010-2568&lt;/td&gt;
&lt;td&gt;LNK shortcut RCE; propagation via USB without autorun [@ms-bulletin-ms10-046]&lt;/td&gt;
&lt;td&gt;August 2, 2010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS10-061&lt;/td&gt;
&lt;td&gt;CVE-2010-2729&lt;/td&gt;
&lt;td&gt;Print Spooler RCE; network-layer propagation [@ms-bulletin-ms10-061]&lt;/td&gt;
&lt;td&gt;September 14, 2010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS10-073&lt;/td&gt;
&lt;td&gt;CVE-2010-2743&lt;/td&gt;
&lt;td&gt;win32k.sys keyboard-layout local privilege escalation [@ms-bulletin-ms10-073]&lt;/td&gt;
&lt;td&gt;October 12, 2010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MS10-092&lt;/td&gt;
&lt;td&gt;CVE-2010-3338&lt;/td&gt;
&lt;td&gt;Task Scheduler local privilege escalation [@ms-bulletin-ms10-092]&lt;/td&gt;
&lt;td&gt;December 14, 2010&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The LNK bug (MS10-046) is the propagation-by-USB primitive that gave Stuxnet its air-gap-jumping reputation: merely displaying the icon of a crafted shortcut, which Windows Explorer did automatically when the user opened the USB drive, triggered code execution [@ms-bulletin-ms10-046]. The Print Spooler RCE (MS10-061) addressed a Spooler permissions-validation bug that let Stuxnet propagate over the network as a printer-share request [@ms-bulletin-ms10-061].The Print Spooler attack surface returned a decade later as CVE-2021-34527 PrintNightmare, demonstrating that a sufficiently complex local-privilege-escalation surface tends to be re-discoverable across architectural rewrites. The keyboard-layout LPE (MS10-073) was the one Dang and Ferrie walked at 27C3 -- the kernel indexed a table of function pointers when loading a keyboard layout from disk, and Stuxnet supplied a layout that pointed the index at attacker memory [@ms-bulletin-ms10-073]. The Task Scheduler LPE (MS10-092) corrected the way Task Scheduler conducted integrity checks to validate that tasks ran with their intended user privileges [@ms-bulletin-ms10-092]. Stuxnet also re-used the older MS08-067 NetAPI worm bug on unpatched hosts as a non-zero-day propagation path [@ms-bulletin-ms08-067] -- this is the Conficker bug from October 2008, not a 2010 zero-day, and any four-zero-day count that includes it is wrong.&lt;/p&gt;

flowchart LR
    subgraph Propagation
        A[&quot;LNK shortcut RCE&lt;br /&gt;MS10-046 / CVE-2010-2568&quot;]
        B[&quot;Print Spooler RCE&lt;br /&gt;MS10-061 / CVE-2010-2729&quot;]
    end
    subgraph Escalation
        C[&quot;win32k.sys keyboard-layout LPE&lt;br /&gt;MS10-073 / CVE-2010-2743&quot;]
        D[&quot;Task Scheduler LPE&lt;br /&gt;MS10-092 / CVE-2010-3338&quot;]
    end
    subgraph Payload
        E[&quot;Siemens Step 7 / S7-300 PLC&lt;br /&gt;centrifuge rotor manipulation&quot;]
    end
    A --&amp;gt; C
    A --&amp;gt; D
    B --&amp;gt; C
    B --&amp;gt; D
    C --&amp;gt; E
    D --&amp;gt; E
&lt;h3&gt;3.3 The stolen Authenticode certificates&lt;/h3&gt;
&lt;p&gt;The worm&apos;s dropper was signed by two real, valid &lt;a href=&quot;https://paragmali.com/blog/authenticode-and-catalog-files-the-crypto-foundation-under-w/&quot; rel=&quot;noopener&quot;&gt;Authenticode certificates&lt;/a&gt; issued to Realtek Semiconductor and JMicron Technology [@symantec-stuxnet-dossier-v14]. Both certificates were revoked within weeks of disclosure, but during the operational window of Stuxnet, every signature check Windows performed against the dropper returned a clean verdict.The Realtek and JMicron certificates were not merely stolen out of an email inbox; the corresponding hardware security modules were almost certainly accessed in person at the original equipment manufacturers&apos; facilities in the Hsinchu Science Park, Taiwan -- the long-form reconstruction in Kim Zetter&apos;s &lt;em&gt;Countdown to Zero Day&lt;/em&gt; lays out the physical-access logistics that the wire-only theft hypothesis cannot satisfy [@zetter-countdown-to-zero-day]. This prefigured the supply-chain attack class that becomes SolarWinds a decade later. This was the first publicly analyzed kinetic-effect proof that the code-signing trust root -- Authenticode and the kernel-mode driver signing PKI that depended on it -- was an adversary target rather than a structural defence.&lt;/p&gt;
&lt;h3&gt;3.4 Architectural lessons&lt;/h3&gt;
&lt;p&gt;Two structural lessons emerged from the disclosure cycle. First, USB as an attack surface acquired its own discipline. In February 2011, Microsoft re-released the autorun update covered by Microsoft Security Advisory 967940 / KB971029 as an automatic update via Windows Update, having previously offered it as an optional patch in February 2009 [@krebs-autorun-2011]. Second, IT and operational-technology (OT) cross-domain trust collapsed as a defensible perimeter -- Natanz was an air-gapped network that a USB stick crossed, and every CISO with operational-technology assets had to re-ask the question of whether a nation-state would burn a Windows zero-day to break their plant.&lt;/p&gt;
&lt;h3&gt;3.5 Did Stuxnet defeat any defender primitive Windows 7 shipped?&lt;/h3&gt;
&lt;p&gt;The narrow answer is no, the worm did not need to. Stuxnet&apos;s propagation primitives carried their own attack code -- the LNK bug ran from Explorer, the Spooler bug ran from the printer-share RPC interface -- so they did not need to defeat AppLocker (AppLocker only blocks executions a configured rule denies; an explorer.exe rendering a crafted shortcut was not a denied execution) or ASLR or DEP. The win32k.sys local privilege escalation, however, foreshadowed the Section 5 argument neatly: the per-binary mitigations Windows 7 shipped (AppLocker, ASLR, DEP, ForceASLR) did nothing for a kernel-mode bug, because kernel-mode is where those mitigations are enforced from.&lt;/p&gt;
&lt;h3&gt;3.6 Was Stuxnet really the &lt;em&gt;first&lt;/em&gt; nation-state Windows zero-day operation?&lt;/h3&gt;
&lt;p&gt;Only with two qualifiers. Operation Aurora -- the espionage campaign Google publicly disclosed on January 12, 2010 [@google-aurora-blog; @google-aurora-wayback] -- pre-dates Stuxnet&apos;s June 2010 public identification by roughly five months and used a single Windows / Internet Explorer zero-day, the IE use-after-free catalogued as CVE-2010-0249 [@nvd-cve-2010-0249], for cyber-espionage. Google&apos;s own disclosure stated that &quot;at least twenty other large companies from a wide range of businesses -- including the Internet, finance, technology, media and chemical sectors -- have been similarly targeted&quot; [@google-aurora-wayback]. The publicly named subset that emerged across the January 12-15, 2010 disclosure window included Adobe Systems (acknowledged on the Adobe corporate blog January 12, 2010) [@adobe-aurora-disclosure], Juniper Networks, Rackspace [@wikipedia-operation-aurora], plus Yahoo, Symantec, Northrop Grumman, Dow Chemical, and Morgan Stanley named in Ariana Eunjung Cha and Ellen Nakashima&apos;s Washington Post coverage on January 14, 2010 [@wapo-aurora-cha-nakashima]. Dmitri Alperovitch of McAfee Labs named the campaign &quot;Operation Aurora&quot; on January 14, 2010 based on a &lt;code&gt;\..\Aurora_Src\AuroraVNC\&lt;/code&gt; file-path string recovered from the malware binaries [@mcafee-aurora-alperovitch]. Microsoft patched the IE bug out-of-band as MS10-002 on January 21, 2010 [@ms-bulletin-ms10-002].&lt;/p&gt;

Aurora is the necessary disambiguation. The popular framing of Stuxnet as the first nation-state Windows zero-day operation is *false* without qualifiers. Aurora used one zero-day for espionage in January 2010; Stuxnet used four zero-days for kinetic effect in June 2010. The defensible framing is: *Stuxnet is the first publicly analyzed nation-state Windows operation that burned multiple zero-days for kinetic, physical effect* [@symantec-stuxnet-dossier-v14; @google-aurora-blog; @nvd-cve-2010-0249]. Both qualifiers (&quot;multi-zero-day&quot; and &quot;kinetic / physical&quot;) are load-bearing. Drop either and Aurora falsifies the framing.
&lt;p&gt;Stuxnet showed nation-states would burn four Windows zero-days for a single operation. But four zero-days is an expensive way to compromise a credential, and as it turned out, a French engineer was about to make zero-days irrelevant for the credential-theft problem.&lt;/p&gt;
&lt;h2&gt;4. Mimikatz: The Credential Layer Demolition&lt;/h2&gt;
&lt;p&gt;Benjamin Delpy describes Mimikatz, in Andy Greenberg&apos;s Wired profile, as &quot;a side project to learn C&quot; [@greenberg-mimikatz-wired]. The reader&apos;s natural reaction -- a side project that broke a decade of Microsoft&apos;s most ambitious hardening programme? -- is precisely the point.&lt;/p&gt;
&lt;h3&gt;4.1 Delpy, LSASS, and the May 2011 release&lt;/h3&gt;
&lt;p&gt;Delpy was at the time an IT manager at a French government institution he declines to name [@greenberg-mimikatz-wired]. He had become curious about an architectural quirk: Windows could prompt for his password at logon, then later authenticate him to remote IIS and SMB servers using HTTP Digest without ever asking again. Something inside the OS had to hold a recoverable form of his password. He started reverse-engineering the Local Security Authority Subsystem Service (LSASS) and the credential-provider tree behind it.&lt;/p&gt;

A long-lived user-mode Windows process that holds the secrets the operating system needs to satisfy single sign-on across SMB, RPC, HTTP, RDP, IIS, and MS-SQL without re-prompting the user. By design, LSASS caches NT hashes, Kerberos Ticket-Granting Tickets, and (depending on the loaded security packages) recoverable plaintext credentials [@ms-credentials-processes]. It is the load-bearing target of every credential-extraction tool the next decade produces.
&lt;p&gt;The architectural quirk was structural, not accidental. The single sign-on contract requires the operating system to &lt;em&gt;re-authenticate&lt;/em&gt; the user to network services, and the network protocols of the 1990s and 2000s (NTLM, Kerberos, HTTP Digest, MS-CHAP) all required either a hash, a ticket, or a recoverable plaintext to do that re-authentication [@ms-credentials-processes]. LSASS held all three. There was no way to satisfy the contract without holding the secret in some recoverable form inside an LSASS-controlled memory region.&lt;/p&gt;
&lt;p&gt;Delpy released the first version of Mimikatz in May 2011 as closed-source software [@greenberg-mimikatz-wired; @wikipedia-mimikatz].Delpy describes Mimikatz as &quot;a side project to learn C&quot; in the Wired profile; the framing matters because it underlines that breaking Windows credential security at this depth did not require nation-state resources -- a single engineer with a debugger could do it. Microsoft&apos;s response to his initial private disclosure had been, in his telling, that &quot;you don&apos;t want to fix it&quot;; he made the tool public to force the conversation. The GitHub repository &lt;code&gt;gentilkiwi/mimikatz&lt;/code&gt; was created on April 6, 2014 at 18:30:02 UTC -- the API-verifiable timestamp [@mimikatz-github]. Any &quot;Mimikatz first released in 2007&quot; claim refers to Delpy&apos;s pre-release private experimentation, not a public release.&lt;/p&gt;
&lt;h3&gt;4.2 Four primitives that broke the credential layer&lt;/h3&gt;
&lt;p&gt;The Mimikatz module set Delpy authored over 2011-2014 contains four primitives that together explain why every per-binary mitigation Microsoft had shipped was insufficient.&lt;/p&gt;

Replay an NT hash as a bearer credential against any service that accepts NTLM authentication, *without* ever knowing the user&apos;s plaintext password [@mimikatz-github; @duckwall-campbell-bh2013]. The NTLM protocol authenticates by proof-of-possession of the NT hash, not proof-of-knowledge of the password.
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;Pass-the-Hash&lt;/a&gt; is the load-bearing primitive. NTLM authentication on the wire authenticates by proof-of-possession of the NT hash, not proof-of-knowledge of the password. The plaintext password is computed exactly once, at logon, to derive the NT hash via &lt;code&gt;MD4(UTF16LE(password))&lt;/code&gt;. After that the operating system does not need the cleartext again for NTLM. Anyone holding the hash can authenticate as the user without ever knowing the password. The real NTLMv2 protocol per MS-NLMP §3.3.2 is a two-stage HMAC-MD5 construction [@ms-nlmp-ntlmv2]: stage 1 derives an intermediate &lt;code&gt;NTOWFv2 = HMAC_MD5(NT_hash, UTF16LE(UPPERCASE(user) || domain))&lt;/code&gt;; stage 2 computes &lt;code&gt;NTProofStr = HMAC_MD5(NTOWFv2, ServerChallenge || ClientChallengeBlob)&lt;/code&gt;. The bearer-credential invariant survives both stages -- the function consumes the NT hash directly and never references the cleartext -- which is the exact property Pass-the-Hash exploits.&lt;/p&gt;
&lt;p&gt;{`
// Illustrative -- the real NTLMv2 protocol is a two-stage HMAC-MD5
// construction (see MS-NLMP section 3.3.2):
//   Stage 1: NTOWFv2 = HMAC_MD5(NT_hash, UPPERCASE(user) || domain)
//   Stage 2: NTProofStr = HMAC_MD5(NTOWFv2, ServerChallenge || temp)
// The Pass-the-Hash invariant -- that the NT hash is the bearer
// credential because the protocol consumes it without ever needing
// the cleartext password -- survives the simplification below.
const crypto = require(&apos;crypto&apos;);&lt;/p&gt;
&lt;p&gt;function ntlmResponse(ntHash, serverNonce, clientNonce) {
  // Simplified single-stage HMAC-MD5 keyed on the NT hash.
  // The plaintext password is never used by the protocol after logon.
  const hmac = crypto.createHmac(&apos;md5&apos;, Buffer.from(ntHash, &apos;hex&apos;));
  hmac.update(Buffer.concat([serverNonce, clientNonce]));
  return hmac.digest(&apos;hex&apos;);
}&lt;/p&gt;
&lt;p&gt;const stolenHash = &apos;8846f7eaee8fb117ad06bdd830b7586c&apos;;
const serverNonce = Buffer.from(&apos;0123456789abcdef&apos;, &apos;hex&apos;);
const clientNonce = Buffer.from(&apos;fedcba9876543210&apos;, &apos;hex&apos;);&lt;/p&gt;
&lt;p&gt;console.log(&apos;NTLM response:&apos;, ntlmResponse(stolenHash, serverNonce, clientNonce));
console.log(&apos;No plaintext password was used. The hash IS the credential.&apos;);
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The plaintext password is not the secret. Once the operating system has derived the hash at logon, anyone who reaches LSASS and reads that hash can authenticate as the user against any NTLM-accepting service for as long as that hash remains valid -- which is until the user next changes the password. The credential-replay class is a corollary of this single insight applied to different bearer credentials.&lt;/p&gt;
&lt;/blockquote&gt;

Extract a Kerberos Ticket-Granting Ticket or service ticket from LSASS and re-import it into another logon session for replay. Mimikatz exposes both halves: `sekurlsa::tickets /export` extracts; `kerberos::ptt` re-imports [@mimikatz-github].
&lt;p&gt;Pass-the-Ticket is the Kerberos analogue of Pass-the-Hash. A Kerberos TGT is a bearer credential by design -- it proves the holder authenticated to the Key Distribution Center -- and like the NT hash, anyone holding the ticket can replay it. Mimikatz&apos;s &lt;code&gt;kerberos::ptt&lt;/code&gt; injects a ticket blob into the local session&apos;s ticket cache; the next call to &lt;code&gt;klist&lt;/code&gt; shows it as if the local logon had earned it.&lt;/p&gt;

Use a stolen NT hash to request a *fresh* Kerberos TGT from the Key Distribution Center -- the bridge from an NTLM-recovered hash to a Kerberos-issued ticket. Defeats estates that have disabled NTLM but trust Kerberos pre-authentication keys derived from the same password hash [@mimikatz-github].
&lt;p&gt;Overpass-the-Hash is the bridge primitive. Estates that disabled NTLM in 2012-2014 in response to early Pass-the-Hash discussion believed they had closed the credential-replay door. Overpass-the-Hash re-opened it by re-using the NT hash to compute the Kerberos pre-authentication value, then sending a normal Kerberos AS-REQ. The KDC issued a TGT keyed on the same secret the NTLM stack had used. From there, every subsequent Kerberos service ticket request was a legitimate Kerberos exchange backed by a stolen secret.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WDigest plaintext-in-memory&lt;/strong&gt; is the fourth primitive, and the one that surprised even Microsoft&apos;s own teams when Delpy demonstrated it. Microsoft&apos;s WDigest Security Support Provider, which implemented HTTP Digest authentication on the server side and Digest single sign-on on the client side, held the user&apos;s plaintext password in LSASS memory by design, recoverable as long as the user&apos;s session was active.WDigest predates the modern web; HTTP Digest authentication had been essentially deprecated by the time Mimikatz operationalised the plaintext-recovery primitive, which is why the KB2871997 opt-out has near-zero operational downside on any post-2010 estate. Mimikatz&apos;s &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; enumerated the loaded credential-providers, walked the LSASS heap structures, and printed every cached secret it could decrypt -- including, on most pre-2014 estates, the user&apos;s plaintext password in clear text.&lt;/p&gt;
&lt;p&gt;(One discipline note. Skeleton Key is &lt;em&gt;not&lt;/em&gt; one of the Part 3 Mimikatz primitives. Skeleton Key was disclosed by Dell SecureWorks Counter Threat Unit on January 12, 2015 [@secureworks-skeleton-key] and Delpy added &lt;code&gt;misc::skeleton&lt;/code&gt; to Mimikatz on January 17, 2015, both outside the Part 3 window. It opens Part 4.)&lt;/p&gt;

sequenceDiagram
    participant Op as Operator (Admin)
    participant Mim as mimikatz.exe
    participant Krn as Windows Kernel
    participant LSA as LSASS.exe
    Op-&amp;gt;&amp;gt;Mim: privilege::debug
    Mim-&amp;gt;&amp;gt;Krn: AdjustTokenPrivileges (SeDebugPrivilege)
    Krn--&amp;gt;&amp;gt;Mim: TRUE
    Op-&amp;gt;&amp;gt;Mim: sekurlsa::logonpasswords
    Mim-&amp;gt;&amp;gt;Krn: OpenProcess (PROCESS_VM_READ on LSASS PID)
    Krn--&amp;gt;&amp;gt;Mim: process handle
    Mim-&amp;gt;&amp;gt;LSA: ReadProcessMemory (walk security-package list)
    LSA--&amp;gt;&amp;gt;Mim: encrypted credential blobs
    Mim-&amp;gt;&amp;gt;Krn: BCryptDecrypt (LSA master key from same address space)
    Krn--&amp;gt;&amp;gt;Mim: cleartext NT hashes, TGTs, WDigest plaintexts
    Mim--&amp;gt;&amp;gt;Op: print every cached secret
&lt;h3&gt;4.3 The 2013 inflection: graph-walking offensive Active Directory&lt;/h3&gt;
&lt;p&gt;In August 2013, Skip Duckwall and Chris Campbell delivered &quot;Pass-the-Hash 2: The Admin&apos;s Revenge&quot; at Black Hat USA [@duckwall-campbell-bh2013]. The talk did not invent the primitives Mimikatz had already shipped. It made offensive Active Directory tradecraft a public, named discipline by formalising the graph-walking insight: every Windows host an administrator logs into caches a credential for that administrator; every credential cached on a compromised host is a stolen credential; every stolen credential is a new starting node for the next lateral movement. The attack graph closes on the domain controller within hops measured in single digits on almost every real enterprise estate.&lt;/p&gt;
&lt;p&gt;The discipline decomposes into a four-step iterative loop on any Windows estate with cached domain credentials [@duckwall-campbell-bh2013]. &lt;strong&gt;Step one: enumerate active sessions on the compromised host&lt;/strong&gt; -- &lt;code&gt;NetSessionEnum&lt;/code&gt; returns inbound SMB sessions, &lt;code&gt;NetWkstaUserEnum&lt;/code&gt; returns the logged-on user list (pre-KB4480964 without admin rights), and &lt;code&gt;quser&lt;/code&gt; / &lt;code&gt;qwinsta&lt;/code&gt; enumerate interactive logons. The output is the &lt;code&gt;(user, host)&lt;/code&gt; tuple set representing every credential cached in the host&apos;s LSASS. &lt;strong&gt;Step two: identify a reachable administrator&lt;/strong&gt; -- cross-reference each enumerated user against local Administrators group membership and against the domain groups that grant administrative access to a higher-tier host. The output is a set of &lt;code&gt;(harvested-user, target-host)&lt;/code&gt; tuples where the harvested credential can be replayed against the target with administrative privilege. &lt;strong&gt;Step three: Pass-the-Hash to the higher-tier host&lt;/strong&gt; -- inject the harvested NT hash into a new logon session via &lt;code&gt;sekurlsa::pth /run:...&lt;/code&gt; and execute remote commands against the target as the harvested user, with no need for the cleartext password [@mimikatz-github]. &lt;strong&gt;Step four: harvest the new host&apos;s LSASS and repeat&lt;/strong&gt; -- &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; against the new beachhead dumps every credential that host has cached, each becoming a new starting node for the next iteration. The loop terminates when one harvested credential is a Domain Admin.&lt;/p&gt;
&lt;p&gt;This four-step loop is the &lt;em&gt;implicit&lt;/em&gt; graph the article&apos;s diagram illustrates: vertices are users and hosts, edges are &lt;code&gt;MemberOf&lt;/code&gt; (user is a group member), &lt;code&gt;AdminTo&lt;/code&gt; (user has administrative access to a host), and &lt;code&gt;HasSession&lt;/code&gt; (a host currently caches a credential for a user). Three years later, Andy Robbins, Will Schroeder, and Rohan Vazarkar productized this graph at DEF CON 24 in Las Vegas on August 6, 2016 as &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;, which uses the &lt;code&gt;SharpHound&lt;/code&gt; collector to enumerate every vertex and edge, loads them into a Neo4j database, and runs Cypher shortest-path queries from any compromised principal to the &lt;code&gt;Domain Admins&lt;/code&gt; group [@bloodhound-defcon24]. BloodHound is a 2016 artifact and properly belongs to Part 4; for the 2009-2014 Part 3 window, the graph existed only in operator notebooks and on Duckwall and Campbell&apos;s whiteboard, but every Windows estate already had it -- the attacker just had to walk it.&lt;/p&gt;
&lt;h3&gt;4.4 The 2014 inflection: the Golden Ticket&lt;/h3&gt;
&lt;p&gt;In August 2014, Benjamin Delpy and Skip Duckwall jointly presented &quot;Abusing Microsoft Kerberos: Sorry You Guys Don&apos;t Get It&quot; at Black Hat USA [@delpy-duckwall-bh2014].The dual authorship matters: Delpy and Duckwall presented the talk together, and any single-author attribution misses the collaboration that produced the Golden Ticket walkthrough. The headline reveal was the &lt;strong&gt;Golden Ticket&lt;/strong&gt;: a forged Kerberos Ticket-Granting Ticket signed with the stolen NT hash of the domain&apos;s &lt;code&gt;krbtgt&lt;/code&gt; account.&lt;/p&gt;

A forged Kerberos Ticket-Granting Ticket signed with the stolen NT hash of the domain&apos;s krbtgt service account. Grants arbitrary user, arbitrary group, and arbitrary lifetime impersonation across every domain controller in the Active Directory forest. Survives every password reset *except* the krbtgt account&apos;s own [@delpy-duckwall-bh2014; @metcalf-golden-ticket].
&lt;p&gt;The &lt;a href=&quot;https://paragmali.com/blog/krbtgt-the-account-that-owns-active-directory/&quot; rel=&quot;noopener&quot;&gt;krbtgt account&lt;/a&gt; is the master signing key for the domain&apos;s Kerberos infrastructure. Every TGT a domain controller issues is signed with the krbtgt NT hash, and the domain trusts any TGT that verifies against that hash. If an attacker holding domain-admin privileges has ever extracted the krbtgt hash from a domain controller&apos;s LSASS, they can forge a TGT for any user, with any group membership, with any lifetime they choose -- and the domain controllers will accept it as if it had been legitimately issued. The forged ticket survives every routine password reset on the domain because routine password resets do not rotate the krbtgt account. Sean Metcalf&apos;s ADSecurity walkthrough remains the practitioner-grade canonical reference [@metcalf-golden-ticket].&lt;/p&gt;
&lt;h3&gt;4.5 What this proved&lt;/h3&gt;
&lt;p&gt;By the end of 2014, the Mimikatz codebase had operationalised pass-the-hash, pass-the-ticket, overpass-the-hash, WDigest plaintext recovery, and the Golden Ticket on a default-configured modern Windows host. Every credential the LSA process held in memory in a recoverable form was structurally exposed.&lt;/p&gt;
&lt;p&gt;The scope of that claim matters. TPM-bound keys, smart-card private keys behind a hardware boundary, and Kerberos service keys on Windows servers whose LSASS the attacker had not yet compromised were &lt;em&gt;not&lt;/em&gt; exposed by Mimikatz. The precise statement is &lt;em&gt;every credential the LSA process held in memory in a recoverable form&lt;/em&gt;, not &quot;every Windows credential primitive ever,&quot; and the precise statement is the one Microsoft eventually acknowledged in the Mitigating Pass-the-Hash whitepaper series [@ms-pth-v2].&lt;/p&gt;

Mimikatz did not need to defeat AppLocker, ASLR, DEP, or Authenticode. It ran as an administrator, called OpenProcess on LSASS, and walked away with every cached credential the operating system would ever hold. The defender&apos;s playbook had been answering the wrong question.
&lt;p&gt;Stuxnet was a four-zero-day operation that ran once. Mimikatz was a free, open-source command that ran every time. The offensive economics of attacking Windows fleets shifted decisively away from zero-day-burning and toward credential replay. &lt;em&gt;Why&lt;/em&gt; did this happen, and what does it mean for the next decade of Windows defence?&lt;/p&gt;
&lt;h2&gt;5. The Causal Link: Hardening Birthed the Credential-Theft Class&lt;/h2&gt;
&lt;p&gt;After two parallel narratives, the reader has the evidence to follow the argument. This is the article&apos;s intellectual centre.&lt;/p&gt;
&lt;h3&gt;5.1 The pivot up the trust stack&lt;/h3&gt;
&lt;p&gt;While Microsoft was closing per-binary attack surface -- Authenticode, kernel-mode code signing, ASLR, DEP, AppLocker, AppContainer, ELAM, Secure Boot -- attackers pivoted up the trust stack to what those hardened binaries still had to trust: the credentials in LSASS memory, the Kerberos tickets in the LSA cache, and the LSA process address space itself. The mitigation surface and the attack surface are not at the same layer. This is the article&apos;s structural insight, and it is the single sentence the rest of the argument exists to defend.&lt;/p&gt;

flowchart TD
    A[&quot;Hardware root: TPM, UEFI Secure Boot db/dbx&quot;]
    B[&quot;Bootloader signature chain (Secure Boot, Measured Boot)&quot;]
    C[&quot;Kernel-mode code (KMCS, ELAM as first boot-start driver, PatchGuard)&quot;]
    D[&quot;User-mode signed binaries (Authenticode, AppLocker rules)&quot;]
    E[&quot;Sandboxed renderers (AppContainer, EPM, WinRT)&quot;]
    F[&quot;LSASS process memory: NT hashes, Kerberos TGTs, krbtgt key&quot;]
    G[&quot;Attacker primitive: Mimikatz sekurlsa::logonpasswords&quot;]
    A --&amp;gt; B --&amp;gt; C --&amp;gt; D --&amp;gt; E --&amp;gt; F
    G -.reads.-&amp;gt; F
    style F fill:#fde68a,stroke:#b45309,color:#5f370e
    style G fill:#fecaca,stroke:#991b1b,color:#7f1d1d
&lt;p&gt;The diagram makes the asymmetry visible. Every defender control protects a layer &lt;em&gt;below&lt;/em&gt; LSASS. Mimikatz attacks LSASS directly. None of the per-binary controls is in the attack path because Mimikatz does not need to defeat them -- it runs as a process the per-binary controls approved.&lt;/p&gt;
&lt;h3&gt;5.2 The Mimikatz codebase as a single causal node&lt;/h3&gt;
&lt;p&gt;Every credential-replay class that defines the next decade of red-team tradecraft traces to one 2011 codebase. Pass-the-Hash, Pass-the-Ticket, Overpass-the-Hash, Golden Ticket -- all four landed in &lt;code&gt;gentilkiwi/mimikatz&lt;/code&gt;. After the GitHub repository creation on April 6, 2014 [@mimikatz-github], the same codebase later grew the post-Part-3 modules (Skeleton Key and DCSync; see §11 FAQ) [@secureworks-skeleton-key; @metcalf-dcsync]. There is no comparable single codebase on the defender side. Microsoft&apos;s countermeasures landed across at least three product teams (Active Directory, Windows Defender, Hyper-V), and the architectural answer required a hypervisor.&lt;/p&gt;

Because you don&apos;t want to fix it, I&apos;ll show it to the world to make people aware of it. -- Benjamin Delpy [@greenberg-mimikatz-wired]
&lt;p&gt;Delpy&apos;s framing converted a defender&apos;s blind spot into a public, weaponised primitive. Microsoft&apos;s initial dismissal of his private disclosure -- that the credential model was &quot;by design&quot; -- was true, in the most damaging possible sense. The model &lt;em&gt;was&lt;/em&gt; by design. The single sign-on contract required it. Closing the gap required a different design.&lt;/p&gt;
&lt;h3&gt;5.3 The economic argument&lt;/h3&gt;
&lt;p&gt;The shift was economic as much as architectural. A reliable Windows zero-day exploit chain commanded a substantial unit price on the early-2010s grey market and burned on first use: once a sample was disclosed and patched, the exploit was worthless to a serious operator. A Mimikatz invocation, by contrast, is free, reusable indefinitely on any pre-Credential-Guard estate, leaves no on-disk footprint, and runs as the operator the attacker already compromised. The asymmetry is not subtle.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Stuxnet (June 2010)&lt;/th&gt;
&lt;th&gt;Mimikatz (May 2011 onward)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Attacker cost&lt;/td&gt;
&lt;td&gt;Four Windows zero-days + two stolen Authenticode certificates + ICS payload [@symantec-stuxnet-dossier-v14]&lt;/td&gt;
&lt;td&gt;Free open-source tool [@mimikatz-github]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reusability&lt;/td&gt;
&lt;td&gt;Single-use; zero-days patched within months [@ms-bulletin-ms10-046; @ms-bulletin-ms10-061; @ms-bulletin-ms10-073; @ms-bulletin-ms10-092]&lt;/td&gt;
&lt;td&gt;Indefinite on any pre-Credential-Guard host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On-disk footprint&lt;/td&gt;
&lt;td&gt;Multi-megabyte signed dropper + Step 7 / S7 payloads&lt;/td&gt;
&lt;td&gt;Single executable; can run in memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detection footprint&lt;/td&gt;
&lt;td&gt;Symantec / Kaspersky / ESET signatures within weeks of disclosure [@symantec-stuxnet-dossier-v14]&lt;/td&gt;
&lt;td&gt;Initially evades signature-based AV; later detected via ProcessAccess masks on LSASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Target population&lt;/td&gt;
&lt;td&gt;Specific ICS estate (Natanz)&lt;/td&gt;
&lt;td&gt;Every Windows AD estate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threat-model implication&lt;/td&gt;
&lt;td&gt;Nation-states will burn zero-days for kinetic effect&lt;/td&gt;
&lt;td&gt;Anyone with admin can replay every cached credential&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; Defensive success at one layer reliably produces attacker innovation at the next layer up. The 2009-2014 window proves it: Microsoft killed the rootkit, bootkit, and unsigned-bootloader classes; attackers responded by reading the credentials in LSASS memory that every hardened binary still had to trust. The mitigation surface and the attack surface were not at the same layer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the credential layer was structurally broken, why didn&apos;t Microsoft just fix it? They tried. The next section is the honest evaluation of Microsoft&apos;s counter-pivot through November 2014.&lt;/p&gt;
&lt;h2&gt;6. Microsoft&apos;s Counter-Pivot: 2013-2014&lt;/h2&gt;
&lt;p&gt;Microsoft was not asleep. By Windows 8.1 General Availability on October 17, 2013, three controls landed that were &lt;em&gt;directly&lt;/em&gt; a response to Mimikatz. They were partial wins, all of them; the architectural acknowledgement that LSASS-in-VTL0 was unsalvageable would arrive only with Virtualisation-Based Security and Credential Guard in Windows 10 1507 [@ms-credential-guard], outside this article&apos;s window. This section is the honest evaluation of what shipped, what it accomplished, and why none of it was enough.&lt;/p&gt;
&lt;h3&gt;6.1 Restricted Admin RDP&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/rdp-authentication-26-years/&quot; rel=&quot;noopener&quot;&gt;Restricted Admin RDP&lt;/a&gt; changes the Remote Desktop Protocol so that the client never sends the user&apos;s plaintext password to the server&apos;s LSASS [@kb2871997]. Instead, the server issues a Network Level Authentication challenge that the client signs using its local NT hash; the user authenticates to the remote desktop session as a network logon rather than an interactive logon. Critical credential material is never present on the RDP server.&lt;/p&gt;
&lt;p&gt;The bug Restricted Admin closes is the credential-disclosure failure mode: a foothold on the RDP server used to learn every administrator&apos;s plaintext password as they logged in. The bug it leaves open is replay. A Restricted Admin RDP session is a &lt;em&gt;network&lt;/em&gt; logon, and an attacker holding the NT hash for an administrative account can invoke &lt;code&gt;sekurlsa::pth /run:&quot;mstsc /restrictedadmin&quot;&lt;/code&gt; from a compromised host and authenticate to the target RDP server using only the hash. Restricted Admin reduced disclosure; it did not close replay.&lt;/p&gt;

sequenceDiagram
    participant C as RDP Client
    participant S as RDP Server (LSASS)
    Note over C,S: Classic RDP (credential delegation)
    C-&amp;gt;&amp;gt;S: TLS handshake plus plaintext credentials
    S-&amp;gt;&amp;gt;S: LSASS caches plaintext password for session
    Note over S: Foothold on server reveals every admin password
    Note over C,S: Restricted Admin RDP (post-KB2871997)
    C-&amp;gt;&amp;gt;S: Network Level Authentication challenge request
    S-&amp;gt;&amp;gt;C: server nonce
    C-&amp;gt;&amp;gt;C: sign nonce with local NT hash
    C-&amp;gt;&amp;gt;S: signed response
    S-&amp;gt;&amp;gt;S: verify against domain controller
    Note over S: Server never sees plaintext
    Note over C: Attacker with NT hash can still run mstsc with restrictedadmin
&lt;p&gt;Server-side Restricted Admin shipped at Windows 8.1 / Server 2012 R2 General Availability on October 17, 2013. The client-side back-port to Windows 7, Server 2008 R2, Windows 8, and Server 2012 followed via KB2871997 on May 13, 2014 [@kb2871997], which is also where the WDigest opt-out and TokenLeakDetectDelaySecs primitives shipped.&lt;/p&gt;
&lt;h3&gt;6.2 LSA Protected Process (RunAsPPL)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/protected-process-light-when-the-administrator-isnt-enough/&quot; rel=&quot;noopener&quot;&gt;LSA Protected Process&lt;/a&gt; loads LSASS as a Protected Process Light with the signer level &lt;code&gt;PsProtectedSignerLsa&lt;/code&gt;. Once Protected, the Windows kernel refuses any &lt;code&gt;OpenProcess(PROCESS_VM_READ)&lt;/code&gt; call against LSASS from a process running at a lower signer level -- including a process running as NT AUTHORITY\SYSTEM with &lt;code&gt;SeDebugPrivilege&lt;/code&gt; [@ms-lsa-protection]. The flag is enabled by setting &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\Lsa\RunAsPPL&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;. RunAsPPL is the strongest credential-protection primitive Microsoft shipped inside Windows 8.1.&lt;/p&gt;

A kernel-enforced signer level that prevents OpenProcess(PROCESS_VM_READ) and CreateRemoteThread against the protected process from any process running at a lower signer level, regardless of token privileges or session [@itm4n-lsa-protection; @ms-lsa-protection]. The Lsa variant requires every LSA plug-in DLL (SSP, AP, custom credential providers) to itself be signed at a compatible signer level, which is why enabling RunAsPPL on real estates requires an LSA plug-in audit.
&lt;p&gt;The bypass class is Bring Your Own Vulnerable Driver. A malicious kernel-mode driver, loaded through a vulnerable but Microsoft-signed third-party driver that the attacker has placed on disk, can clear the &lt;code&gt;Protection&lt;/code&gt; byte in the kernel &lt;code&gt;EPROCESS&lt;/code&gt; structure for LSASS, after which the &lt;code&gt;OpenProcess(PROCESS_VM_READ)&lt;/code&gt; call succeeds. Mimikatz ships its own kernel driver, &lt;code&gt;mimidrv.sys&lt;/code&gt;, that performs exactly this manipulation [@mimikatz-github]. The structural problem is that RunAsPPL is enforced by the same kernel an attacker is compromising to bypass it; the protection cannot be made strictly stronger inside the same privilege ring than the kernel that enforces it.&lt;/p&gt;

A common misreading is that PPL is a partial Credential Guard, or that Credential Guard replaces PPL. The most useful framing is itm4n&apos;s: *&quot;I noticed that this protection tends to be confused with Credential Guard, which is completely different&quot;* [@itm4n-lsa-protection]. PPL is a same-privilege gate inside VTL0 -- both LSASS and the attacker live in the same kernel address space, and the kernel decides whether to grant a process handle. Credential Guard is a cross-privilege isolation between VTL0 and VTL1 (the Virtual Trust Levels Hyper-V introduces in Windows 10 1507) [@ms-credential-guard]: the credential material lives in a Virtual Secure Mode trustlet (LSAISO) that the VTL0 kernel cannot read because the hypervisor&apos;s Second-Level Address Translation tables deny the mapping. The two controls are complementary -- PPL hardens LSASS against in-VTL0 attackers; Credential Guard moves the high-value secret out of VTL0 entirely. §8.3 develops the cross-privilege isolation argument formally.
&lt;h3&gt;6.3 The Mitigating Pass-the-Hash whitepaper series&lt;/h3&gt;
&lt;p&gt;Microsoft published the Mitigating Pass-the-Hash and Other Credential Theft whitepaper in two versions: v1 in December 2012 from the Trustworthy Computing group [@ms-pth-v1-landing] and v2 in July 2014 [@ms-pth-v2]. There is no v3. Post-2014 guidance migrated into the &lt;em&gt;Securing Privileged Access&lt;/em&gt; online documentation rather than appearing as a numbered v3 PDF, and any &quot;v3 2017&quot; reference is incorrect.&lt;/p&gt;
&lt;p&gt;The v1 paper introduced the tier 0 / tier 1 / tier 2 administrative-account model: separate the accounts that manage the forest (tier 0: domain controllers, AD), the accounts that manage server applications (tier 1: file servers, Exchange, SQL), and the accounts that manage end-user workstations (tier 2: helpdesk, desktop support). The rule is that a tier-N credential must never be exposed on a tier-(N+1) host. The model is sound. The problem is that v1 was recommendations-only with no enforcement primitive inside the operating system, and operators routinely violated tiering (the helpdesk technician fixing the CEO&apos;s laptop with a tier-2 credential and then RDPing to a tier-1 file server exposes the credential at the laptop&apos;s LSASS). The v2 paper integrated the technical D5 controls (RunAsPPL, Restricted Admin, KB2871997) precisely because v1 alone could not move the needle on real estates.&lt;/p&gt;
&lt;h3&gt;6.4 KB2871997 and the WDigest opt-out&lt;/h3&gt;
&lt;p&gt;The May 13, 2014 update KB2871997 is the single most operationally impactful credential-protection control of the entire window [@kb2871997]. It carried three deliverables. First, the Restricted Admin client back-port to Windows 7 / Server 2008 R2 / Windows 8 / Server 2012, which Section 6.1 covers. Second, the &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential = 0&lt;/code&gt; registry default that disabled WDigest plaintext credential storage in LSASS memory on a freshly patched system. Third, the &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\Lsa\TokenLeakDetectDelaySecs&lt;/code&gt; (default 30 seconds) cleanup of leaked logon-session credentials.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The WDigest opt-out (&lt;code&gt;UseLogonCredential = 0&lt;/code&gt;) has zero operational downside on any post-2010 estate -- HTTP Digest authentication is essentially extinct in the enterprise -- and removes the most-cited credential-recovery primitive Mimikatz used through 2014 [@kb2871997]. It ships with the same back-port that brings Restricted Admin to down-level Windows. There is no defensible argument for not applying it on any supported Windows from 2014 onward.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The WDigest opt-out was buried in the KB2871997 bulletin because the headline framing was Restricted Admin RDP; many 2014-era administrators applied the patch for the RDP fix without realising the WDigest default had also changed [@kb2871997].&lt;/p&gt;
&lt;h3&gt;6.5 The seeds of Credential Guard&lt;/h3&gt;
&lt;p&gt;By late 2014 Microsoft was already prototyping the Hyper-V-as-security-boundary architecture that becomes Virtualisation-Based Security, &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;, and Hypervisor-protected Code Integrity in Windows 10 1507 on July 29, 2015 [@ms-credential-guard]. For the Part 3 reader, the key observation is that Microsoft had already concluded by mid-2014 that no amount of in-VTL0 hardening could close the credential-replay gap structurally, and that the architectural answer required moving the credential cache to a different privilege domain than the kernel attackers compromise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Restricted Admin reduced disclosure but not replay. RunAsPPL stopped a Mimikatz invocation only until BYOVD. The Pass-the-Hash tiering model named the problem but had no enforcement primitive inside the operating system. Microsoft&apos;s counter-pivot in the Part 3 window was correct in direction and &lt;em&gt;insufficient by construction&lt;/em&gt; -- because the architecture was the problem, not the engineering.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Microsoft shipped the right primitives. None of them was sufficient by construction, because the architecture was the problem. To see why, we have to look at the one structural thing the window left open: the SChannel attack surface, and the impossibility argument behind it.&lt;/p&gt;
&lt;h2&gt;7. The SChannel Coda: WinShock (MS14-066, November 11, 2014)&lt;/h2&gt;
&lt;p&gt;The window closes on November 11, 2014 with the last great pre-cloud TLS-stack remote code execution in Windows. WinShock is a counterpoint that reinforces the article&apos;s thesis rather than contradicting it: even with every credential-layer control of 2013-2014 deployed, an unrelated per-binary defect in the Schannel TLS stack could still hand an attacker remote code execution before any application code ran. The credential-layer hardening Microsoft spent the year shipping could not have prevented this bug, and the bug&apos;s existence is part of the evidence that hardening one layer leaves orthogonal layers exposed.&lt;/p&gt;
&lt;p&gt;A note up front, because the popular framing got this wrong. The bulletin itself was &lt;em&gt;not&lt;/em&gt; silent. MS14-066 was published on the November 11, 2014 Patch Tuesday with a Critical severity rating, an explicit CVE assignment (CVE-2014-6321), contemporary Brian Krebs coverage [@krebs-ms14-066], and public proof-of-concept walkthroughs within months [@nvd-cve-2014-6321]. The &quot;silent&quot; framing applies only to the additional Schannel hardening fixes Microsoft bundled into the same update without separate disclosures.&lt;/p&gt;
&lt;h3&gt;7.1 The mechanism&lt;/h3&gt;
&lt;p&gt;A crafted TLS handshake triggered a memory-corruption path inside &lt;code&gt;schannel.dll&lt;/code&gt;, the Windows Secure Channel security package that implements TLS for every in-box TLS consumer [@ms-bulletin-ms14-066; @nvd-cve-2014-6321]. The bug allowed remote code execution before any application code ran -- the handshake itself was the attack. The NVD entry catalogues the affected platforms as Windows Server 2003 SP2, Windows Vista SP2, Windows Server 2008 SP2 and R2 SP1, Windows 7 SP1, Windows 8, Windows 8.1, Windows Server 2012 Gold and R2, and Windows RT Gold and 8.1 -- essentially every supported Windows of the era [@nvd-cve-2014-6321].&lt;/p&gt;
&lt;p&gt;The attack surface was universal across the Windows enterprise estate of late 2014. Every IIS host terminating HTTPS, every SMB-over-HTTPS endpoint, every RDP-over-TLS listener, every Exchange ActiveSync endpoint, every Active Directory Federation Services endpoint terminating TLS in Schannel was exposed. A defensible writer-side abstraction (which this article takes) is that a crafted handshake triggered a memory-corruption path; the precise internal type and function family Microsoft fixed are not safely attributable without a primary-source walkthrough beyond the bulletin&apos;s published abstract.&lt;/p&gt;
&lt;h3&gt;7.2 The bundled extras&lt;/h3&gt;
&lt;p&gt;Microsoft bundled additional Schannel hardening into MS14-066 without separate bulletins. The article does not name specific CVE IDs for those bundled extras because prior pipeline runs found such attributions factually wrong (those CVE IDs belong to other bulletins or are REJECTED in NVD). The defensible framing is that Microsoft bundled additional Schannel hardening into the same update without separate bulletins, anchored to contemporary coverage of the patch cycle [@krebs-ms14-066]. The substantive point survives without speculative CVE attribution.&lt;/p&gt;
&lt;p&gt;The &quot;no public exploitation&quot; framing of MS14-066 is wrong. BeyondTrust&apos;s &quot;Triggering MS14-066&quot; blog post and the SecuritySift &quot;Exploiting MS14-066 (CVE-2014-6321) aka &apos;Winshock&apos;&quot; walkthrough are both referenced from the NVD entry as Exploit Third Party Advisory [@nvd-cve-2014-6321]. The CVE was patched, and the exploitation tradecraft was public; only the bundled hardening extras went unannotated.&lt;/p&gt;
&lt;h3&gt;7.3 Strategic significance&lt;/h3&gt;
&lt;p&gt;WinShock is the bookend on an era when the Windows Schannel stack was the front door of every enterprise. After 2014, TLS termination for major Windows estates increasingly happened at Azure Front Door, Akamai, Cloudflare, or AWS Application Load Balancer rather than at the Windows Schannel layer. Microsoft&apos;s own first-party services -- Exchange Online, SharePoint Online, the Office 365 ingress fleet -- terminated TLS at Azure-managed edge appliances, the topology documented in Microsoft&apos;s &lt;em&gt;Microsoft 365 network connectivity principles&lt;/em&gt; as the recommended &quot;connect locally to the Microsoft global network&quot; architecture in which the customer&apos;s traffic enters Microsoft&apos;s network as close to the user as possible and TLS is terminated at the nearest edge node [@ms-365-network-principles]. The architectural lesson is not that Schannel was uniquely fragile; it is that monolithic TLS stacks across hundreds of in-box consumers were a brittle design that the industry stopped accepting as the default deployment topology for enterprise services.&lt;/p&gt;
&lt;p&gt;WinShock closed the window with a per-binary patch. But the bigger story -- the credential layer Microsoft had spent the year trying to close -- was structurally broken in a way no patch could fix. To see why, we have to make the impossibility argument formally.&lt;/p&gt;
&lt;h2&gt;8. Theoretical Limits: Why No Per-Binary Hardening Could Fix the Credential Layer&lt;/h2&gt;
&lt;p&gt;A reframe. Every section so far has narrated &lt;em&gt;evidence&lt;/em&gt;. This section turns that evidence into an argument from architecture -- a structural reason the per-binary playbook &lt;em&gt;could not have&lt;/em&gt; fixed the credential layer, regardless of how good Microsoft&apos;s engineering was.&lt;/p&gt;
&lt;h3&gt;8.1 The trusted-computing-base argument&lt;/h3&gt;
&lt;p&gt;Every authenticated Windows process must, at some point, hold a verifiable secret. As §4.1 established, the single sign-on contract forces LSASS to hold a recoverable secret in memory [@ms-credentials-processes]. As long as that secret lives in a memory space the OS can read, an attacker who reaches that memory space can read it too.&lt;/p&gt;
&lt;p&gt;AppLocker, ASLR, DEP, AppContainer, ELAM, and Secure Boot are all per-binary mitigations [@ms-applocker; @ms-elam; @ms-secure-boot]. They prevent the &lt;em&gt;wrong&lt;/em&gt; code from running. They do not prevent the &lt;em&gt;right&lt;/em&gt; code (an administrator-launched Mimikatz; a Microsoft-signed but vulnerable third-party kernel driver) from reading LSASS memory through documented Win32 APIs. The per-binary playbook is a code-execution control, not a memory-access control, and the credential-theft attack is not a code-execution attack.&lt;/p&gt;
&lt;h3&gt;8.2 The asymmetry&lt;/h3&gt;
&lt;p&gt;The defender must close 100% of the per-binary attack surface to prevent a single piece of attacker code from running. The attacker needs only one credential primitive to remain extractable to win. The two budgets are not comparable. The defender&apos;s job is exponentially harder by construction, and any single residual gap -- one unsigned plug-in, one cached WDigest plaintext, one stolen NT hash -- gives the attacker domain-wide replay. This is not a Microsoft engineering failure. It is an architectural inevitability of the in-VTL0 LSASS model.&lt;/p&gt;
&lt;h3&gt;8.3 The VTL0-symmetry argument&lt;/h3&gt;
&lt;p&gt;In any single-privilege-ring operating system, no protection mechanism implemented &lt;em&gt;inside&lt;/em&gt; that ring can structurally defend a memory region against an attacker who reaches that ring. This is the formal statement of the limit Microsoft hit in 2014.&lt;/p&gt;
&lt;p&gt;RunAsPPL is the strongest 2014-era expression of this bound. As §6.2 documented, a BYOVD-loaded kernel driver can clear the &lt;code&gt;Protection&lt;/code&gt; byte on the LSASS &lt;code&gt;EPROCESS&lt;/code&gt; and &lt;code&gt;OpenProcess(PROCESS_VM_READ)&lt;/code&gt; succeeds [@itm4n-lsa-protection; @ms-lsa-protection]; the protection is enforced by the same kernel the attacker is compromising; the kernel cannot enforce a protection against itself.&lt;/p&gt;
&lt;p&gt;The architectural way to state it: $\text{Protection}&lt;em&gt;{\text{in-ring}}(M) \lt \text{Adversary}&lt;/em&gt;{\text{in-ring}}(M)$ for any memory region $M$ in the same privilege ring as the adversary. The protection function and the adversary function operate on the same domain, and the adversary always wins by construction. The algebraic notation is informal; the formal capture is the Bell-LaPadula / Lampson confinement bound, which states that in a single-privilege-ring system an adversary who reaches that ring can read any memory the kernel can map [@wikipedia-bell-lapadula]. Closing the gap requires moving $M$ to a privilege domain $\text{D}&apos;$ such that the in-ring adversary cannot map $\text{D}&apos;$ at all.&lt;/p&gt;
&lt;p&gt;That is exactly what Virtualisation-Based Security does in Windows 10 1507 [@ms-credential-guard]. Hyper-V boots before the Windows kernel and creates two Virtual Trust Levels: VTL0 is the normal Windows kernel attackers compromise; VTL1 is Virtual Secure Mode, an isolated execution domain whose memory the VTL0 kernel cannot read because the hypervisor&apos;s Second-Level Address Translation tables deny the mapping. Credential Guard hosts an LSA Isolated trustlet (LSAISO) in VTL1 that holds the high-value credential material; the VTL0 LSASS process holds only obfuscated references that LSAISO can resolve. A Mimikatz invocation in VTL0 can still extract the references, but the references no longer dereference to a credential the VTL0 kernel can read.&lt;/p&gt;

As long as the kernel that protects LSASS executes in the same privilege ring as the kernel an attacker compromises, every protection inside that ring is bypassable. The credential cache must live in a different privilege domain than the kernel that the attacker can compromise.
&lt;h3&gt;8.4 The way out, foreshadowed&lt;/h3&gt;
&lt;p&gt;Hardware-rooted isolation of the credential cache is the only structural answer. Virtualisation-Based Security, Credential Guard, and the LSAISO trustlet in VTL1 -- the spine of &lt;a href=&quot;https://paragmali.com/blog/above-the-kernel-the-windows-security-wars-part-4-2015-2019/&quot; rel=&quot;noopener&quot;&gt;Part 4&lt;/a&gt; -- are the architectural answer to the architectural problem the Part 3 window proves cannot be closed inside VTL0 [@ms-credential-guard]. The article closes the Part 3 argument by naming the problem precisely so Part 4 can name the solution precisely.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Hardware-rooted isolation of the credential cache -- the LSAISO trustlet in a VTL1 the VTL0 kernel cannot read -- is the only structural answer. Part 4 ships it. Part 3 names &lt;em&gt;why&lt;/em&gt; it had to.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The architecture was the problem. What did practitioners do with this evidence at the end of 2014?&lt;/p&gt;
&lt;h2&gt;9. Open Problems at the End of 2014&lt;/h2&gt;
&lt;p&gt;Picture a Fortune-500 security operations centre on a Friday afternoon in early December 2014. The team has applied every Microsoft patch through MS14-066 [@ms-bulletin-ms14-066], deployed AppLocker on Enterprise SKUs [@ms-applocker], set &lt;code&gt;RunAsPPL = 1&lt;/code&gt; after a careful LSA plug-in audit [@ms-lsa-protection], applied KB2871997 to disable WDigest plaintext storage [@kb2871997], and read the Mitigating Pass-the-Hash v2 whitepaper cover to cover [@ms-pth-v2]. They run an internal red-team exercise the following Monday. Mimikatz still works. Why?&lt;/p&gt;
&lt;p&gt;The credential layer is still essentially open. WDigest plaintext storage is now opt-out by default on freshly patched hosts, which closes the single most embarrassing primitive Delpy&apos;s 2011 demonstration exposed [@kb2871997]. But the cached NT hashes that NTLM authentication needs, the Kerberos Ticket-Granting Tickets the SSO contract holds in the LSA ticket cache, and the krbtgt master signing key on any domain controller whose LSASS the attacker can &lt;code&gt;OpenProcess&lt;/code&gt; against all remain extractable [@mimikatz-github; @ms-credentials-processes]. RunAsPPL stops a Mimikatz invocation from user mode, but it does not stop Mimikatz from invoking its own &lt;code&gt;mimidrv.sys&lt;/code&gt; driver (or any other vulnerable signed third-party driver) to clear the protection byte from kernel mode and proceed [@itm4n-lsa-protection; @mimikatz-github]. The same &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; that worked in May 2011 still works in December 2014 on every estate that has not stripped its third-party drivers down to a zero-BYOVD baseline -- which is no real estate at all.&lt;/p&gt;
&lt;p&gt;One open problem the security community debated through 2014 deserves a sharper treatment because it surfaces the &lt;em&gt;structural&lt;/em&gt; limit of any in-LSASS hardening strategy: why does Microsoft not simply relocate or obfuscate the LSA secret structures whose offsets Mimikatz hard-codes? The Mimikatz codebase carries an explicit, per-Windows-build signature table in &lt;code&gt;mimikatz/modules/sekurlsa/kuhl_m_sekurlsa_utils.c&lt;/code&gt; that maps every supported Windows kernel / &lt;code&gt;lsasrv.dll&lt;/code&gt; / &lt;code&gt;livessp.dll&lt;/code&gt; / &lt;code&gt;wdigest.dll&lt;/code&gt; build to the byte offsets and signature byte sequences Mimikatz scans for at run time [@mimikatz-sekurlsa-source]. The maintenance cost on the offensive side is one row per shipped Windows build per quarter. The proposed defensive response -- shuffle the struct layouts each cumulative update, randomise the symbol offsets, swap the byte signatures -- fails as a defence for three independent reasons. First, cost asymmetry. Microsoft would commit the test, validation, and Windows Hardware Quality Labs re-certification cost of every layout shuffle across every supported Windows SKU, language pack, and architecture every quarter; Mimikatz&apos;s maintainers would commit one pull request and one signature-table row per build. Second, defender-side fragility. The same LSASS structures the offsets index are consumed by Microsoft&apos;s own security tooling, by every third-party Endpoint Detection and Response agent, and by Windows Error Reporting; randomising the layout breaks the defender&apos;s own dependencies first and the attacker&apos;s last. Third, adversary-side robustness. Mimikatz already supports pattern-based signature scanning that finds the target structures even when their absolute offsets move; the offset hard-coding is a performance optimisation, not a requirement. The only structural defence is the one the engineering pipeline is already building: lift the credential cache out of the VTL0 user-mode process space entirely and into a Virtualisation-Based Security trustlet whose memory the VTL0 kernel cannot read. Alex Ionescu&apos;s Black Hat USA 2015 &quot;Battle of SKM and IUM&quot; talk lays out the VTL1 / IUM architecture in operator-facing detail and forward-references the Credential Guard design that ships in Windows 10 1507 [@ionescu-skm-ium-bhusa15]. The Part 3 community could see the answer; the architectural prerequisites simply had not yet shipped.&lt;/p&gt;
&lt;p&gt;Microsoft is prototyping Virtualisation-Based Security and Credential Guard, but the architectural answer ships outside this article&apos;s window [@ms-credential-guard]. Even after it ships, Credential Guard requires Windows 10 Enterprise, UEFI 2.3.1, Secure Boot, a 64-bit CPU with virtualisation extensions, and -- on most estates -- a hardware refresh cycle that costs years and millions. The deployment surface that needs the protection most cannot adopt it until well into 2017.&lt;/p&gt;
&lt;p&gt;AppLocker still carries its Windows 7 structural gaps in late 2014: the Application Identity service can be stopped by any process running as LocalSystem, after which enforcement degrades open until reboot, and the dual-DACL bypass class (rules that pass both Publisher and Path checks but reach a different binary at runtime) remains unaddressed [@ms-applocker; @ms-applocker-design]. Windows Defender Application Control -- the kernel-enforced policy successor that closes both gaps -- is still a Windows 10 enterprise feature in the Part 4 window. Secure Boot has its first &lt;code&gt;dbx&lt;/code&gt; revocation politics in this window: Microsoft&apos;s revocation list has to retire compromised UEFI bootloaders without bricking dual-boot Linux installations on the millions of OEM machines that ship with Secure Boot enabled, and the cadence and scope of &lt;code&gt;dbx&lt;/code&gt; updates becomes a recurring operational point of friction between Microsoft, OEMs, and the Linux distribution community [@ms-secure-boot; @mjg59-shim-signed]. The Pass-the-Hash v2 tiering recommendations are aspirational for the vast majority of 2014 deployments -- a complete tier 0 / tier 1 / tier 2 administrative-account programme is a multi-year project that requires Active Directory restructuring, change-management governance, and operator retraining at scale, and most estates that read the v2 paper applied KB2871997 and stopped there [@ms-pth-v2].&lt;/p&gt;
&lt;p&gt;Mimikatz&apos;s post-Part-3 modules (Skeleton Key and DCSync; see §11 FAQ) sit in the same codebase, are anchor events in the Part 4 window, and define the credential-replay horizon the Part 3 reader is staring at [@secureworks-skeleton-key; @metcalf-dcsync].&lt;/p&gt;
&lt;p&gt;The defining open question at the end of 2014 is how Microsoft isolates a long-lived user-mode process (LSASS) holding the most valuable secrets in the operating system from an administrator-privileged attacker on the same host, without breaking the hundreds of in-tree dependencies LSASS has accumulated since NT 3.1. The answer -- Virtualisation-Based Security plus the trustlet model -- is the spine of Part 4. It requires a hypervisor, a hardware-rooted boot chain, a re-architected LSA plug-in protocol that splits sensitive operations into LSAISO trustlet calls, and an operational deployment story that took Microsoft from late 2014 prototypes to general availability in 2015 and broad enterprise adoption only by 2018-2019.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; At the end of 2014, WDigest plaintext storage is closed by default. NT hashes, Kerberos TGTs, the krbtgt master key, and every other secret LSASS holds in recoverable form remain extractable by any administrator on the same host who can load a kernel driver. The architectural answer -- Credential Guard in Windows 10 1507 -- ships eight months later [@ms-credential-guard]. The Part 3 window proves the problem is real; Part 4 ships the answer.&lt;/p&gt;
&lt;/blockquote&gt;

Even at end-of-2014, with every Microsoft control available, the dominant Fortune-500 estate had applied the WDigest opt-out [@kb2871997] and almost nothing else. Tiering [@ms-pth-v2] is a multi-year programme. RunAsPPL [@ms-lsa-protection] requires an LSA plug-in audit that breaks any custom credential provider not yet re-signed at the PPL signer level. The architectural answer -- Credential Guard in 2015 [@ms-credential-guard] -- arrives to a deployment surface still struggling to deploy the 2013 controls. The gap between *the security primitive Microsoft shipped* and *the security primitive a Fortune-500 estate actually had running* was the largest it had ever been, and it grew through the Windows 10 1507 General Availability window.
&lt;p&gt;Eight open problems. None of them admits a Part 3-era technical solution. So how does a practitioner read the 2009-2014 primitives against a 2026 Windows 11 baseline?&lt;/p&gt;
&lt;h2&gt;10. Practical Guide: Reading the 2009-2014 Primitives Against a 2026 Windows 11 Baseline&lt;/h2&gt;
&lt;p&gt;The previous nine sections built the structural argument. This section answers the operator&apos;s question: which of these 2009-2014 primitives are still load-bearing in 2026, and which were superseded?&lt;/p&gt;
&lt;h3&gt;10.1 Which Part 3 primitives are still load-bearing in 2026&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Primitive (Part 3)&lt;/th&gt;
&lt;th&gt;Still in use 2026?&lt;/th&gt;
&lt;th&gt;Superseded by&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;AppLocker (Win 7+) [@ms-applocker]&lt;/td&gt;
&lt;td&gt;Yes, on Windows 10/11 Enterprise estates&lt;/td&gt;
&lt;td&gt;App Control for Business (WDAC) for new deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ELAM (Win 8+) [@ms-elam]&lt;/td&gt;
&lt;td&gt;Yes, load-bearing for the boot chain on every supported Windows&lt;/td&gt;
&lt;td&gt;Unchanged primitive; Defender&apos;s WdBoot.sys is the in-box ELAM driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UEFI Secure Boot (Win 8+) [@ms-secure-boot]&lt;/td&gt;
&lt;td&gt;Yes; mandatory for Windows 11 hardware certification&lt;/td&gt;
&lt;td&gt;Strengthened with mandatory dbx revocation enforcement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AppContainer (Win 8+) [@windows-internals-6e-p1]&lt;/td&gt;
&lt;td&gt;Yes; substrate for MSIX, Edge renderers, Win32 App Isolation, Recall trustlet&lt;/td&gt;
&lt;td&gt;Generalised across all packaged Win32 apps via App Isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LSA Protected Process (Win 8.1+) [@ms-lsa-protection]&lt;/td&gt;
&lt;td&gt;Yes; &lt;em&gt;on by default&lt;/em&gt; on &lt;strong&gt;new installations&lt;/strong&gt; of Windows 11 22H2 and later (upgraded systems retain default-off and require manual or GPO enablement)&lt;/td&gt;
&lt;td&gt;Complemented by Credential Guard on enterprise hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restricted Admin RDP (Win 8.1+) [@kb2871997]&lt;/td&gt;
&lt;td&gt;Yes; still recommended&lt;/td&gt;
&lt;td&gt;Remote Credential Guard (Win 10 1607+) for high-tier environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WDigest plaintext disablement (KB2871997) [@kb2871997]&lt;/td&gt;
&lt;td&gt;Default on every supported Windows since 2014&lt;/td&gt;
&lt;td&gt;Unchanged primitive; WDigest itself is essentially deprecated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mitigating Pass-the-Hash tiering model [@ms-pth-v2]&lt;/td&gt;
&lt;td&gt;Yes; lives on as Privileged Access Workstations and Enterprise Access Model&lt;/td&gt;
&lt;td&gt;&lt;em&gt;Securing Privileged Access&lt;/em&gt; online documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two surprises in the table. First, LSA Protected Process is &lt;em&gt;on by default&lt;/em&gt; on &lt;strong&gt;new installations&lt;/strong&gt; of Windows 11 22H2 and later -- which closes the gap for newly-shipped devices, though estates that upgraded from earlier Windows versions still require the manual or GPO enablement step that defined the 2014-2020 period. Second, AppLocker is still in production on enterprise estates ten-plus years after Windows 7 General Availability; the WDAC successor is the recommendation for new deployments, but the installed AppLocker base did not get replaced.&lt;/p&gt;
&lt;h3&gt;10.2 Mimikatz tradecraft as the floor of red-team capability&lt;/h3&gt;
&lt;p&gt;On any pre-Credential-Guard Windows estate -- and that is still a non-trivial fraction of the 2026 install base -- Mimikatz&apos;s 2011-2014 module set defines the floor of red-team capability. &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; reads every LSA-cached credential the operator&apos;s privileges allow [@mimikatz-github]. &lt;code&gt;sekurlsa::tickets /export&lt;/code&gt; extracts every Kerberos ticket from the LSA cache. &lt;code&gt;lsadump::secrets&lt;/code&gt; reads LSA private secrets. &lt;code&gt;lsadump::sam&lt;/code&gt; reads local SAM hashes. &lt;code&gt;kerberos::ptt&lt;/code&gt; re-imports tickets for replay. &lt;code&gt;kerberos::golden&lt;/code&gt; forges Golden Tickets given a stolen krbtgt hash [@metcalf-golden-ticket]. The Part 3 window&apos;s primitives are the foundation any practitioner reasoning about lateral movement in a Windows-AD estate uses every day, and the conceptual model Sean Metcalf documented on ADSecurity.org remains the canonical operator-grade reference.&lt;/p&gt;
&lt;h3&gt;10.3 Detection&lt;/h3&gt;
&lt;p&gt;Where to look. Sysmon ProcessAccess events on LSASS (event ID 10) with Granted Access masks of &lt;code&gt;0x1010&lt;/code&gt;, &lt;code&gt;0x1410&lt;/code&gt;, or &lt;code&gt;0x143A&lt;/code&gt; correspond to the read-and-decrypt access pattern Mimikatz&apos;s &lt;code&gt;sekurlsa::logonpasswords&lt;/code&gt; requires; the masks decompose into &lt;code&gt;PROCESS_VM_READ + PROCESS_QUERY_LIMITED_INFORMATION&lt;/code&gt; (0x1010), plus &lt;code&gt;PROCESS_VM_OPERATION&lt;/code&gt; (0x1410), plus &lt;code&gt;PROCESS_VM_WRITE + PROCESS_CREATE_THREAD&lt;/code&gt; (0x143A), and are widely-attested operator-grade detection lore catalogued across EDR vendor blogs and MITRE ATT&amp;amp;CK T1003.001 (OS Credential Dumping: LSASS Memory) sub-techniques [@mitre-t1003-001]. Windows Security event 4673 (sensitive privilege use) on &lt;code&gt;SeDebugPrivilege&lt;/code&gt; fires when a process adjusts its token to enable debug privileges -- the prerequisite for &lt;code&gt;privilege::debug&lt;/code&gt; -- which is interesting in itself when the actor is not a known debugger. System Access Control Lists on the krbtgt account, paired with Domain Controller audit subcategories for Kerberos AS-REQ and TGS-REQ, surface the AS-REQ-without-corresponding-logon anomalies that Golden Ticket use produces [@metcalf-golden-ticket]. Microsoft Defender for Identity raises Suspected Golden Ticket and Suspected Skeleton Key alerts on its analysis of domain-controller telemetry (the Skeleton Key alert is a Part 4 forward reference).&lt;/p&gt;
&lt;p&gt;{`
// Conceptual classifier for Sysmon event ID 10 (ProcessAccess) targeting LSASS.
// The canonical &quot;read-and-decrypt&quot; mask pattern Mimikatz needs to call
// OpenProcess + ReadProcessMemory + BCryptDecrypt against LSASS.
function isMimikatzLikely(event) {
  if (event.id !== 10) return false;
  if (!/lsass.exe$/i.test(event.targetImage)) return false;
  const interesting = new Set([&apos;0x1010&apos;, &apos;0x1410&apos;, &apos;0x143A&apos;]);
  return interesting.has(event.grantedAccess.toLowerCase().toUpperCase());
}&lt;/p&gt;
&lt;p&gt;const sample = {
  id: 10,
  targetImage: &apos;C:\\Windows\\System32\\lsass.exe&apos;,
  grantedAccess: &apos;0x1410&apos;,
  sourceImage: &apos;C:\\tools\\mimikatz.exe&apos;
};&lt;/p&gt;
&lt;p&gt;console.log(&apos;Alert?&apos;, isMimikatzLikely(sample));
console.log(&apos;SOCs combine this with allow-listed debugger paths and PPL state.&apos;);
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The same Restricted Admin flag that closes the disclosure-at-server gap [@kb2871997] also enables a Pass-the-Hash operator to invoke &lt;code&gt;sekurlsa::pth /run:&quot;mstsc /restrictedadmin&quot;&lt;/code&gt; from a compromised host and authenticate to the target RDP server using only the stolen NT hash [@mimikatz-github]. Restricted Admin is a &lt;em&gt;disclosure&lt;/em&gt; mitigation, not a &lt;em&gt;replay&lt;/em&gt; mitigation. Combine it with Remote Credential Guard (Windows 10 1607+) on tier 0 administrative paths.&lt;/p&gt;
&lt;/blockquote&gt;

1. Apply KB2871997 with `UseLogonCredential = 0` on every supported Windows. Zero downside.
2. Enable `RunAsPPL = 1` after a one-cycle LSA plug-in audit. Plan a rollback for any custom credential provider not yet re-signed at the PPL signer level [@ms-lsa-protection].
3. Adopt the Pass-the-Hash v2 tiering model as planning vocabulary, then operationalise it as Microsoft&apos;s *Securing Privileged Access* / Enterprise Access Model documentation. Multi-year programme; treat as a roadmap [@ms-pth-v2].
4. Use Restricted Admin for administrative RDP; promote to Remote Credential Guard on tier 0 paths.
5. Run AppLocker on every Enterprise SKU you have not yet migrated to WDAC [@ms-applocker]. Lock down `AppIDSvc` start-type to disabled-but-set-by-policy.
6. Enable Secure Boot, Measured Boot, and BitLocker (TPM + PIN) on every laptop [@ms-secure-boot]. Microsoft&apos;s default platform validation profile on native UEFI + Secure Boot systems is PCR 7 (Secure Boot State) and PCR 11 (BitLocker access control), which is the *correct* profile to use when Secure Boot is on and the platform&apos;s option ROMs are trusted [@ms-bitlocker-configure]. For hardened estates that want to detect tampering with the UEFI firmware itself, the option-ROM configuration, or the boot-manager binary independent of Secure Boot&apos;s signature check, expand the profile to PCRs 0, 2, 4, 7, 11 -- adding PCR 0 (UEFI firmware code), PCR 2 (option-ROM code), and PCR 4 (boot-manager binary measurements) on top of the default [@ms-bitlocker-countermeasures]. The hardened profile generates more BitLocker recovery-key prompts after legitimate firmware updates, so the operational cost is real and the choice between the two profiles is the standard balance between detection coverage and help-desk load.
7. Enable Credential Guard (Windows 10 1607+) on every estate whose hardware supports it [@ms-credential-guard]. This is the architectural answer; everything above is harm reduction.
&lt;p&gt;The 2009-2014 primitives are still here. So is Mimikatz. Part 4 explains why, and what Microsoft did about it.&lt;/p&gt;
&lt;h2&gt;11. Frequently asked questions&lt;/h2&gt;

No. The four zero-days -- MS10-046 (LNK shortcut RCE), MS10-061 (Print Spooler RCE), MS10-073 (win32k.sys keyboard-layout LPE), and MS10-092 (Task Scheduler LPE) -- were used across the worm&apos;s propagation and escalation surfaces, *not* chained in a single sequential exploit [@symantec-stuxnet-dossier-v14; @ms-bulletin-ms10-046; @ms-bulletin-ms10-061; @ms-bulletin-ms10-073; @ms-bulletin-ms10-092]. Different hosts encountered different combinations depending on patch level, USB usage, network shape, and whether the local user already had administrative privileges.

Only with two qualifiers -- multi-zero-day and kinetic-physical effect. Operation Aurora (January 12, 2010) used a single Internet Explorer 0-day (CVE-2010-0249) against Google and at least twenty other named victims including Adobe, Juniper, Yahoo, Symantec, Northrop Grumman, Dow Chemical, and Morgan Stanley (full sourcing and the verbatim Google wording in §3.6) [@google-aurora-wayback; @nvd-cve-2010-0249]; Stuxnet (June 17, 2010) used four zero-days for kinetic effect [@symantec-stuxnet-dossier-v14]. Drop either qualifier and Aurora falsifies the framing.

No. The Pass-the-Hash concept dates to Paul Ashton&apos;s 1997 NTBugtraq post [@wikipedia-pth] and was operationalised by Hernan Ochoa&apos;s 2008 Pass-the-Hash Toolkit (`iam.exe` / `whosthere.exe`) at Core Security Corelabs [@core-ptht-2008]. What Mimikatz did was make the primitive operational on a default-configured modern Windows host without requiring custom NTLM client code [@greenberg-mimikatz-wired; @mimikatz-github]. It turned a known protocol weakness into a one-line operator tool that ran against any LSASS the operator could `OpenProcess` against, and it added the Kerberos primitives (Pass-the-Ticket, Overpass-the-Hash, Golden Ticket) that previous Pass-the-Hash toolchains had not addressed. Skip Duckwall and Chris Campbell&apos;s *Pass-the-Hash 2: The Admin&apos;s Revenge* at Black Hat USA 2013 formalised the graph-walking discipline that ties Mimikatz primitives together into the lateral-movement operating model the rest of the decade inherits [@duckwall-campbell-bh2013].

Partially. The headline CVE (CVE-2014-6321) was patched on a published Patch Tuesday bulletin on November 11, 2014 [@ms-bulletin-ms14-066; @nvd-cve-2014-6321] with contemporary KrebsOnSecurity coverage [@krebs-ms14-066] and public proof-of-concept walkthroughs within months. The &quot;silent&quot; framing applies only to the additional Schannel hardening fixes Microsoft bundled into the same bulletin without separate disclosures. This article deliberately does not name specific CVE IDs for those bundled extras, because prior pipeline runs found such attributions factually wrong.

It wasn&apos;t, because Microsoft published v1 in December 2012 [@ms-pth-v1-landing] and v2 in July 2014 [@ms-pth-v2] and then migrated subsequent guidance into the post-2014 *Securing Privileged Access* online documentation rather than producing a numbered v3 PDF. Any &quot;v3 2017&quot; reference in secondary sources is incorrect; the canonical documentation chain after v2 is the *Securing Privileged Access* and *Enterprise Access Model* pages on Microsoft Learn.

No. The Symantec dossier was authored by Nicolas Falliere, Liam O Murchu, and Eric Chien of Symantec Security Response, v1.4, February 2011 [@symantec-stuxnet-dossier-v14]. Bruce Dang was at Microsoft&apos;s Security Response Center and co-presented &quot;Adventures in Analyzing Stuxnet&quot; with Peter Ferrie at the 27th Chaos Communication Congress (27C3) in Berlin on December 27, 2010 [@dang-ferrie-27c3], which is a separate primary covering the win32k.sys CVE-2010-2743 kernel exploit walkthrough (the 27C3-not-29C3 venue correction is documented in the §3.1 sidenote). Dang&apos;s affiliation is Microsoft MSRC, not Symantec.

No. Mimikatz&apos;s first public release was May 2011 (closed source) [@greenberg-mimikatz-wired; @wikipedia-mimikatz]. The GitHub repository `gentilkiwi/mimikatz` was created on April 6, 2014 at 18:30:02 UTC -- a timestamp anyone can verify via the GitHub API [@mimikatz-github]. Any &quot;2007&quot; date refers to Delpy&apos;s pre-release private experimentation, not a public release.

No. Both anchor events post-date the Part 3 window. Dell SecureWorks Counter Threat Unit disclosed the Skeleton Key malware family on January 12, 2015 [@secureworks-skeleton-key], and Delpy added the corresponding `misc::skeleton` module to Mimikatz on January 17, 2015. Skeleton Key, DCSync, and the Credential Guard architectural pivot are the spine of Part 4 [@metcalf-dcsync; @ms-credential-guard].
&lt;p&gt;Skeleton Key. Virtualisation-Based Security. Credential Guard. Part 4 opens on January 17, 2015, with the same Mimikatz codebase and a new technique.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;windows-security-wars-part-3-hardening-decade&quot; keyTerms={[
  { term: &quot;LSASS&quot;, definition: &quot;Local Security Authority Subsystem Service: the long-lived user-mode Windows process that caches NT hashes, Kerberos tickets, and (depending on loaded security packages) recoverable plaintext credentials for single sign-on.&quot; },
  { term: &quot;AppContainer&quot;, definition: &quot;A Windows access token with a per-package security identifier and capability-SID vector; resource access checks intersect the capability set with the resource ACL. The substrate for WinRT / Modern apps in Windows 8 and MSIX / Win32 App Isolation in modern Windows.&quot; },
  { term: &quot;Pass-the-Hash (PtH)&quot;, definition: &quot;Replay an NT hash as a bearer credential against any NTLM-accepting service, without ever knowing the user&apos;s plaintext password.&quot; },
  { term: &quot;Pass-the-Ticket (PtT)&quot;, definition: &quot;Extract a Kerberos Ticket-Granting Ticket or service ticket from LSASS and re-import it into another logon session for replay.&quot; },
  { term: &quot;Overpass-the-Hash&quot;, definition: &quot;Use a stolen NT hash to request a fresh Kerberos TGT from the KDC; the bridge from an NTLM-recovered hash to a Kerberos-issued ticket.&quot; },
  { term: &quot;Golden Ticket&quot;, definition: &quot;A forged Kerberos TGT signed with the stolen NT hash of the domain&apos;s krbtgt account; grants arbitrary user, group, and lifetime impersonation across the AD forest.&quot; },
  { term: &quot;Protected Process Light (PPL)&quot;, definition: &quot;A kernel-enforced signer level that prevents OpenProcess(PROCESS_VM_READ) and code injection against the protected process from lower-signer-level callers, regardless of token privileges.&quot; },
  { term: &quot;ELAM&quot;, definition: &quot;Early Launch Antimalware: the first boot-start driver, allowed to inspect and classify subsequent boot-start drivers via BDCB_CLASSIFICATION before they load.&quot; },
  { term: &quot;Secure Boot&quot;, definition: &quot;UEFI firmware verification of the signature of every UEFI driver, option ROM, and OS loader before transferring control, anchored by the Platform Key and signed Key Exchange Keys.&quot; },
  { term: &quot;VTL0 / VTL1&quot;, definition: &quot;Virtual Trust Levels introduced by Hyper-V in Windows 10 1507; VTL0 is the normal Windows kernel attackers compromise, VTL1 is Virtual Secure Mode where Credential Guard hosts the LSAISO trustlet that holds high-value credential material.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>mimikatz</category><category>stuxnet</category><category>pass-the-hash</category><category>credential-theft</category><category>applocker</category><category>secure-boot</category><category>lsass</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>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></channel></rss>