<?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: ntlm-relay</title><description>Posts tagged ntlm-relay.</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/ntlm-relay/rss.xml" rel="self" type="application/rss+xml"/><item><title>SYSTEM in Ten Seconds: How the Potato Family Survived Every Microsoft Mitigation</title><link>https://paragmali.com/blog/system-in-ten-seconds-how-the-potato-family-survived-every-m/</link><guid isPermaLink="true">https://paragmali.com/blog/system-in-ten-seconds-how-the-potato-family-survived-every-m/</guid><description>A decade of Windows local privilege escalation -- HotPotato through FakePotato -- rests on one architectural decision Microsoft has refused to revisit.</description><pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate><content:encoded>
The Potato family is a decade of Windows local privilege escalation, eleven named variants
disclosed between January 2016 (HotPotato) and August 2024 (FakePotato), all pivoting on the same
primitive: `SeImpersonatePrivilege` (introduced as a defined user right in the Windows 2000 SP4 /
XP SP2 / Server 2003 hardening cycle [@msrc-token-kidnapping; @ms-impersonate-policy]) plus `ImpersonateNamedPipeClient`
(a Win32 primitive documented as supported since Windows XP for clients and Windows Server 2003
for servers [@ms-impersonate-api]). Each variant -- HotPotato (January 2016), RottenPotato,
JuicyPotato, RoguePotato, PrintSpoofer, RemotePotato0, JuicyPotatoNG, GodPotato (the 2026
default), LocalPotato (CVE-2023-21746), SilverPotato, FakePotato (CVE-2024-38100) -- defeats a
specific Microsoft mitigation, but no mitigation closes the family. The structural reason is the
MSRC Windows Security Servicing Criteria, which treats the `SeImpersonatePrivilege`-to-SYSTEM
transition as a safety boundary, not a security boundary. The Potato class is therefore an
architectural decision, not a bug.
&lt;h2&gt;1. A Web Shell, Ten Seconds, SYSTEM&lt;/h2&gt;
&lt;p&gt;A red teamer drops a web shell on an Internet Information Services server running as &lt;code&gt;IIS APPPOOL\DefaultAppPool&lt;/code&gt;. Ten seconds later, the shell prints &lt;code&gt;nt authority\system&lt;/code&gt;. The operator did not exploit a memory-corruption bug, did not bypass a kernel security boundary, did not even use an undocumented API. They invoked &lt;code&gt;CoCreateInstance&lt;/code&gt; against a Distributed COM (DCOM) class identifier, waited for the SYSTEM-context RPCSS service to authenticate to a named pipe they owned, and called &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; [@ms-impersonate-api]. Every step was documented Win32 behaviour. The exploit is that Microsoft has spent a decade refusing to call any of those steps a security boundary [@msrc-servicing-criteria; @troopers24].&lt;/p&gt;
&lt;p&gt;The artefact in the operator&apos;s hand is one of several. In May 2026 it is most likely &lt;code&gt;GodPotato.exe -cmd &quot;cmd /c whoami&quot;&lt;/code&gt; -- a single Apache 2.0-licensed binary that BeichenDream published on GitHub on December 23, 2022 [@beichendream-god]. The README says it works on every supported Windows release from Windows 8 through Windows 11, and from Server 2012 through Server 2022 [@beichendream-god]. Community testing has since extended the working range to Server 2025 with default Distributed COM hardening enabled [@compass-three-headed].&lt;/p&gt;

A Windows user-rights assignment that lets a thread substitute another user&apos;s security context for its own (typically via `ImpersonateNamedPipeClient` or `ImpersonateLoggedOnUser`). Granted by default to `LOCAL SERVICE`, `NETWORK SERVICE`, every Internet Information Services application-pool identity, and most service accounts [@ms-impersonate-policy]. Introduced as a defined user right in the Windows 2000 SP4 / XP SP2 / Server 2003 service-hardening cycle that MSRC discusses in its 2009 Token Kidnapping retrospective [@msrc-token-kidnapping], after which possessing it has been one named-pipe round-trip away from being SYSTEM.
&lt;p&gt;The IIS context matters. The default application-pool identity holds &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; because IIS depends on it for legitimate request-scoped impersonation [@itm4n-printspoofer]. So does the default SQL Server service account, the Background Intelligent Transfer Service (BITS) account, the Spooler service account, and every account that hosts a Windows service that may need to &quot;act as&quot; a calling user. Anyone who can run code inside one of those accounts can run code as SYSTEM in seconds.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every step the operator takes -- &lt;code&gt;CoCreateInstance&lt;/code&gt;, the SYSTEM-context RPCSS authentication, &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;, the subsequent &lt;code&gt;CreateProcessWithToken&lt;/code&gt; -- is in Microsoft&apos;s published Win32 contract [@ms-impersonate-api; @ms-dcom-spec]. None of them is a memory-corruption bug. The &quot;exploit&quot; is the existence of a documented call sequence that turns a service account into SYSTEM, on a fully-patched Windows 11 box, in 2026.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the puzzle the rest of the article is here to solve. The technique has been a one-binary operation for nearly a decade [@troopers24]. Microsoft has shipped three named hardening waves against it (a 2019-2020 OXID-resolver fix [@forshaw-pz-2021]; the three-phase CVE-2021-26414 Distributed COM hardening rollout from June 2021 to March 2023 [@ms-kb5004442]; and per-variant CVE patches in 2023 and 2024 [@nvd-cve-2023-21746; @nvd-cve-2024-38100]). None of those waves closed the family. Why?&lt;/p&gt;
&lt;h2&gt;2. The Architectural Primitive&lt;/h2&gt;
&lt;p&gt;The answer is in a Microsoft document called the &lt;a href=&quot;https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/&quot; rel=&quot;noopener&quot;&gt;Windows Security Servicing Criteria&lt;/a&gt; [@msrc-servicing-criteria]. It defines what Microsoft will and will not service as a security vulnerability. Quoting the document directly: &quot;A security boundary provides a logical separation between the code and data of security domains with different levels of trust&quot; [@msrc-servicing-criteria]. The page then lists the boundaries Microsoft has defined for Windows -- kernel mode versus user mode, virtual machine versus host, session versus session, and so on. The list is the &lt;em&gt;enumeration&lt;/em&gt; that decides which bug classes get CVEs and which do not.&lt;/p&gt;
&lt;p&gt;The Potato family pivots on a transition that is conspicuously &lt;em&gt;not&lt;/em&gt; on the list: a service account that holds &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; becoming SYSTEM. As Andrea Pierini and Antonio Cocomazzi articulated in the Troopers 24 retrospective, Microsoft&apos;s published position is that the Windows Service Hardening boundary is a &lt;em&gt;safety&lt;/em&gt; boundary rather than a &lt;em&gt;security&lt;/em&gt; boundary, which is why so many Potato exploits continue to work on fully updated Windows systems [@troopers24]. WSH is Microsoft&apos;s own shorthand for &lt;strong&gt;Windows Service Hardening&lt;/strong&gt; -- the family of post-XP-SP2 protections that isolate service accounts from one another. The position is consistent with everything Microsoft has shipped: per-variant patches when a specific vehicle becomes too embarrassing, and silence on the underlying primitive. (The verbatim Troopers 24 articulation appears in §13.)&lt;/p&gt;

The boundary *definition* on `microsoft.com/en-us/msrc/windows-security-servicing-criteria` is rendered in static HTML and can be fetched directly [@msrc-servicing-criteria]. The boundary *enumeration table* immediately below it, which lists the bug classes that do and do not get CVEs, is JavaScript-rendered and does not appear in static fetches. The community-canonical secondary source for what is on that list is the Troopers 24 talk by Pierini and Cocomazzi [@troopers24], cross-referenced against James Forshaw&apos;s Project Zero retrospective from October 2021 [@forshaw-pz-2021] and Mark Russinovich&apos;s `aka.ms/win-security-boundaries` paraphrase. This article cites the primary for the definition and the Troopers retrospective for the enumeration.
&lt;p&gt;Three primitives, taken together, mechanically determine the entire family. Once they are stated, the only remaining question is which SYSTEM-context service is cheapest to coerce.&lt;/p&gt;
&lt;h3&gt;Primitive one: SeImpersonatePrivilege&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is a Windows user-rights assignment that permits a thread to call &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;, &lt;code&gt;ImpersonateLoggedOnUser&lt;/code&gt;, and the related impersonation APIs [@ms-impersonate-policy]. By Windows default, it is granted to &lt;code&gt;LOCAL SERVICE&lt;/code&gt;, &lt;code&gt;NETWORK SERVICE&lt;/code&gt;, every Internet Information Services application-pool identity, and most service accounts that need to act on behalf of clients [@itm4n-printspoofer]. (For when the right was introduced and a working definition, see §1; Decoder&apos;s one-sentence summary of what the grant means in practice is the climactic PullQuote in §6.3.)&lt;/p&gt;
&lt;h3&gt;Primitive two: ImpersonateNamedPipeClient&lt;/h3&gt;

A Win32 API that lets the server end of a named pipe adopt the security context of whoever just connected to that pipe. After the call, the calling thread holds an impersonation token for the client identity, and any subsequent system call (including `CreateProcessWithToken`) executes as that identity. The function has been part of `namedpipeapi.h` since Windows XP for clients and Windows Server 2003 for servers, with no deprecation notice as of the 2025-07-01 documentation revision [@ms-impersonate-api].
&lt;p&gt;The mechanism is exactly the one a SYSTEM-context service uses for legitimate request-scoped impersonation. The Potato class subverts it by getting a SYSTEM-context service to connect to a pipe the attacker owns. No memory corruption, no kernel exploit, no undocumented API. The Win32 reference describes the call as the standard way for a pipe server to &quot;impersonate the client end&quot; [@ms-impersonate-api].&lt;/p&gt;
&lt;h3&gt;Primitive three: the MSRC servicing-criteria carve-out&lt;/h3&gt;
&lt;p&gt;The third primitive is policy, not code. The MSRC document distinguishes a &lt;em&gt;security boundary&lt;/em&gt; (whose violation gets a CVE and a security update) from a &lt;em&gt;safety boundary&lt;/em&gt; (where Microsoft will patch when convenient but does not commit to a service-level objective). The defensible reading, articulated explicitly by Pierini and Cocomazzi at Troopers 24, is that the SYSTEM-from-&lt;code&gt;SeImpersonate&lt;/code&gt; transition lives on the safety side [@troopers24]. The implication is structural: a service account holding &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; &quot;is already privileged&quot; in Microsoft&apos;s policy view. Promoting it to SYSTEM is therefore not a privilege escalation that requires a security update.&lt;/p&gt;

flowchart LR
    A[Service account with SeImpersonatePrivilege] --&amp;gt; B[Coerce SYSTEM-context service to connect to attacker-owned named pipe]
    B --&amp;gt; C[Call ImpersonateNamedPipeClient on server thread]
    C --&amp;gt; D[Thread now holds SYSTEM impersonation token]
    D --&amp;gt; E[CreateProcessWithToken spawns SYSTEM process]
    F[MSRC servicing criteria carve-out] -.-&amp;gt;|&quot;Allows step A to remain a default grant&quot;| A
    F -.-&amp;gt;|&quot;Allows step C to remain a documented Win32 API&quot;| C
&lt;p&gt;Taken together, the three primitives reduce the entire Potato family to a single problem statement: &lt;em&gt;find the cheapest SYSTEM-context service to coerce into a callback&lt;/em&gt;. Every named variant since 2016 is an answer to that problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Microsoft does not consider the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;-to-SYSTEM transition a security boundary; it considers it a safety boundary. The Potato family is the consequence. Variants change vehicles -- NetBIOS spoofing, BITS DCOM, Print Spooler RPC, EFS RPC, RPCSS OXID, ShellWindows -- but every one of them lives on the same architectural carve-out [@troopers24; @msrc-servicing-criteria].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The phrase &lt;code&gt;aka.ms/win-security-boundaries&lt;/code&gt; was popularised by Mark Russinovich&apos;s Channel 9 talks of the late 2010s. Channel 9 was retired on December 1, 2021, so the link is now mostly cited as a memorable handle for the boundary list rather than as a clickable URL. The live equivalent is the MSRC servicing criteria document itself [@msrc-servicing-criteria].&lt;/p&gt;
&lt;p&gt;Given primitives this old and this widely default-granted -- both the named-pipe impersonation API and the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; user right have been in their current form since the Windows 2000 SP4 / Server 2003 / XP SP2 service-hardening cycle [@msrc-token-kidnapping; @ms-impersonate-policy; @ms-impersonate-api] -- the natural question is why the named Potato family did not appear until 2016. The next section is the answer.&lt;/p&gt;
&lt;h2&gt;3. The Long Pre-Potato Era, 2001-2015&lt;/h2&gt;
&lt;p&gt;In March 2008, Cesar Cerrudo stood on a stage in Dubai at Hack-in-the-Box and demonstrated that a SYSTEM-context Windows service holding &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; was, in effect, one named-pipe call away from SYSTEM [@cerrudo-hitb-slides; @msrc-token-kidnapping]. Microsoft acknowledged the technique on the MSRC blog on April 14, 2009, and shipped MS09-012 -- the patch Cerrudo later nicknamed &quot;Chimichurri&quot; in his Black Hat USA 2010 follow-up [@msrc-token-kidnapping; @blackhat-2010-cerrudo]. Cerrudo extended the work two years later at Black Hat USA 2010 in a paper titled &quot;Token Kidnapping&apos;s Revenge&quot; [@blackhat-2010-cerrudo]. Microsoft patched the specific NetworkService-to-SYSTEM vehicle. They did not revoke the privilege from the service accounts that held it [@msrc-token-kidnapping].&lt;/p&gt;
&lt;p&gt;That pattern -- patch the vehicle, leave the primitive -- is the family&apos;s bequest from Cerrudo.&lt;/p&gt;

NTLM **relay** forwards an NTLM authentication captured from victim A to a different server B, where the attacker authenticates as A. NTLM **reflection** is the special case where B is the same machine (often the same protocol) as A. Microsoft fixed the most obvious same-protocol case with MS08-068 in 2008 [@ms-ms08-068]. Cross-protocol reflection (HTTP-to-SMB, DCOM-to-RPC) was not closed by that patch and became the doorway through which the Potato family entered.
&lt;p&gt;Seven years before Cerrudo, on March 31, 2001, Sir Dystic of the Cult of the Dead Cow stood on a different stage at @lanta.con in Atlanta and released SMBRelay, the first public same-protocol &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM relay&lt;/a&gt; tool [@cultdeadcow-smbrelay]. Microsoft eventually responded with MS08-068, a &lt;em&gt;same-protocol-only&lt;/em&gt; fix [@ms-ms08-068]. Cross-protocol relay -- HTTP to SMB, DCOM to local RPC -- remained open.&lt;/p&gt;
&lt;p&gt;That opening was the canvas James Forshaw painted on. In December 2014, then at Google Project Zero, Forshaw filed Issue 222 (&quot;Windows: Local WebDAV NTLM Reflection EoP&quot;) demonstrating that the WebClient service performs NTLM authentication when asked to open a WebDAV URL, and that the resulting NTLM session can be reflected cross-protocol to the local SMB service [@forshaw-pz-2021]. A few months later Forshaw filed Issue 325, showing that &lt;code&gt;CoGetInstanceFromIStorage&lt;/code&gt; could coerce a DCOM activation into authenticating to an attacker-controlled TCP endpoint. Microsoft patched the 2015 issue as CVE-2015-2370 [@nvd-cve-2015-2370]. In his October 2021 retrospective Forshaw wrote, with the laconic precision of a researcher whose contributions are still being weaponised seven years later:&lt;/p&gt;

The technique to locally relay authentication for DCOM was something I originally reported back in 2015 (issue 325). This issue was fixed as CVE-2015-2370, however the underlying authentication relay using DCOM remained. This was repurposed and expanded upon by various others for local and remote privilege escalation in the RottenPotato series of exploits. -- James Forshaw, Project Zero, October 2021 [@forshaw-pz-2021]
&lt;p&gt;Cerrudo nicknamed the MS09-012 patch &quot;Chimichurri&quot; after the Argentine green sauce, and used the name when he reprised the work at Black Hat USA 2010 [@blackhat-2010-cerrudo]. Cerrudo was at Argeniss and later IOActive when he developed the technique [@msrc-token-kidnapping; @blackhat-2010-cerrudo].&lt;/p&gt;
&lt;p&gt;The primary artefact for Cerrudo&apos;s March 2008 Hack-in-the-Box Dubai talk (slides, video, abstract) is no longer reachable on the conference site; the MSRC blog&apos;s retrospective is the canonical secondary that anchors the date and venue [@msrc-token-kidnapping]. The Black Hat USA 2010 &quot;Token Kidnapping&apos;s Revenge&quot; whitepaper [@blackhat-2010-cerrudo] is the durable primary for the underlying technique.&lt;/p&gt;

gantt
    title Pre-Potato lineage 2001-2015
    dateFormat YYYY-MM
    section NTLM relay
    SMBRelay (Sir Dystic) :a1, 2001-03, 1M
    MS08-068 same-protocol fix :a2, 2008-10, 1M
    section Token escalation
    Token Kidnapping HITB Dubai (Cerrudo) :b1, 2008-03, 1M
    MS09-012 Chimichurri :b2, 2009-04, 1M
    Token Kidnapping&apos;s Revenge (Cerrudo) :b3, 2010-07, 1M
    section DCOM primitive
    Project Zero Issue 222 (Forshaw) :c1, 2014-12, 1M
    Project Zero Issue 325 (Forshaw) :c2, 2015-04, 1M
    CVE-2015-2370 patch :c3, 2015-07, 1M
&lt;p&gt;By the end of 2015 the three pieces were on the table. A long-standing default privilege grant (Cerrudo&apos;s &quot;SeImpersonate equals SYSTEM&quot; thesis). A specific cross-protocol reflection technique (Forshaw&apos;s WebDAV-to-SMB Issue 222). A specific DCOM-activation coercion primitive (Forshaw&apos;s &lt;code&gt;CoGetInstanceFromIStorage&lt;/code&gt; Issue 325). Microsoft had patched the literal bug in the third piece and explicitly declined to revoke the privilege in the first. The technique was published, the proof-of-concept code was on GitHub, and the family was a binary release away. The next chapter is the moment someone shipped the binary.&lt;/p&gt;
&lt;h2&gt;4. HotPotato, January 16, 2016&lt;/h2&gt;
&lt;p&gt;On January 16, 2016, Stephen Breen of Foxglove Security published a blog post titled &quot;Hot Potato&quot; [@foxglove-hotpotato]. He had just spoken at ShmooCon. The repository, &lt;code&gt;foxglovesec/Potato&lt;/code&gt;, would land on GitHub three weeks later, on February 9, 2016 [@foxglove-potato-repo]. The post&apos;s opening sentence is the family&apos;s birth certificate:&lt;/p&gt;

Hot Potato (aka: Potato) takes advantage of known issues in Windows to gain local privilege escalation in default configurations, namely NTLM relay (specifically HTTP-&amp;gt;SMB relay) and NBNS spoofing. -- Stephen Breen, Foxglove Security, January 16, 2016 [@foxglove-hotpotato]
&lt;p&gt;Breen had not invented NTLM reflection. He had combined three existing primitives into a single-binary, one-click privilege escalation that worked on every default Windows install from Windows 7 through Server 2012 [@foxglove-hotpotato]. The Foxglove post acknowledges the lineage explicitly: &quot;a similar technique was disclosed by the guys at Google Project Zero ... In fact, some of our code was shamelessly borrowed from their PoC&quot; [@foxglove-hotpotato].&lt;/p&gt;
&lt;h3&gt;How HotPotato works&lt;/h3&gt;
&lt;p&gt;The exploit chains three independent tricks. Step one is UDP-port exhaustion. The tool opens enough UDP sockets that the local NetBIOS Name Service (NBNS) name lookups fail, forcing Windows to fall back to broadcast-based name resolution [@foxglove-hotpotato]. Step two is NBNS spoofing of the WPAD hostname, pointed at &lt;code&gt;127.0.0.1&lt;/code&gt;. Step three is the actual reflection: when Windows Update or Windows Defender polls for an update, it consults the WPAD URL, gets the attacker&apos;s proxy auto-configuration script, and routes its HTTP requests through the attacker&apos;s local listener -- which then relays the SYSTEM-context NTLM negotiation to the local SMB service [@foxglove-hotpotato].&lt;/p&gt;

sequenceDiagram
    participant Atk as Hot Potato tool
    participant NBNS as NetBIOS Name Service
    participant WU as Windows Update (SYSTEM)
    participant WPAD as WPAD HTTP listener (attacker)
    participant SMB as Local SMB service
    Atk-&amp;gt;&amp;gt;NBNS: UDP-flood to exhaust ports and force broadcast
    Atk-&amp;gt;&amp;gt;NBNS: Spoof WPAD hostname pointing at 127.0.0.1
    WU-&amp;gt;&amp;gt;WPAD: GET wpad.dat over HTTP
    WPAD--&amp;gt;&amp;gt;WU: Attacker-supplied proxy auto-config
    WU-&amp;gt;&amp;gt;WPAD: HTTP request with SYSTEM-context NTLM negotiate
    WPAD-&amp;gt;&amp;gt;SMB: Reflect the NTLM exchange to local SMB
    SMB--&amp;gt;&amp;gt;Atk: SMB session authenticated as SYSTEM
    Atk-&amp;gt;&amp;gt;Atk: ImpersonateNamedPipeClient and spawn SYSTEM shell
&lt;p&gt;The result was a single binary that produced a SYSTEM shell from any local user account on the target host -- because on a default Windows install every authenticated local user can run code, open UDP sockets, and bind a loopback HTTP listener, which is all HotPotato needs to bootstrap.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; HotPotato does not use Distributed COM activation at all. It uses NetBIOS spoofing, WPAD hijacking, and HTTP-to-SMB cross-protocol relay. The family is named for HotPotato but the &lt;em&gt;defining&lt;/em&gt; primitive of every later variant -- DCOM activation -- is absent. HotPotato is in the family because it pivots through the same &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; plus named-pipe-impersonation core, which is the actual definition of the family. The repository name &lt;code&gt;Potato&lt;/code&gt; and the family naming convention are both Breen&apos;s [@foxglove-potato-repo].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The naming pattern that has now produced eleven variants started with the GitHub repository name &lt;code&gt;foxglovesec/Potato&lt;/code&gt; [@foxglove-potato-repo]. Breen later wrote that &quot;Hot&quot; was a riff on the fact that the SYSTEM token was passed around like a hot potato; the suffix convention spread from there organically.&lt;/p&gt;
&lt;h3&gt;Why HotPotato did not last&lt;/h3&gt;
&lt;p&gt;HotPotato had three structural weaknesses. NetBIOS spoofing is unreliable: the UDP-port exhaustion can fail under load, group policy can pin a real WPAD URL, and a legitimate WPAD response can win the race. NetBIOS is disabled in security-hardened environments as a matter of routine. And the HTTP-to-SMB cross-protocol path was the very thing Extended Protection for Authentication and SMB channel-binding tokens were designed to close [@crowdstrike-drop-mic]. On a Windows 10 1607 host with EPA on the SMB server, HotPotato failed.&lt;/p&gt;
&lt;p&gt;Researchers needed a coercion vehicle that was deterministic, did not rely on broadcast spoofing, and used a protocol Microsoft had not yet hardened end-to-end. Forshaw&apos;s Project Zero Issue 325 -- the &lt;code&gt;CoGetInstanceFromIStorage&lt;/code&gt; DCOM trigger -- met all three criteria [@forshaw-pz-2021]. The next variant weaponised it.&lt;/p&gt;
&lt;h2&gt;5. The DCOM-Activation Breakthrough, 2016-2018&lt;/h2&gt;
&lt;h3&gt;5.1 RottenPotato (DerbyCon 6, September 2016)&lt;/h3&gt;
&lt;p&gt;Eight months after HotPotato, Stephen Breen returned with a co-author and a new vehicle. The talk was on September 23, 2016 -- the Friday of DerbyCon 6 -- and the blog post followed three days later [@foxglove-rottenpotato]. The Foxglove post identifies the co-author by name: &quot;myself and my partner in crime, Chris Mallz (@vvalien1) spoke at DerbyCon about a project we&apos;ve been working on for the last few months&quot; [@foxglove-rottenpotato].&lt;/p&gt;
&lt;p&gt;Many secondary sources credit Andrea Pierini (Decoder) as the RottenPotato co-author. The Foxglove primary disproves this verbatim [@foxglove-rottenpotato]. Decoder enters the family lineage two years later, with JuicyPotato in 2018 [@ohpe-juicy]. Chris Mallz is the actual RottenPotato co-author.&lt;/p&gt;
&lt;p&gt;RottenPotato replaced HotPotato&apos;s NetBIOS-and-WPAD chain with Forshaw&apos;s DCOM-activation primitive. The hard-coded target was the Background Intelligent Transfer Service (BITS) Distributed COM server, class identifier &lt;code&gt;{4991d34b-80a1-4291-83b6-3328366b9097}&lt;/code&gt;, and the hard-coded listener port was &lt;code&gt;127.0.0.1:6666&lt;/code&gt; [@foxglove-rottenpotato; @foxglove-rotten-repo].&lt;/p&gt;

A Win32 OLE function that instantiates a Distributed COM object using a marshalled `IStorage` interface pointer as the activation source. By marshalling an `IStorage` whose object exporter identifier (OXID) resolves to an attacker-controlled TCP endpoint, the activator can redirect the resulting authentication callback to a listener it owns. Forshaw filed this as Project Zero Issue 325 in 2015 [@forshaw-pz-2021]; RottenPotato weaponised it.

sequenceDiagram
    participant Atk as RottenPotato (service account)
    participant Pipe as Local listener on 127.0.0.1:6666
    participant DCOM as DCOM activation (RPCSS)
    participant BITS as BITS COM server (SYSTEM)
    participant RPC as Local RPC on port 135
    Atk-&amp;gt;&amp;gt;Pipe: Start TCP listener on 127.0.0.1:6666
    Atk-&amp;gt;&amp;gt;DCOM: CoGetInstanceFromIStorage with BITS CLSID and marshalled IStorage
    DCOM-&amp;gt;&amp;gt;BITS: Spawn BITS under SYSTEM context
    BITS-&amp;gt;&amp;gt;Pipe: Callback to the marshalled endpoint
    Pipe-&amp;gt;&amp;gt;RPC: Forward COM packets to local RPC on port 135
    RPC--&amp;gt;&amp;gt;Pipe: Reply containing SYSTEM-context NTLM exchange
    Pipe--&amp;gt;&amp;gt;Atk: SYSTEM authentication captured
    Atk-&amp;gt;&amp;gt;Atk: ImpersonateNamedPipeClient and CreateProcessWithToken
&lt;p&gt;The technique was 100% reliable on Windows 7 through Windows 10 1803 and Server 2008 R2 through Server 2016 [@foxglove-rottenpotato]. There was no broadcast spoofing on the wire, no race condition, and no dependence on Windows Update polling. The price was rigidity: the hard-coded BITS class identifier and port 6666 made the tool brittle to BITS being disabled, and the original release depended on the Metasploit framework.&lt;/p&gt;
&lt;h3&gt;5.2 RottenPotatoNG and lonelypotato&lt;/h3&gt;
&lt;p&gt;In December 2017, the user &lt;code&gt;breenmachine&lt;/code&gt; published RottenPotatoNG, a C++ port that removed the Metasploit dependency: &quot;New version of RottenPotato as a C++ DLL and standalone C++ binary - no need for meterpreter or other tools&quot; [@breenmachine-rottenng]. The codebase that JuicyPotato would later generalise was now in place.&lt;/p&gt;

Many surveys date the `decoder-it/lonelypotato` variant to &quot;early 2018&quot; and place it as the link between RottenPotatoNG and JuicyPotato. The GitHub REST API reports `created_at: 2020-02-08T16:30:00Z` for the repository [@decoder-lonely], a full two years later. Decoder&apos;s first appearance in the Potato lineage is actually the December 6, 2019 post &quot;We thought they were Potatoes but they were Beans&quot; [@decoder-beans], with `lonelypotato` arriving in February 2020 as a post-OXID-hardening cleanup variant adjacent to RoguePotato [@decoder-lonely]. The 2017-2018 attribution is a citation error that has propagated across several survey papers.
&lt;h3&gt;5.3 JuicyPotato (Pierini + Trotta, July-August 2018)&lt;/h3&gt;
&lt;p&gt;What if any class identifier, not just the BITS one, could be the activation target? On July 27, 2018, Andrea Pierini and Giuseppe Trotta published the answer. The repository &lt;code&gt;ohpe/juicy-potato&lt;/code&gt; was created that day per the GitHub REST API; the blog post followed on August 10, 2018 [@ohpe-juicy]. The repository description reads: &quot;Juicy Potato (abusing the golden privileges) -- A sugared version of RottenPotatoNG, with a bit of juice&quot; [@ohpe-juicy].&lt;/p&gt;
&lt;p&gt;The original JuicyPotato blog post at &lt;code&gt;decoder.cloud/2018/08/10/juicy-potato-abusing-the-golden-privileges/&lt;/code&gt; returns HTTP 404 in 2026, and no Wayback Machine snapshot exists for that exact URL. The &lt;code&gt;ohpe/juicy-potato&lt;/code&gt; README is the live verbatim mirror of the title and the technique walkthrough [@ohpe-juicy]. Pierini&apos;s blog has reorganised several times; older posts that survive elsewhere on &lt;code&gt;decoder.cloud&lt;/code&gt; include the October 2018 &quot;No more Rotten/Juicy Potato&quot; [@decoder-no-more-rotten] and the December 2019 &quot;We thought they were Potatoes&quot; [@decoder-beans].&lt;/p&gt;
&lt;p&gt;JuicyPotato turned RottenPotato into a search engine. The README ships a per-Windows-version class identifier matrix: each row a Windows release, each column a CLSID that activates under SYSTEM context and implements the &lt;code&gt;IMarshal&lt;/code&gt; interface [@ohpe-juicy]. The tool accepts a tunable listener port (replacing the hard-coded 6666), a tunable process-creation mode (&lt;code&gt;CreateProcessWithToken&lt;/code&gt; for &lt;code&gt;SeImpersonate&lt;/code&gt; holders, &lt;code&gt;CreateProcessAsUser&lt;/code&gt; for &lt;code&gt;SeAssignPrimaryToken&lt;/code&gt; holders, or both), and a TEST mode for class-identifier discovery [@ohpe-juicy].&lt;/p&gt;

Microsoft does not freeze the set of registered Distributed COM class identifiers across Windows builds. Default COM-server registrations change between releases as components are added, removed, or refactored. A class identifier that activates under SYSTEM on Windows 10 1709 may not exist on Server 2019. JuicyPotato&apos;s CLSID matrix is therefore not a static lookup table -- it is the precomputed result of an empirical per-build search [@ohpe-juicy]. Every red-team handbook published between 2018 and 2020 references this matrix; subsequent variants (RoguePotato, JuicyPotatoNG) inherit and update it.

flowchart TD
    A[Enumerate registered DCOM CLSIDs on target build] --&amp;gt; B{&quot;For each CLSID&quot;}
    B --&amp;gt; C[Attempt CoGetInstanceFromIStorage with marshalled IStorage]
    C --&amp;gt; D{&quot;Activation reaches attacker listener?&quot;}
    D --&amp;gt;|No| B
    D --&amp;gt;|Yes| E{&quot;Callback authenticates as SYSTEM?&quot;}
    E --&amp;gt;|No| B
    E --&amp;gt;|Yes| F[Log CLSID into per-OS matrix]
    F --&amp;gt; B
    B --&amp;gt; G[Output: working CLSID for this Windows build]
&lt;p&gt;The Potato class was now universal. From mid-2018 through 2019 it was the default tool in every red-team handbook, every Metasploit-adjacent post-exploitation cheat-sheet, and every penetration-testing certification&apos;s lab. Microsoft had noticed.&lt;/p&gt;
&lt;h2&gt;6. The Mitigation Arms Race, 2020-2024&lt;/h2&gt;
&lt;p&gt;Every subsection below is the same shape: Microsoft ships a mitigation, researchers find a counter-move, MSRC produces an artifact (a CVE, a &quot;Won&apos;t Fix&quot; decision, or silence), and the architectural reading gets one more empirical confirmation.&lt;/p&gt;
&lt;h3&gt;6.1 The first Distributed COM mitigation, 2019-2020&lt;/h3&gt;
&lt;p&gt;In late 2018, Windows 10 1809 and Server 2019 began shipping a change to RPCSS. JuicyPotato stopped working. Researchers who reverse-engineered the change discovered that the OXID resolver address on the local Distributed COM activation path was now hard-coded to &lt;code&gt;127.0.0.1:135&lt;/code&gt;. The marshalled &lt;code&gt;IStorage&lt;/code&gt; callback could no longer be redirected to an arbitrary loopback port. Forshaw described it bluntly three years later:&lt;/p&gt;

Being able to redirect the OXID resolver RPC connection locally to a different TCP port was not by design and Microsoft eventually fixed this in Windows 10 1809/Server 2019. -- James Forshaw, October 2021 [@forshaw-pz-2021]
&lt;p&gt;No CVE was assigned. The change shipped silently as part of the regular Patch Tuesday cycle [@forshaw-pz-2021]. Pierini and Cocomazzi tested it on their own workloads and confirmed the failure mode publicly in October 2018: &quot;Recently I downloaded the new Windows server 2019 and upgraded my Win10 box to 1809 ... the juicy/rotten exploit ... did not work on both OS&quot; [@decoder-no-more-rotten].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 2019-2020 OXID-resolver change is the first Microsoft response to the Potato family. It does not declare Distributed COM activation a security boundary. It narrows the resolver port to 135 and leaves the underlying primitive (coerce SYSTEM context via OXID resolver, then impersonate the resulting token) intact. The mitigation defines exactly one specific bypass; researchers had to discover that themselves [@forshaw-pz-2021; @decoder-no-more-rotten].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2 RoguePotato (Cocomazzi + Pierini, May 2020)&lt;/h3&gt;
&lt;p&gt;On May 10, 2020, Antonio Cocomazzi published the RoguePotato repository on GitHub [@antonio-rogue]. The disclosure post appeared the next day, May 11. The README banner is &quot;RoguePotato @splinter_code &amp;amp; @decoder_it&quot; -- the same Pierini-and-Cocomazzi team that goes on to author RemotePotato0, JuicyPotatoNG, LocalPotato, and SilverPotato [@antonio-rogue].&lt;/p&gt;
&lt;p&gt;The counter-move accepts the hard-coded port-135 constraint and works around it. RoguePotato is two pieces. On an attacker-controlled remote host, run a port forwarder that listens on TCP 135 and redirects to a chosen attacker port. On the target, run &lt;code&gt;RoguePotato.exe&lt;/code&gt; pointing the OXID resolver at the remote forwarder. RPCSS dutifully sends the resolution request to the remote host on port 135 (since Microsoft hard-coded the &lt;em&gt;port&lt;/em&gt;, not the &lt;em&gt;host&lt;/em&gt;); the forwarder bounces the traffic back to the target on the attacker-chosen port; RoguePotato impersonates the OXID resolver and steers the activation back to a SYSTEM-context COM server [@antonio-rogue]. Standard NTLM relay and named-pipe impersonation finish the job.&lt;/p&gt;

flowchart LR
    A[RoguePotato.exe on target] --&amp;gt; B[RPCSS sends OXID resolution to remote-host port 135]
    B --&amp;gt; C[Remote port forwarder on attacker VPS]
    C --&amp;gt; D[Forward to target on attacker-chosen port]
    D --&amp;gt; E[Fake OXID resolver inside RoguePotato]
    E --&amp;gt; F[Steer activation to SYSTEM-context COM server]
    F --&amp;gt; G[Named-pipe impersonation, CreateProcessWithToken, SYSTEM shell]
&lt;p&gt;{&lt;code&gt;// Step 1 -- on an attacker-controlled remote host (any internet-reachable VPS): const forwarder = &quot;socat tcp-listen:135,reuseaddr,fork tcp:10.0.0.3:9999&quot;; // Step 2 -- on the target with SeImpersonatePrivilege: const exploit = &apos;RoguePotato.exe -r 10.0.0.3 -e &quot;C:\\\\windows\\\\system32\\\\cmd.exe&quot; -l 9999&apos;; console.log(&quot;Remote forwarder:&quot;, forwarder); console.log(&quot;Target exploit  :&quot;, exploit); console.log(&quot;Expected output : nt authority\\\\system&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;RoguePotato proved that the mitigation Microsoft chose did not break the underlying primitive. It only forced the attack to phone home. Two failure modes followed: in egress-filtered networks where outbound TCP 135 is blocked, the technique cannot run, and the remote forwarder is operationally noisy. Researchers needed a workaround that lived entirely on the target.&lt;/p&gt;
&lt;h3&gt;6.3 PrintSpoofer (Clément Labro, early May 2020)&lt;/h3&gt;
&lt;p&gt;Around the same time as RoguePotato, in early May 2020 (GitHub repository &lt;code&gt;itm4n/PrintSpoofer&lt;/code&gt; created April 28, 2020; blog post first archived in the Wayback Machine on May 3, 2020), Clément Labro -- writing as &lt;code&gt;itm4n&lt;/code&gt; -- published &quot;PrintSpoofer -- Abusing Impersonation Privileges on Windows 10 and Server 2019&quot; [@itm4n-printspoofer]. The mechanism uses no Distributed COM at all.&lt;/p&gt;
&lt;p&gt;The Print Spooler service exposes an RPC call, &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt;, that accepts a UNC path; the Spooler -- running as SYSTEM -- connects to that path to deliver printer-change notifications. Point the path at an attacker-owned named pipe; the Spooler connects; call &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;; done [@itm4n-printspoofer]. Labro articulated the family&apos;s thesis statement in the post, attributing it to Decoder:&lt;/p&gt;

If you have SeAssignPrimaryToken or SeImpersonate privilege, you are SYSTEM. -- attributed to Andrea Pierini (@decoder_it), quoted by Clément Labro in the PrintSpoofer writeup, May 2020 [@itm4n-printspoofer]

sequenceDiagram
    participant Atk as PrintSpoofer (SeImpersonate holder)
    participant Pipe as Attacker-owned named pipe
    participant Spooler as Print Spooler (SYSTEM)
    Atk-&amp;gt;&amp;gt;Pipe: Create named pipe and start accept loop
    Atk-&amp;gt;&amp;gt;Spooler: RpcRemoteFindFirstPrinterChangeNotificationEx with attacker UNC
    Spooler-&amp;gt;&amp;gt;Pipe: Connect to UNC path under SYSTEM context
    Pipe-&amp;gt;&amp;gt;Atk: ImpersonateNamedPipeClient on server thread
    Atk-&amp;gt;&amp;gt;Atk: CreateProcessWithToken spawns SYSTEM shell
&lt;p&gt;This is the moment the architectural reading clicks. The family is &lt;em&gt;not&lt;/em&gt; about Distributed COM activation. Closing DCOM would not close the family. The next variant would use Spooler RPC, the one after that would use the Encrypting File System RPC, and the one after that would use Microsoft Distributed Transaction Coordinator RPC. Forshaw&apos;s contemporaneous April 2020 tiraniddo.dev post on shared logon sessions makes the same architectural point from a different angle [@forshaw-tiraniddo-2020].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Potato family is about the primitive, not the vehicle. &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; plus &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; plus any SYSTEM-context Windows service with a callback-style API equals SYSTEM. Closing one vehicle (Distributed COM activation) leaves every other vehicle (Spooler RPC, EFS RPC, the next service that gets a callback interface) wide open [@itm4n-printspoofer; @forshaw-tiraniddo-2020].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.4 RemotePotato0 and the &quot;Won&apos;t Fix&quot;&lt;/h3&gt;
&lt;p&gt;In April 2021, Cocomazzi and Pierini pushed the technique across the network in a SentinelLabs post titled &quot;Relaying Potatoes: DCE/RPC NTLM Relay EoP&quot; [@sentinellabs-relaying]. The repository tagline names the outcome bluntly: &quot;Just another &apos;Won&apos;t Fix&apos; Windows Privilege Escalation from User to Domain Admin&quot; [@antonio-remote].&lt;/p&gt;
&lt;p&gt;The mechanism is cross-session NTLM relay over Distributed COM and RPC. An unprivileged local user triggers the Distributed COM activation service to make another user logged on the same machine (typically an administrator in an interactive RDP session) authenticate via NTLM. The captured NTLM exchange is then cross-protocol relayed (RPC to LDAP, with a port forwarder bridging the gap) to a domain controller with LDAP signing disabled. The attacker writes their own account into a privileged group or registers resource-based constrained delegation, and the engagement is over [@sentinellabs-relaying].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response is the most quoted sentence in the family&apos;s history:&lt;/p&gt;

The current status of this vulnerability is &apos;won&apos;t fix&apos; ... Although Microsoft considers the vulnerability an important privilege escalation, it has been classified as &apos;Won&apos;t Fix&apos;. -- SentinelLabs disclosure of RemotePotato0, April 2021 [@sentinellabs-relaying]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; RemotePotato0 was a fully working exploit chain that promoted any local low-privilege user to Domain Admin. Microsoft was given the disclosure, replicated the technique, and declined to issue a CVE. This is the moment the architectural reading stops being a researcher narrative and becomes a documented MSRC decision [@sentinellabs-relaying]. Microsoft eventually shipped a partial mitigation in October 2022 that broke the RPC-to-LDAP scenario specifically, but the underlying primitive survives in adjacent variants [@antonio-remote].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.5 The CVE-2021-26414 Distributed COM hardening rollout&lt;/h3&gt;
&lt;p&gt;Two months after the RemotePotato0 disclosure, Microsoft began the only DCOM-side hardening it would ship under a CVE. KB5004442 documents a three-phase rollout, quoted verbatim from the article: &quot;The first phase of DCOM updates was released on June 8, 2021. In that update, DCOM hardening was disabled by default. ... The second phase of DCOM updates was released on June 14, 2022. ... The final phase of DCOM updates will be released in March 2023. It will keep the DCOM hardening enabled and remove the ability to disable it&quot; [@ms-kb5004442].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Phase 1&lt;/td&gt;
&lt;td&gt;June 8, 2021&lt;/td&gt;
&lt;td&gt;DCOM hardening shipped, &lt;em&gt;disabled by default&lt;/em&gt;. Administrators may opt in via registry.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2&lt;/td&gt;
&lt;td&gt;June 14, 2022&lt;/td&gt;
&lt;td&gt;Hardening &lt;em&gt;enabled by default&lt;/em&gt;. Registry opt-out still available.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3&lt;/td&gt;
&lt;td&gt;March 14, 2023&lt;/td&gt;
&lt;td&gt;Hardening &lt;em&gt;enforced with no opt-out&lt;/em&gt;. The &lt;code&gt;RPC_C_AUTHN_LEVEL_PKT_INTEGRITY&lt;/code&gt; minimum is mandatory.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The RPC authentication-level constant that requires every packet of an RPC exchange to be signed for integrity (level 5 of 6). CVE-2021-26414 raises the *minimum* DCOM activation authentication level to this constant, rejecting legacy Distributed COM clients that activate at lower levels. The full rejection appears in Windows Event ID 10036 as &quot;The server-side authentication level policy does not allow the user %1\\%2 SID (%3) from address %4 to activate DCOM server. Please raise the activation authentication level at least to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY in client application&quot; [@ms-kb5004442].
&lt;p&gt;The hardening raised the bar for legacy Distributed COM client authentication. It did not declare Distributed COM activation a security boundary [@ms-kb5004442; @ms-techcommunity-dcom]. The &quot;Manage changes&quot; framing in the KB title is deliberate: this is a compatibility migration with telemetry events (10036 server-side, 10037 and 10038 client-side) so enterprises can find legacy clients before the final cut [@ms-kb5004442].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Distributed COM is everywhere in Windows. Removing the ability to activate at a lower authentication level breaks legacy Distributed COM applications that have not been updated since at least 2014. Microsoft&apos;s 21-month rollout window between Phase 1 (June 2021) and Phase 3 (March 2023) was a compatibility migration -- the telemetry events let enterprise IT find and fix the legacy clients before the final cut [@ms-kb5004442; @ms-techcommunity-dcom]. The hardening is the most aggressive Distributed COM mitigation Microsoft has ever shipped, and even so it does not declare Distributed COM activation a security boundary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Researchers had 21 months to find a way around it. They took 18.&lt;/p&gt;
&lt;h3&gt;6.6 JuicyPotatoNG (Pierini + Cocomazzi, September 21, 2022)&lt;/h3&gt;
&lt;p&gt;Pierini and Cocomazzi returned on September 21, 2022, with JuicyPotatoNG -- the last pre-Phase-3 Distributed COM activation variant [@decoder-juicyng]. The blog post is titled &quot;Giving JuicyPotato a second chance: JuicyPotatoNG&quot; and walks through three counter-moves combined into a single binary [@decoder-juicyng; @antonio-juicyng].&lt;/p&gt;
&lt;p&gt;First, the tool embeds Forshaw&apos;s October 2021 local-OXID trick. Forshaw had shown that an OXID resolution request could be answered by a local Distributed COM server on a randomly selected port, dropping the need for an external forwarder [@forshaw-pz-2021]. JuicyPotatoNG ships that trick as a default. Second, it falls back to a tight set of usable class identifiers; the default is &lt;code&gt;{854A20FB-2D44-457D-992F-EF13785D2B51}&lt;/code&gt;, the PrintNotify class [@antonio-juicyng]. Third, it calls &lt;code&gt;LogonUser&lt;/code&gt; with &lt;code&gt;LOGON32_LOGON_NEW_CREDENTIALS&lt;/code&gt; to sidestep the INTERACTIVE-group restriction that constrained earlier post-RoguePotato attempts [@decoder-juicyng].&lt;/p&gt;
&lt;p&gt;The cross-pollination is worth marking. Forshaw&apos;s October 2021 Project Zero post on relaying Distributed COM authentication described the local-OXID trick as a research result [@forshaw-pz-2021]. Pierini and Cocomazzi picked it up eleven months later and shipped it as the default mode of JuicyPotatoNG [@decoder-juicyng]. SilverPotato (April 2024) and the Compass Security follow-on (September 2024) cite the same trick [@compass-three-headed]. Forshaw&apos;s blog has been the unofficial reference implementation for the lineage&apos;s offensive primitives for half its lifetime.&lt;/p&gt;
&lt;p&gt;JuicyPotatoNG also implements a Security Support Provider Interface (SSPI) hook on &lt;code&gt;AcceptSecurityContext&lt;/code&gt; to capture the SYSTEM token without requiring &lt;code&gt;RpcImpersonateClient&lt;/code&gt;. The effect is to make the tool work for both &lt;code&gt;SeImpersonate&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;SeAssignPrimaryToken&lt;/code&gt; holders [@decoder-juicyng]. The result is a clean, single-binary, no-external-infrastructure local-DCOM-activation exploit -- which is the version that worked between Phase 2 (June 14, 2022, enabled by default) and Phase 3 (March 14, 2023, enforced with no opt-out) of the CVE-2021-26414 rollout [@ms-kb5004442].&lt;/p&gt;
&lt;p&gt;The next variant would need to survive Phase 3.&lt;/p&gt;
&lt;h3&gt;6.7 GodPotato (BeichenDream, December 23, 2022)&lt;/h3&gt;
&lt;p&gt;Three months after JuicyPotatoNG, on December 23, 2022, the Chinese-speaking researcher BeichenDream published GodPotato to GitHub [@beichendream-god]. The README is bilingual English and Chinese, and it opens with a precise summary of where the variant fits in the lineage:&lt;/p&gt;

Based on the history of Potato privilege escalation for 6 years, from the beginning of RottenPotato to the end of JuicyPotatoNG, I discovered a new technology by researching DCOM, which enables privilege escalation in Windows 2012 - Windows 2022 ... There are some defects in rpcss when dealing with oxid, and rpcss is a service that must be opened by the system, so it can run on almost any Windows OS, I named it GodPotato. -- BeichenDream, GodPotato README, December 2022 [@beichendream-god]
&lt;p&gt;The mechanism manipulates the OXID-handling flow &lt;em&gt;inside&lt;/em&gt; RPCSS so the activated Distributed COM server&apos;s authentication callback returns to a tool-controlled endpoint &lt;em&gt;without&lt;/em&gt; requiring the OXID resolver to be redirected. Because the redirect itself is what the CVE-2021-26414 hardening rejects, GodPotato sidesteps the hardening entirely [@beichendream-god]. RPCSS is a mandatory Windows service -- it cannot be disabled without breaking the operating system -- so the technique works on every supported Windows release as of disclosure.&lt;/p&gt;
&lt;p&gt;{&lt;code&gt;// On a target host where the calling account holds SeImpersonatePrivilege // (default for every IIS app-pool identity, MSSQL service account, BITS account, etc.) const command = &apos;GodPotato -cmd &quot;cmd /c whoami&quot;&apos;; console.log(&quot;Run:&quot;, command); console.log(&quot;Expected output: nt authority\\\\system&quot;); console.log(&quot;Working OS coverage: Windows 8 through Windows 11; Server 2012 through Server 2025&quot;); console.log(&quot;Underlying primitive: RPCSS OXID-handling defect, no external infra, single binary&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;Microsoft has not assigned a CVE to the underlying RPCSS defect [@beichendream-god; @compass-three-headed].Apache 2.0 licensing matters here: red-team operators routinely recompile GodPotato from source to bypass binary-hash signatures, and the permissive license makes redistribution unproblematic [@beichendream-god]. The pattern is consistent with the servicing-criteria reading. GodPotato is in May 2026 the practitioner default on every in-support Windows release: single binary, no external infrastructure, no separate OXID resolver, Apache-2.0-licensed and freely re-buildable when EDR vendors signature the public binary [@beichendream-god].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; GodPotato survives every Microsoft mitigation because Microsoft has not declared the underlying primitive a security boundary. Three named hardening waves (the 2019-2020 OXID-resolver change, the three-phase CVE-2021-26414 rollout from June 2021 to March 2023, and the per-variant CVE patches in 2023 and 2024) leave GodPotato working on Server 2025 and Windows 11 24H2 as of this writing [@beichendream-god; @ms-kb5004442; @compass-three-headed].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.8 LocalPotato and CVE-2023-21746&lt;/h3&gt;
&lt;p&gt;Three weeks after GodPotato landed, Microsoft assigned the first-ever CVE in the local Potato lineage. The variant was LocalPotato, the CVE was CVE-2023-21746, and the patch shipped in the January 2023 Patch Tuesday [@nvd-cve-2023-21746; @msrc-cve-2023-21746]. The Decoder writeup, published February 13, 2023, walks through the timeline:&lt;/p&gt;

&quot;We reported our findings to the Microsoft Security Response Center (MSRC) on September 9, 2022, and it was resolved with the release of the January 2023 patch Tuesday and assigned the CVE number CVE-2023-21746.&quot; -- Andrea Pierini, &quot;LocalPotato&quot; writeup, February 2023 [@decoder-localpotato]
&lt;p&gt;LocalPotato is not a Distributed COM activation Potato. It attacks the local NTLM authentication protocol itself. During a local NTLM exchange, the Type 2 (Challenge) message carries a &quot;Reserved&quot; field that, in the local-NTLM case, encodes the upper bytes of the local server context handle the client should associate with. By racing two simultaneous local NTLM authentications -- one privileged client to attacker server, one attacker client to a real local server -- and swapping the Reserved fields in the two Type 2 messages, LSASS binds the privileged identity to the attacker&apos;s low-privilege context [@decoder-localpotato; @localpotato-com]. The result is an arbitrary file-read and file-write primitive that chains cleanly to SYSTEM.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Pierini and Cocomazzi had been pushing on the architectural carve-out for seven years before they got a CVE. The boundary that made the difference: LocalPotato attacks the local user-to-local-user NTLM authentication context, which &lt;em&gt;is&lt;/em&gt; on the servicing-criteria boundary list. The underlying &lt;code&gt;SeImpersonate&lt;/code&gt;-to-SYSTEM primitive is not. Microsoft will service the parts of the protocol that are inside the boundary; it will not service the parts that are outside [@decoder-localpotato; @msrc-servicing-criteria].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The LocalPotato writeup credits Elad Shamir for the original hint that started the research [@decoder-localpotato]. The dedicated companion site &lt;code&gt;localpotato.com&lt;/code&gt; carries the canonical title &quot;LocalPotato -- When swapping the context leads you to SYSTEM&quot; and links the CVE [@localpotato-com].&lt;/p&gt;
&lt;h3&gt;6.9 SilverPotato (Pierini + Cocomazzi, April 24, 2024)&lt;/h3&gt;
&lt;p&gt;A year later, on April 24, 2024, Pierini and Cocomazzi extended the cross-session Distributed COM activation primitive that RemotePotato0 had pioneered into a fully practical &lt;em&gt;domain&lt;/em&gt; attack. The blog post title is &quot;Hello, I&apos;m your domain admin and I want to authenticate against you&quot; [@decoder-silverpotato]. The Troopers 24 abstract refers to the technique by its other name, ADCSCoercePotato [@troopers24; @decoder-adcs-coerce-repo]; both names refer to the same primitive.&lt;/p&gt;
&lt;p&gt;The mechanism: members of the &lt;strong&gt;Distributed COM Users&lt;/strong&gt; or &lt;strong&gt;Performance Log Users&lt;/strong&gt; built-in groups can remotely trigger an NTLM authentication from any user currently logged on the target server -- including a Domain Administrator on a Domain Controller -- and relay it. The specific vehicle is the &lt;code&gt;sppui&lt;/code&gt; Distributed COM application (class identifier &lt;code&gt;F87B28F1-DA9A-4F35-8EC0-800EFCF26B83&lt;/code&gt;, &quot;SPPUIObjectInteractive Class&quot;, hosted in &lt;code&gt;slui.exe&lt;/code&gt;), which runs under the Interactive User identity [@decoder-silverpotato]. Pierini&apos;s wording in the post is unsparing:&lt;/p&gt;

&quot;Members of Distributed COM Users or Performance Log Users Groups can trigger from remote and relay the authentication of users connected on the target server, including Domain Controllers.&quot; -- Andrea Pierini, &quot;SilverPotato&quot; writeup, April 2024 [@decoder-silverpotato]
&lt;p&gt;The captured authentication is relayed via &lt;code&gt;ntlmrelayx&lt;/code&gt; to &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;AD CS Web Enrollment&lt;/a&gt; or LDAP, then chained with &lt;code&gt;ForgeCert&lt;/code&gt; and &lt;code&gt;Rubeus&lt;/code&gt; into a full Domain Admin Kerberos TGT [@decoder-silverpotato]. The Compass Security follow-on from September 2024 extends the chain further by modifying the KrbRelay project to make it remote and cross-session capable: &quot;I modified the KrbRelay project to make it remote and cross-session capable, because Andrea did not release his PoC code ... DCOM hardening only allows relay to HTTP or unprotected LDAP&quot; [@compass-three-headed]. Tianze Ding&apos;s Black Hat Asia 2024 talk on &quot;CertifiedDCOM&quot; landed in the same window [@blackhat-asia-2024]. Pierini&apos;s February 2024 post on the ADCS server side of the same surface foreshadowed the chain a few weeks earlier [@decoder-adcs-server].&lt;/p&gt;

flowchart LR
    A[Member of Distributed COM Users on target DC] --&amp;gt; B[Cross-session DCOM activation against sppui CLSID]
    B --&amp;gt; C[Logged-on Domain Admin session authenticates via NTLM]
    C --&amp;gt; D[ntlmrelayx forwards NTLM to AD CS Web Enrollment]
    D --&amp;gt; E[Computer-template certificate issued]
    E --&amp;gt; F[ForgeCert and Rubeus mint Domain Admin Kerberos TGT]
    F --&amp;gt; G[Domain compromise]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Troopers 24 abstract describes SilverPotato as &quot;still in review by MSRC&quot; as of June 2024 [@troopers24]. The Compass Security follow-on demonstrates a working end-to-end chain four months later [@compass-three-headed]. The default Distributed COM group memberships on Domain Controllers that grant the activation rights SilverPotato weaponises have not changed in any shipping Windows release as of May 2026. No CVE has been assigned [@decoder-silverpotato; @troopers24].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.10 FakePotato and CVE-2024-38100&lt;/h3&gt;
&lt;p&gt;Four months after SilverPotato, on August 2, 2024, Pierini published the most recent named variant. He called it FakePotato, and he was up front about the name:&lt;/p&gt;

&quot;You might be wondering why I called it the &apos;Fake&apos; Potato. Initially, I thought it could be exploited using the same techniques as the *Potato families, but it turned out to be different and much simpler in this case.&quot; -- Andrea Pierini, &quot;The Fake Potato&quot; writeup, August 2024 [@decoder-fakepotato]
&lt;p&gt;FakePotato abuses the &lt;strong&gt;ShellWindows&lt;/strong&gt; Distributed COM application (AppID &lt;code&gt;{9BA05972-F6A8-11CF-A442-00A0C90A8F39}&lt;/code&gt;), hosted in &lt;code&gt;explorer.exe&lt;/code&gt; and registered to run under the Interactive User identity. Cross-session activation via &lt;code&gt;BindToMoniker(&quot;session:N!new:&amp;lt;CLSID&amp;gt;&quot;)&lt;/code&gt; invokes &lt;code&gt;ShellExecute&lt;/code&gt; in the target session. There is no NTLM relay, no token impersonation, no &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; requirement -- any Authenticated User suffices because &lt;code&gt;explorer.exe&lt;/code&gt; in High Integrity Level (UAC-disabled administrator) granted the Authenticated Users group execute permission via the DCOM Access Security ACL [@decoder-fakepotato].&lt;/p&gt;
&lt;p&gt;{&lt;code&gt;$obj = [System.Runtime.InteropServices.Marshal]::BindToMoniker(&quot;session:2!new:9BA05972-F6A8-11CF-A442-00A0C90A8F39&quot;) $p = $obj.item(0).document.application $p.ShellExecute(&quot;c:\\temp\\reverse.bat&quot;, &quot;&quot;, &quot;c:\\windows&quot;, $null, 0)&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;Microsoft assigned CVE-2024-38100 and shipped the patch in the July 2024 Patch Tuesday cumulative updates on July 9, 2024 (KB5040434 for Windows 10 1607 / Windows Server 2016; equivalent KBs for Windows 11, Server 2019, Server 2022, and Server 2025) -- four weeks before the public disclosure [@decoder-fakepotato; @nvd-cve-2024-38100; @msrc-cve-2024-38100]. The patch corrects the &lt;code&gt;explorer.exe&lt;/code&gt; ACL in High Integrity Level contexts so the Authenticated Users permission required for activation is no longer granted. The underlying cross-session Distributed COM activation primitive that SilverPotato and FakePotato share is untouched [@decoder-silverpotato; @decoder-fakepotato].&lt;/p&gt;
&lt;p&gt;FakePotato is not, in the relay sense, a Potato at all. It is a misconfiguration of the &lt;code&gt;ShellWindows&lt;/code&gt; Distributed COM application&apos;s permissions in High Integrity Level contexts [@decoder-fakepotato]. Pierini&apos;s &quot;Fake&quot; framing acknowledges the divergence from the NTLM-reflection pattern that defined the family from RottenPotato through GodPotato. The naming choice is itself a small piece of taxonomy: not every member of the family is a token-relay exploit, even if every member exploits the same architectural carve-out.&lt;/p&gt;
&lt;p&gt;After nearly a decade of patching specific vehicles and refusing to declare the underlying primitive a boundary, Microsoft&apos;s pattern is hard to miss.&lt;/p&gt;
&lt;h2&gt;7. Eleven Variants at a Glance&lt;/h2&gt;
&lt;p&gt;Nine years of named-variant disclosures, eleven named variants, one architectural argument. The table below is sourced cell by cell from the preceding sections.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variant&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Authors&lt;/th&gt;
&lt;th&gt;Coercion vehicle&lt;/th&gt;
&lt;th&gt;Mitigation it bypassed&lt;/th&gt;
&lt;th&gt;Microsoft response&lt;/th&gt;
&lt;th&gt;Still works in 2026?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;HotPotato [@foxglove-hotpotato]&lt;/td&gt;
&lt;td&gt;Jan 16, 2016&lt;/td&gt;
&lt;td&gt;Stephen Breen&lt;/td&gt;
&lt;td&gt;NBNS spoof + WPAD + HTTP-to-SMB relay&lt;/td&gt;
&lt;td&gt;MS08-068 same-protocol-only fix&lt;/td&gt;
&lt;td&gt;None named; EPA/SMB hardening eventually closed the vehicle&lt;/td&gt;
&lt;td&gt;Only on pre-1607 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RottenPotato [@foxglove-rottenpotato]&lt;/td&gt;
&lt;td&gt;Sep 23, 2016&lt;/td&gt;
&lt;td&gt;Stephen Breen + Chris Mallz&lt;/td&gt;
&lt;td&gt;DCOM activation via BITS CLSID on 127.0.0.1:6666&lt;/td&gt;
&lt;td&gt;(none yet)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Only pre-1809 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RottenPotatoNG [@breenmachine-rottenng]&lt;/td&gt;
&lt;td&gt;Dec 29, 2017&lt;/td&gt;
&lt;td&gt;breenmachine&lt;/td&gt;
&lt;td&gt;Same as RottenPotato (C++ port; no Metasploit)&lt;/td&gt;
&lt;td&gt;(none yet)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Only pre-1809 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JuicyPotato [@ohpe-juicy]&lt;/td&gt;
&lt;td&gt;Jul 27, 2018&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Giuseppe Trotta&lt;/td&gt;
&lt;td&gt;Generalised DCOM activation; CLSID matrix&lt;/td&gt;
&lt;td&gt;(none yet)&lt;/td&gt;
&lt;td&gt;OXID-resolver hard-coding in Win10 1809 / Server 2019 [@forshaw-pz-2021]&lt;/td&gt;
&lt;td&gt;Only pre-1809 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RoguePotato [@antonio-rogue]&lt;/td&gt;
&lt;td&gt;May 10, 2020&lt;/td&gt;
&lt;td&gt;Antonio Cocomazzi + Andrea Pierini&lt;/td&gt;
&lt;td&gt;DCOM activation through remote TCP-135 forwarder&lt;/td&gt;
&lt;td&gt;2019-2020 OXID-resolver hardening&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;Only pre-Phase-3 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrintSpoofer [@itm4n-printspoofer]&lt;/td&gt;
&lt;td&gt;Early May 2020&lt;/td&gt;
&lt;td&gt;Clément Labro&lt;/td&gt;
&lt;td&gt;Print Spooler RPC &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All DCOM-side hardening (irrelevant)&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;Yes, when Spooler is running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RemotePotato0 [@sentinellabs-relaying]&lt;/td&gt;
&lt;td&gt;Apr 2021&lt;/td&gt;
&lt;td&gt;Antonio Cocomazzi + Andrea Pierini&lt;/td&gt;
&lt;td&gt;Cross-session DCOM/RPC NTLM relay&lt;/td&gt;
&lt;td&gt;(defines a new threat surface)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&quot;Won&apos;t Fix&quot;&lt;/strong&gt;; partial Oct 2022 RPC-to-LDAP mitigation&lt;/td&gt;
&lt;td&gt;Partially (primitive intact)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JuicyPotatoNG [@antonio-juicyng; @decoder-juicyng]&lt;/td&gt;
&lt;td&gt;Sep 21, 2022&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Antonio Cocomazzi&lt;/td&gt;
&lt;td&gt;Local-OXID trick + LogonUser NewCredentials&lt;/td&gt;
&lt;td&gt;CVE-2021-26414 Phase 1 and Phase 2&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;Only pre-Phase-3 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GodPotato [@beichendream-god]&lt;/td&gt;
&lt;td&gt;Dec 23, 2022&lt;/td&gt;
&lt;td&gt;BeichenDream&lt;/td&gt;
&lt;td&gt;RPCSS OXID-handling defect (no resolver redirect)&lt;/td&gt;
&lt;td&gt;All three CVE-2021-26414 phases&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes -- the 2026 default&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LocalPotato / CVE-2023-21746 [@decoder-localpotato; @nvd-cve-2023-21746]&lt;/td&gt;
&lt;td&gt;Patched Jan 10, 2023&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Antonio Cocomazzi&lt;/td&gt;
&lt;td&gt;NTLM Type-2 &quot;Reserved&quot; field context swap&lt;/td&gt;
&lt;td&gt;(orthogonal -- attacks LSASS)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CVE-2023-21746&lt;/strong&gt; (first local-Potato CVE)&lt;/td&gt;
&lt;td&gt;No -- patched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SilverPotato / ADCSCoercePotato [@decoder-silverpotato; @troopers24]&lt;/td&gt;
&lt;td&gt;Apr 24, 2024&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Antonio Cocomazzi&lt;/td&gt;
&lt;td&gt;Cross-session DCOM against &lt;code&gt;sppui&lt;/code&gt; AppID&lt;/td&gt;
&lt;td&gt;Post-RemotePotato0 partial mitigations&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Still in review by MSRC as of mid-2026&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes -- unpatched&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FakePotato / CVE-2024-38100 [@decoder-fakepotato; @nvd-cve-2024-38100]&lt;/td&gt;
&lt;td&gt;Disclosed Aug 2, 2024&lt;/td&gt;
&lt;td&gt;Andrea Pierini&lt;/td&gt;
&lt;td&gt;Cross-session DCOM against &lt;code&gt;ShellWindows&lt;/code&gt; AppID (ACL bug)&lt;/td&gt;
&lt;td&gt;(orthogonal)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CVE-2024-38100&lt;/strong&gt; in the July 2024 Patch Tuesday (KB5040434 for 1607/Server 2016; per-build KBs elsewhere)&lt;/td&gt;
&lt;td&gt;No -- patched&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two CVEs in nine years of named-variant disclosures. One &quot;Won&apos;t Fix&quot; decision on a working Domain Admin escalation. Zero declarations of &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; or Distributed COM activation as a security boundary. The pattern is consistent across every column [@troopers24; @msrc-servicing-criteria].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Two CVEs in a decade, against a family with eleven named variants. The first CVE was for a piece of the &lt;em&gt;local NTLM protocol&lt;/em&gt; that is on the servicing-criteria list, not for the underlying &lt;code&gt;SeImpersonate&lt;/code&gt;-to-SYSTEM primitive. The second was for a &lt;em&gt;Distributed COM access-control list misconfiguration&lt;/em&gt;, not for cross-session activation as a class. Microsoft will assign CVEs to specific vehicles when forced. It will not declare the architectural primitive a security boundary [@nvd-cve-2023-21746; @nvd-cve-2024-38100; @troopers24].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;8. The 2026 Decision Surface&lt;/h2&gt;
&lt;p&gt;In May 2026, an operator with &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; on a default Windows 11 box has a small menu of working tools, plus three legacy variants that remain useful on unpatched fleets. The current toolkit:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Coercion vehicle&lt;/th&gt;
&lt;th&gt;OS coverage&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GodPotato&lt;/strong&gt; [@beichendream-god]&lt;/td&gt;
&lt;td&gt;RPCSS OXID defect&lt;/td&gt;
&lt;td&gt;Win 8 to Win 11; Server 2012 to Server 2025&lt;/td&gt;
&lt;td&gt;Default first try on any in-support Windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SweetPotato&lt;/strong&gt; [@ccob-sweet]&lt;/td&gt;
&lt;td&gt;Selectable: PrintSpoofer (default), DCOM, EfsRpc, WinRM&lt;/td&gt;
&lt;td&gt;Win 7+ depending on selected mode&lt;/td&gt;
&lt;td&gt;When GodPotato&apos;s binary signature is blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SharpEfsPotato&lt;/strong&gt; [@bugch3ck-efs]&lt;/td&gt;
&lt;td&gt;EFS RPC (&lt;code&gt;EfsRpcOpenFileRaw&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Server 2019+, Win 10/11 with EFS RPC enabled&lt;/td&gt;
&lt;td&gt;DCOM locked down &lt;em&gt;and&lt;/em&gt; Spooler disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PrintSpoofer&lt;/strong&gt; [@itm4n-printspoofer]&lt;/td&gt;
&lt;td&gt;Print Spooler RPC&lt;/td&gt;
&lt;td&gt;Any host with Spooler running&lt;/td&gt;
&lt;td&gt;The lowest-noise option on Spooler-enabled hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JuicyPotatoNG&lt;/strong&gt; [@antonio-juicyng]&lt;/td&gt;
&lt;td&gt;Local-OXID + legacy CLSID&lt;/td&gt;
&lt;td&gt;Pre-Phase-3 DCOM hardening only&lt;/td&gt;
&lt;td&gt;Corporate fleets with delayed CVE-2021-26414 rollout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RoguePotato&lt;/strong&gt; [@antonio-rogue]&lt;/td&gt;
&lt;td&gt;Remote TCP-135 forwarder&lt;/td&gt;
&lt;td&gt;Pre-Phase-3 DCOM hardening&lt;/td&gt;
&lt;td&gt;Pre-2022 hardened-OXID-only systems with attacker remote infra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SilverPotato&lt;/strong&gt; [@decoder-silverpotato]&lt;/td&gt;
&lt;td&gt;Cross-session DCOM against DC&lt;/td&gt;
&lt;td&gt;Default DCs with &lt;code&gt;Distributed COM Users&lt;/code&gt; or &lt;code&gt;Performance Log Users&lt;/code&gt; membership&lt;/td&gt;
&lt;td&gt;Domain-tier escalation -- the only currently-unpatched cross-session variant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Plus three legacy variants worth knowing about: JuicyPotato on pre-1809 builds, RottenPotato on Server 2008 R2 / Windows 7 ESU-eligible builds, and HotPotato as the canonical naming origin and the source of the family&apos;s &quot;documented Win32 calls&quot; framing [@ohpe-juicy; @foxglove-rotten-repo; @foxglove-hotpotato]. Embedded Windows builds (Windows 10 IoT LTSC 2019, some industrial controllers, ATM images) frequently fall behind the OXID-resolver mitigation and remain JuicyPotato-vulnerable through 2026.&lt;/p&gt;

SharpEfsPotato&apos;s canonical repository is `github.com/bugch3ck/SharpEfsPotato` [@bugch3ck-efs]. A widely shared `ly4k/SharpEfsPotato` fork exists and is referenced in some red-team writeups, but the upstream is the `bugch3ck` repo per the README&apos;s own credit chain (&quot;Built from SweetPotato by @\_EthicalChaos\_ and SharpSystemTriggers/SharpEfsTrigger by @cube0x0&quot;) [@bugch3ck-efs]. Operators citing the `ly4k` URL are pointing at a fork.
&lt;p&gt;Every one of these tools has a Microsoft mitigation in its history. None of those mitigations closed the family. The next section asks what mitigation could.&lt;/p&gt;
&lt;h2&gt;9. What Would It Take To Close the Family?&lt;/h2&gt;
&lt;p&gt;A counterfactual sharpens the question. Suppose Microsoft decided in 2026 that the family must end. Three closure options exist, and each carries a compatibility cost.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Closure option&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Compatibility cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1. Declare &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; a security boundary&lt;/td&gt;
&lt;td&gt;Revoke the privilege from default service accounts (IIS app pools, SQL Server, BITS, Task Scheduler, the Spooler)&lt;/td&gt;
&lt;td&gt;Operationally prohibitive: thousands of third-party services depend on the default grant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Declare Distributed COM activation a security boundary&lt;/td&gt;
&lt;td&gt;Validate the activator&apos;s identity against the activated CLSID&apos;s registered identity on every activation&lt;/td&gt;
&lt;td&gt;Breaks 25 years of legacy Distributed COM applications written between 1996 and 2021 [@ms-dcom-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Deprecate &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; as a Win32 primitive&lt;/td&gt;
&lt;td&gt;Remove the call from &lt;code&gt;namedpipeapi.h&lt;/code&gt; or gate it behind a Trustlet validation&lt;/td&gt;
&lt;td&gt;Breaks parts of CSRSS, the console subsystem, and LSASS itself; no deprecation notice exists in the API reference as of mid-2026 [@ms-impersonate-api]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The CVE-2021-26414 hardening creeps toward option 2 for &lt;em&gt;remote&lt;/em&gt; Distributed COM but explicitly does not for &lt;em&gt;local&lt;/em&gt; Distributed COM [@ms-kb5004442]. The &lt;a href=&quot;https://paragmali.com/blog/adminless-how-windows-finally-made-elevation-a-security-boun/&quot; rel=&quot;noopener&quot;&gt;Adminless direction&lt;/a&gt; in Windows 11 24H2 -- Microsoft&apos;s &quot;Administrator protection&quot; platform feature, currently a preview shipped first via Windows Insider builds and not yet generally available [@ms-administrator-protection] -- introduces a per-application admin-elevation gate, but operates &lt;em&gt;above&lt;/em&gt; the SYSTEM-impersonation primitive, not below it. &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; isolates LSASS secrets in a &lt;a href=&quot;https://paragmali.com/blog/vbs-trustlets-what-actually-runs-in-the-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;Virtualization-Based Security Trustlet&lt;/a&gt; -- which protects NTLM hashes from extraction but does not gate &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; or &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; [@ms-credential-guard]. &lt;a href=&quot;https://paragmali.com/blog/living-off-the-land-on-windows-the-lolbin-catalog-and-the-st/&quot; rel=&quot;noopener&quot;&gt;Smart App Control&lt;/a&gt; restricts arbitrary binary execution but does not block in-process exploitation by a SYSTEM-running service [@ms-smart-app-control].&lt;/p&gt;
&lt;p&gt;The lower bound on attack cost is therefore O(1) per invocation, and it stays O(1) as long as the servicing-criteria carve-out holds. No combination of currently-shipping mitigations moves it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Potato family is a fixed point of the current Windows architecture. Every closure option carries a compatibility cost that no currently-announced Microsoft release accepts. Until the MSRC Windows Security Servicing Criteria changes the position on &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; and Distributed COM activation, the family&apos;s lower attack cost is O(1) and no servicing patch can move it [@msrc-servicing-criteria; @troopers24].&lt;/p&gt;
&lt;/blockquote&gt;

The claim is empirical, not formal. A &quot;fixed point&quot; in the algorithmic sense is a value where a function returns its own input. For the Potato family the analogue is: every Microsoft mitigation that does not change the servicing-criteria document returns a family that is still alive. The fixed-point status is consistent with eleven variants over nine years of named-variant disclosures (HotPotato January 2016 -&amp;gt; FakePotato August 2024) against three named hardening waves. It would be invalidated by a major-version Windows release that explicitly revoked the default `SeImpersonatePrivilege` grant on service accounts. No such release is on the public roadmap as of May 2026 [@msrc-servicing-criteria].
&lt;h2&gt;10. Open Problems&lt;/h2&gt;
&lt;p&gt;Five questions sit at the research frontier in 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The next coercion vehicle.&lt;/strong&gt; Each Potato variant is one SYSTEM-context service with a callback-style API. As the family has matured, researchers have mapped a growing surface of candidates: EFS RPC (which SharpEfsPotato already weaponises [@bugch3ck-efs]), Print Spooler async RPC (MS-PAR), Windows Search remote protocol (MS-WSP), and Microsoft Distributed Transaction Coordinator RPC. The community-empirical conjecture, repeated across Troopers 24 [@troopers24] and the Compass Security retrospective [@compass-three-headed], is that any SYSTEM-context Windows service with a callback-style API becomes a Potato vehicle within roughly eighteen months of operational need.&lt;/p&gt;
&lt;p&gt;The &quot;eighteen-month vehicle cadence&quot; is an informal community claim, not a measured statistic. It originates in the Troopers 24 retrospective by Pierini and Cocomazzi [@troopers24] and is reinforced by the Compass Security follow-on documenting how the SilverPotato chain was productised within months of Pierini&apos;s February 2024 ADCS-server post [@decoder-adcs-server; @compass-three-headed]. The number should be read as a rule of thumb, not a benchmark.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux and Windows Subsystem for Linux extension.&lt;/strong&gt; No Linux analogue of &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; exists. There are partial precedents in the impacket cross-protocol relay work, but no Potato-class primitive that produces a SYSTEM token on a Linux host. Open.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Will defence-in-depth combine to close the family without ever declaring a new boundary?&lt;/strong&gt; Microsoft has shipped Credential Guard [@ms-credential-guard], &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;Hypervisor-Protected Code Integrity&lt;/a&gt; [@ms-hvci], Smart App Control [@ms-smart-app-control], and the experimental Administrator-protection direction in Windows 11 24H2 [@ms-administrator-protection]. Each changes the runtime trust model in some way. No combination of currently-shipping technologies closes the family as of May 2026 -- the Potato primitives live below the layer those technologies operate on [@troopers24; @compass-three-headed].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A defensive detection primitive that catches every variant.&lt;/strong&gt; The unifying invariant is &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; being called from a thread that holds &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; against a named pipe that has just received a SYSTEM-context authentication originating from a service the calling process did not initiate. Per-variant detection rules exist for each named tool (GodPotato, PrintSpoofer, JuicyPotato). A generalising rule has not been published [@ms-impersonate-api]. The informal community position is that the family is &lt;em&gt;non-detectable as a class&lt;/em&gt; because the primitive is in the legitimate hot path of nearly every Windows service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MSRC servicing-criteria position on cross-session Distributed COM activation.&lt;/strong&gt; LocalPotato (CVE-2023-21746) received a CVE for a piece of the local NTLM protocol [@nvd-cve-2023-21746]. FakePotato (CVE-2024-38100) received a CVE for an access-control list misconfiguration on the &lt;code&gt;ShellWindows&lt;/code&gt; AppID [@nvd-cve-2024-38100]. SilverPotato is still unpatched [@decoder-silverpotato; @troopers24]. The boundary that distinguishes these three is unclear: why was the &lt;code&gt;ShellWindows&lt;/code&gt; cross-session activation patched while the &lt;code&gt;sppui&lt;/code&gt; cross-session activation has not been? The answer determines the next decade of the family. The defensible reading is that Microsoft will service variants that look like permission misconfigurations on a single AppID but not the underlying cross-session Distributed COM activation primitive itself.&lt;/p&gt;
&lt;h2&gt;11. How to Use a Potato in 2026&lt;/h2&gt;
&lt;p&gt;The practitioner question is operational. Given a foothold and a goal, which Potato variant does the job? The decision tree below walks through the path researchers settle into on red-team engagements.&lt;/p&gt;

flowchart TD
    A[Target OS in support?] --&amp;gt;|&quot;No&quot;| Z1[JuicyPotato on pre-2020 builds, or RoguePotato on 2020-2022 builds]
    A --&amp;gt;|&quot;Yes&quot;| B[Operator privilege?]
    B --&amp;gt;|&quot;SeImpersonate or SeAssignPrimaryToken&quot;| C[Spooler running?]
    B --&amp;gt;|&quot;Standard user, cross-session victim present&quot;| Z2[FakePotato technique illustrative -- patched in KB5040434]
    B --&amp;gt;|&quot;DCOM-group member on a DC&quot;| Z3[SilverPotato with ntlmrelayx to AD CS]
    C --&amp;gt;|&quot;Yes&quot;| D[SweetPotato -e PrintSpoofer default]
    C --&amp;gt;|&quot;No&quot;| E[EFS RPC reachable?]
    E --&amp;gt;|&quot;Yes&quot;| F[SharpEfsPotato]
    E --&amp;gt;|&quot;No&quot;| G[GodPotato as fallback]
&lt;p&gt;The first-try heuristic is short. &lt;strong&gt;GodPotato first&lt;/strong&gt;, because it is the single binary that works on every in-support Windows release [@beichendream-god]. If the GodPotato binary signature is blocked by Endpoint Detection and Response, &lt;strong&gt;SweetPotato with &lt;code&gt;-e PrintSpoofer&lt;/code&gt;&lt;/strong&gt; (or &lt;code&gt;-e EfsRpc&lt;/code&gt; on a Domain Controller where Spooler is off) [@ccob-sweet]. If both are blocked, &lt;strong&gt;SharpEfsPotato&lt;/strong&gt; as the lower-public-exposure third choice [@bugch3ck-efs]. For pre-2023 unpatched fleets, &lt;strong&gt;JuicyPotatoNG&lt;/strong&gt; during the Phase-2 hardening window and &lt;strong&gt;JuicyPotato&lt;/strong&gt; on pre-1809 builds [@antonio-juicyng; @ohpe-juicy]. For domain escalation against a DC, &lt;strong&gt;SilverPotato&lt;/strong&gt; with the Compass Security KrbRelay modifications [@decoder-silverpotato; @compass-three-headed].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; GodPotato. If signature-blocked, SweetPotato with &lt;code&gt;-e PrintSpoofer&lt;/code&gt;. If both blocked, SharpEfsPotato. The rest of the family is for situations the first three do not cover (legacy fleets, DC escalation, technique illustration of patched variants) [@beichendream-god; @ccob-sweet; @bugch3ck-efs].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Several implementation pitfalls catch new operators. The named-pipe path that GodPotato uses (&lt;code&gt;\pipe\&amp;lt;token&amp;gt;\pipe\epmapper&lt;/code&gt;) is widely signatured by EDR vendors -- see the detection-engineering Spoiler below for the specific Sigma and Elastic rules [@sigma-potato-hktl; @elastic-rogue-pipe] -- and recompiling from source with a different pipe template is the standard countermeasure. A token &lt;em&gt;holding&lt;/em&gt; &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; does not necessarily &lt;em&gt;enable&lt;/em&gt; it -- explicit &lt;code&gt;AdjustTokenPrivileges&lt;/code&gt; with &lt;code&gt;SE_PRIVILEGE_ENABLED&lt;/code&gt; is required, and custom adaptations frequently miss the step [@ms-adjusttokenprivileges]. SweetPotato&apos;s default &lt;code&gt;-e PrintSpoofer&lt;/code&gt; mode fails silently on a Domain Controller where Spooler is disabled per the PrintNightmare aftermath; the correct DC default is GodPotato or SharpEfsPotato. RoguePotato&apos;s outbound TCP 135 to attacker infrastructure is blocked by default in most enterprise networks. FakePotato and SilverPotato both require the victim identity to be actively logged in, since both depend on a live cross-session activation surface [@itm4n-printspoofer; @antonio-rogue; @decoder-silverpotato; @decoder-fakepotato].&lt;/p&gt;

If you defend Windows rather than attack it, the detection target is the conjunction of (a) named-pipe creation by an IIS or SQL or service account, (b) a SYSTEM-context process connecting to that pipe shortly after, and (c) `CreateProcessWithToken` from the original service-account process. None of the three events alone is anomalous. The conjunction is. Sysmon Event ID 1 (Process Create) paired with Event IDs 17 and 18 (PipeEvent: Pipe Created and Pipe Connected) plus ETW providers `Microsoft-Windows-COM` and `Microsoft-Windows-RPC` cover the activation-plus-pipe half [@ms-sysmon]; Sysmon Event ID 10 (ProcessAccess) on `lsass.exe` from the originating service account is the third pillar that surfaces the impersonation handle acquisition [@ms-sysmon]. Per-variant signatures are published as Sigma rules for the public LocalPotato, CoercedPotato, JuicyPotato, RottenPotato, and EfsPotato binaries [@sigma-potato-hktl; @sigma-localpotato], and Elastic&apos;s `privilege_escalation_via_rogue_named_pipe` rule fires on the PrintSpoofer / EfsPotato pipe-path pattern that GodPotato shares [@elastic-rogue-pipe]. A class-generalising rule that fires on the *primitive* (rather than per-binary) has not been published.
&lt;p&gt;Library and framework support follows the same shape as any post-exploitation primitive (the picture here is community-empirical, drawn from public BOF and module repositories rather than vendor reference architectures). Cobalt Strike Beacon Object Files wrapping GodPotato, PrintSpoofer, and SweetPotato are widely shared in the red-team community -- &lt;code&gt;incursi0n/GodPotatoBOF&lt;/code&gt; is one publicly published example that integrates with &lt;code&gt;BeaconUseToken()&lt;/code&gt; for in-Beacon SYSTEM-token application [@godpotato-bof] -- and the same wrappers load into Sliver. PowerShell wrappers around PrintSpoofer and JuicyPotato are integrated into Empire and Starkiller. The Metasploit &lt;code&gt;incognito&lt;/code&gt; post-exploitation module handles token impersonation as a primitive but does not wrap GodPotato directly [@msf-incognito]. The &lt;code&gt;impacket&lt;/code&gt; toolkit&apos;s &lt;code&gt;ntlmrelayx&lt;/code&gt; is the canonical relay engine for the tail of SilverPotato [@fortra-impacket], and OleViewDotNet -- Forshaw&apos;s tool -- is the discovery oracle that surfaced the &lt;code&gt;sppui&lt;/code&gt; and &lt;code&gt;ShellWindows&lt;/code&gt; AppIDs in the first place [@tyranid-oleview; @decoder-silverpotato; @decoder-fakepotato].&lt;/p&gt;
&lt;h2&gt;12. Frequently Asked Questions&lt;/h2&gt;


The name `Potato` originates with Stephen Breen&apos;s `foxglovesec/Potato` repository, created February 9, 2016, three weeks after the January 16, 2016 HotPotato blog post [@foxglove-potato-repo; @foxglove-hotpotato]. HotPotato is in the family because it pivots through the same `SeImpersonatePrivilege` plus named-pipe-impersonation primitive that every later variant exploits -- the vehicle is different (NetBIOS spoofing + WPAD + HTTP-to-SMB rather than Distributed COM) but the architectural carve-out is the same. See §4 for the bracketing-variant framing.


Because every Internet Information Services application-pool identity is granted the privilege by Windows default [@itm4n-printspoofer]. The grant exists for legitimate request-scoped impersonation -- it is the mechanism IIS uses to &quot;act as&quot; a calling user during authenticated request handling. The same default grant is the entire vulnerability surface for the Potato family. The Microsoft Security Servicing Criteria document treats the resulting `SeImpersonate`-to-SYSTEM transition as a safety boundary rather than a security boundary [@msrc-servicing-criteria; @troopers24].


No. CVE-2021-26414 hardening raises the *authentication* bar for Distributed COM clients to `RPC_C_AUTHN_LEVEL_PKT_INTEGRITY` and was fully enforced on March 14, 2023 in Phase 3 of the rollout [@ms-kb5004442]. It does not declare Distributed COM activation a security boundary. The proof is that GodPotato, which exploits an RPCSS OXID-handling defect rather than the activation authentication level, survives all three phases of the rollout and remains the practitioner default in 2026 [@beichendream-god].


Open question, with a defensible reading. LocalPotato attacks the local-user-to-local-user NTLM authentication context handle, which *is* on the servicing-criteria boundary list [@decoder-localpotato; @msrc-servicing-criteria]. RemotePotato0 attacks the `SeImpersonate`-to-SYSTEM transition via cross-session Distributed COM activation, which is *not* on the list and was therefore deemed an extension of the existing carve-out [@sentinellabs-relaying; @troopers24]. The two boundaries (local NTLM authentication context vs cross-session Distributed COM activation) are not equivalent in Microsoft&apos;s published servicing position.


Yes, on every patched Windows 11 / Server 2025 build as of this writing [@beichendream-god]. The RPCSS OXID-handling defect that GodPotato weaponises survives all three CVE-2021-26414 hardening phases [@ms-kb5004442; @compass-three-headed]. Microsoft has not assigned a CVE to the underlying defect, consistent with the servicing-criteria reading. Operationally, the only thing that changes between releases is the binary signature -- EDR vendors signature the public Apache-2.0 binary by hash, and operators recompile from source with cosmetic changes to evade [@beichendream-god].


Does not exist as of May 2026. If a 2025-2026 variant appears under an unfamiliar name -- French or otherwise -- verify against the canonical sources before citing: `decoder.cloud` for the Pierini and Cocomazzi line, `github.com/antonioCoco/*` for the Cocomazzi-authored repositories, `github.com/BeichenDream/*` for the BeichenDream line, and `itm4n.github.io` for the PrintSpoofer / SweetPotato line [@decoder-silverpotato; @antonio-rogue; @beichendream-god; @itm4n-printspoofer]. The Troopers 24 retrospective is the community-canonical lineage list as of the most recent consolidated talk [@troopers24].


Informally, no. The primitive `ImpersonateNamedPipeClient` is in the legitimate hot path of nearly every Windows service [@ms-impersonate-api]. Per-variant signatures exist for the public binaries (GodPotato, PrintSpoofer, JuicyPotato), and ETW providers `Microsoft-Windows-COM` and `Microsoft-Windows-RPC` surface the activation-and-RPC events that the Distributed COM variants generate. A class-generalising detection rule has not been published as of May 2026, and the false-positive rate on legitimate Windows services is high for any rule that fires on `ImpersonateNamedPipeClient` alone [@troopers24].

&lt;h2&gt;13. The Architectural Decision&lt;/h2&gt;
&lt;p&gt;Return to the opening scene. The same Internet Information Services web shell, the same &lt;code&gt;GodPotato.exe&lt;/code&gt;, the same ten-second SYSTEM shell. The reader now knows this is not a zero-day. It has been a single-binary operation for the better part of a decade. Every step is documented Win32 behaviour. And every step is permitted by Microsoft&apos;s published servicing position [@beichendream-god; @msrc-servicing-criteria; @troopers24].&lt;/p&gt;
&lt;p&gt;Nine years of named-variant disclosures. Eleven named variants. Three Microsoft hardening waves. Two CVEs -- LocalPotato in January 2023, FakePotato in July 2024 [@nvd-cve-2023-21746; @nvd-cve-2024-38100]. One &quot;Won&apos;t Fix&quot; decision on a working Domain Admin escalation in April 2021 [@sentinellabs-relaying]. Zero declarations of &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; or Distributed COM activation as a security boundary [@troopers24; @msrc-servicing-criteria]. The MSRC Windows Security Servicing Criteria document, the one whose boundary definition fetches in static HTML and whose enumeration table is JavaScript-rendered, is the through-line [@msrc-servicing-criteria]. Pierini and Cocomazzi say it bluntly in the Troopers 24 abstract:&lt;/p&gt;

Microsoft does not consider WSH a security boundary but rather a safety boundary; for this reason, many Potato exploits work (and have been working) on fully updated Windows systems. -- Pierini and Cocomazzi, Troopers 24 abstract [@troopers24]
&lt;p&gt;Microsoft will never fix the Potato class because fixing it requires declaring Distributed COM activation a security boundary, and they have spent twenty-five years insisting it is not. What would change that? A major-version Windows release that explicitly revokes the default &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; grant from service accounts -- a compatibility-breaking change that breaks IIS, SQL Server, BITS, the Spooler, and most third-party services that depend on the legitimate impersonation contract. No such release is on the public roadmap as of May 2026 [@msrc-servicing-criteria; @ms-kb5004442; @beichendream-god].&lt;/p&gt;
&lt;p&gt;Until then, the family is alive, and the ten-second SYSTEM shell is the default outcome of any IIS or service-account foothold on a fully-patched Windows machine. That is not the unintended consequence of an unpatched bug. That is the intended consequence of a published architectural decision.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Potato family is not a stack of bugs Microsoft is slowly working through. It is the long-running consequence of a published architectural decision: that the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;-to-SYSTEM transition is a safety boundary, not a security boundary. Eleven variants over nine years of named-variant disclosures (HotPotato January 2016 -&amp;gt; FakePotato August 2024) are the empirical proof of how stable that decision is [@troopers24; @msrc-servicing-criteria].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The following retention block summarises the six key terms above. Citations for each definition live in §2.1, §2.2, §6.5, §6.1, §3, and §2 of the body respectively (the StudyGuide MDX wrapper does not render &lt;code&gt;@ref-id&lt;/code&gt; links inline).&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;potato-family-decade-ntlm-reflection&quot; keyTerms={[
  { term: &quot;SeImpersonatePrivilege&quot;, definition: &quot;Windows user-rights assignment that permits a thread to substitute another user&apos;s security context for its own; granted by default to LOCAL SERVICE, NETWORK SERVICE, and most service accounts (see §2.1 for full citation).&quot; },
  { term: &quot;ImpersonateNamedPipeClient&quot;, definition: &quot;Win32 API that lets a named-pipe server adopt the security context of whoever just connected to the pipe; documented today as supported since Windows XP for clients and Windows Server 2003 for servers (see §2.2 for full citation).&quot; },
  { term: &quot;OXID resolver&quot;, definition: &quot;RPCSS subsystem that resolves Object Exporter Identifiers during DCOM activation; hard-coded to 127.0.0.1:135 in Windows 10 1809 / Server 2019 to mitigate JuicyPotato (see §6.1).&quot; },
  { term: &quot;RPC_C_AUTHN_LEVEL_PKT_INTEGRITY&quot;, definition: &quot;RPC authentication-level constant requiring per-packet integrity signing; the minimum CVE-2021-26414 enforces on DCOM activation in Phase 3 (March 14, 2023) (see §6.5).&quot; },
  { term: &quot;NTLM reflection&quot;, definition: &quot;Special case of NTLM relay where the authentication is forwarded back to the originating machine, typically across protocols (HTTP to SMB, DCOM to local RPC) (see §3).&quot; },
  { term: &quot;Security boundary vs safety boundary&quot;, definition: &quot;MSRC servicing-criteria distinction: security boundaries get CVEs and security updates; safety boundaries are patched when convenient but carry no service-level guarantee (see §2).&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>privilege-escalation</category><category>ntlm-relay</category><category>dcom</category><category>msrc</category><category>red-team</category><category>post-exploitation</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>The Connection That Refused to Downgrade: Twenty-Five Years of SMB Cryptography, Finally Default-On</title><link>https://paragmali.com/blog/the-connection-that-refused-to-downgrade-twenty-five-years-o/</link><guid isPermaLink="true">https://paragmali.com/blog/the-connection-that-refused-to-downgrade-twenty-five-years-o/</guid><description>How SMB 3.1.1 pre-authentication integrity, AES-256-GCM, and SMB-over-QUIC closed a 25-year attack tradition, and which attacks still survive in 2026.</description><pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate><content:encoded>
**SMB 3.1.1 closed the 25-year-old negotiate-downgrade attack in 2015, but the defaults did not catch up until October 2024.** Pre-authentication integrity hashes every byte of NEGOTIATE and SESSION_SETUP into the SP 800-108 KDF salt, so any tampering produces divergent session keys rather than detectable mismatches. Windows 11 24H2 and Server 2025 finally make SMB signing required by default; encryption is now mandate-able but remains opt-in. The attacks that still work (PetitPotam) route around SMB entirely.
&lt;h2&gt;1. Three Failures in a Coffee Shop&lt;/h2&gt;
&lt;p&gt;A laptop opens its first SMB connection to a corporate file share over the wifi of a coffee shop. An attacker on the same network, holding the same family of relay tooling that Sir Dystic first demonstrated on &lt;strong&gt;March 31, 2001 at @lanta.con in Atlanta&lt;/strong&gt; [@smbrelay-cdc], watches three packets go by: a NEGOTIATE Request, a NEGOTIATE Response, and an authenticated SESSION_SETUP that finishes with a signed READ.&lt;/p&gt;
&lt;p&gt;She tries to relay the credentials to a neighbouring server. She tries to strip the signing-required bit from the NEGOTIATE Response. She tries to inject ciphertext she captured from a previous session of the same user.&lt;/p&gt;
&lt;p&gt;All three attempts fail. None of them touch the contents of the file.&lt;/p&gt;
&lt;p&gt;That outcome is the 2026 default behaviour of a Windows 11 24H2 client talking to a Windows Server 2025 file server [@pyle-techcom-4226591][@smb-security-hardening]. And it is the punch line of a story that took twenty-five years to land.&lt;/p&gt;

This topic was discussed on March 31, 2001 at @lanta.con in Atlanta, Georgia. -- Sir Dystic, cDc disclosure page for SMBRelay [@smbrelay-cdc]
&lt;p&gt;Sir Dystic was the cDc handle of the researcher who shipped the first practical SMB relay tool.&quot;Sir Dystic&quot; is a cult of the Dead Cow pseudonym. The cDc primary disclosure page names only the handle; a legal name attributed in secondary press is not load-bearing for this article, and the primary citation stays with the pseudonym [@smbrelay-cdc]. His attack relayed a client&apos;s &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; challenge response, captured on the wire, into a fresh SMB session against another host where that user already had credentials.&lt;/p&gt;
&lt;p&gt;The technique generalised, and &quot;SMB relay&quot; became a generic term for an attack family that has, over the intervening years, eaten domain controllers, file shares, and Active Directory Certificate Services enrollment endpoints.&lt;/p&gt;
&lt;p&gt;This article walks the twenty-five-year arc of cryptographic responses to that attack family: how each retrofit before 2015 left a load-bearing weakness in the NEGOTIATE handshake; how SMB 3.1.1 closed that weakness with a mechanism that is usually misremembered; how SMB-over-QUIC arrived in 2021 as a parallel transport; how the October 2024 default-on flip in Windows 11 24H2 finally made signing mandatory on every share, not just SYSVOL and NETLOGON [@smb-security-hardening]; and what attacks the SMB team designed against still work in 2026, by routing around SMB entirely.&lt;/p&gt;
&lt;p&gt;There will be three aha moments. The first arrives at the end of section 3: every defence before 2015 was applied after-the-fact to a message an attacker already controlled. The second arrives in section 4: pre-authentication integrity is not a signed negotiate, it is a hash chain that becomes a key-derivation salt. The third arrives in section 6: SMB is now cryptographically sufficient at the wire layer, and the attacks that still matter coerce SMB and relay the authentication somewhere else.&lt;/p&gt;
&lt;p&gt;To see why the attacker&apos;s toolkit failed in 2026, and why the same toolkit worked everywhere from 2001 to 2023, we have to start in 1983.&lt;/p&gt;
&lt;h2&gt;2. The Cleartext Era and the Birth of the Relay Class&lt;/h2&gt;
&lt;p&gt;Barry Feigenbaum designed SMB at IBM Boca Raton in 1983 [@ms-cifs-landing] as a way to make a PC&apos;s open-file table look like it lived on a server. It ran on a single LAN segment, behind a desk, in a room where the only adversary was someone who walked in the door. There was no notion of an attacker on the wire because there was no wire to attack: the protocol predated TCP/IP&apos;s commercial reach by a decade.&lt;/p&gt;
&lt;p&gt;Microsoft adopted the design for LAN Manager in 1987 and carried it into Windows NT in 1993 [@ms-cifs-landing]. Paul Leach&apos;s 1996-1997 IETF draft, eventually known as &lt;code&gt;draft-leach-cifs-v1-spec-02&lt;/code&gt; [@leach-cifs-draft], rebranded the protocol as the &lt;strong&gt;Common Internet File System&lt;/strong&gt; and tried to standardise the dialect at IETF.&lt;/p&gt;
&lt;p&gt;The standardisation effort stalled, but the brand stuck for a decade. The normative SMB1 / CIFS reference today is the Microsoft &lt;code&gt;[MS-CIFS]&lt;/code&gt; open specification [@ms-cifs-landing], which still records the SMB1 dialect strings &lt;code&gt;PC NETWORK PROGRAM 1.0&lt;/code&gt;, &lt;code&gt;MICROSOFT NETWORKS 1.03&lt;/code&gt;, &lt;code&gt;LANMAN1.0&lt;/code&gt;, and &lt;code&gt;NT LM 0.12&lt;/code&gt; that the protocol negotiates at hello.&lt;/p&gt;

Paul Leach (Microsoft) circulated a CIFS Internet Draft at the IETF in 1996-1997 [@leach-cifs-draft], hoping to take SMB through the standards-track process. Microsoft kept revising the spec internally; the IETF draft never advanced to RFC. The &quot;CIFS&quot; name persisted as marketing for SMB1 well after Microsoft had moved on to SMB 2.0 in 2006, which is why product documentation continued to refer to &quot;CIFS shares&quot; through the 2010s even though the wire protocol had changed twice. Today the only meaningful use of the word is as a label for the SMB1 wire dialect family, normatively documented in `[MS-CIFS]` [@ms-cifs-landing].
&lt;p&gt;In parallel, Andrew Tridgell at the Australian National University started reverse-engineering the SMB wire protocol so he could mount a DEC Pathworks server from his Linux box. His first tentative code appeared in early 1992 [@samba-10years]; that codebase grew into Samba, which is the canonical open-source SMB server in 2026 and ships every algorithm matrix the Microsoft client expects to negotiate.&lt;/p&gt;
&lt;p&gt;Microsoft added SMB1 to the Windows Server 2012 R2 deprecation list in &lt;strong&gt;June 2013&lt;/strong&gt;, in advance of the Server 2012 R2 October 2013 release, per Jose Barreto&apos;s 2015 TechNet post (preserved via the Wayback Machine) [@barreto-archive]. &quot;Deprecation&quot; meant the feature was marked for potential removal in subsequent releases, not yet removed. The actual default-off step came with Windows 10 1709 in the Fall Creators Update and Windows Server 2019 [@smb-interception-defense].&lt;/p&gt;

A family of attacks that captures a client&apos;s authentication exchange on the wire and replays it, in real time, into a fresh authenticated session against a different target where the same user already has access. The defining property is that the attacker never learns the plaintext credential; she only needs to ferry the cryptographic responses between two sockets. Originally demonstrated by Sir Dystic for SMB on March 31, 2001 [@smbrelay-cdc], the class generalised to NTLM-over-HTTP, NTLM-over-LDAP, NTLM-over-DCOM, and eventually to cross-protocol variants like PetitPotam that coerce SMB authentication and relay it to ADCS Web Enrollment over HTTPS.
&lt;h3&gt;The 2001 disclosure&lt;/h3&gt;
&lt;p&gt;Sir Dystic&apos;s SMBRelay was a small Windows binary that ran a fake SMB server, accepted a connection from a victim, captured the NTLM challenge-response, and immediately forwarded that response to a real SMB server where the victim had access. The technique worked because SMB1 signing was opt-in by default; on a typical Windows network in 2001, signing was negotiated for connections to SYSVOL and NETLOGON on a domain controller and almost nowhere else. Microsoft&apos;s response at the time was that signing existed and could be turned on. Technically correct; politically untenable.&lt;/p&gt;
&lt;p&gt;The &quot;almost nowhere else&quot; matters. SMB1 did support signing, and the algorithm was a truncated MD5 of the packet concatenated with the session key, mediated by a sequence number, per &lt;code&gt;[MS-CIFS]&lt;/code&gt; §3.1.4.1 [@ms-cifs-landing]. It was not an HMAC, and it was not a strong MAC by 2001 cryptographic standards. But that was not the load-bearing weakness. The load-bearing weakness was that the &lt;strong&gt;signing-required bit travelled in the NEGOTIATE Response itself&lt;/strong&gt;, before any session key existed to protect it. An attacker who could rewrite NEGOTIATE could strip the bit; signing was then mutually disabled and the session continued unsigned.&lt;/p&gt;
&lt;p&gt;The cDc primary page dates the disclosure to &lt;em&gt;March 31, 2001&lt;/em&gt;. The Wikipedia article on SMBRelay says March 21, 2001, and a chain of secondary press has repeated the March 21 date. The primary disclosure page is the dispositive source; the article uses March 31 [@smbrelay-cdc].&lt;/p&gt;
&lt;h3&gt;The 2008 patch&lt;/h3&gt;
&lt;p&gt;Seven years and eight months later, on &lt;strong&gt;November 11, 2008&lt;/strong&gt;, Microsoft shipped MS08-068, which addressed CVE-2008-4037, the same-host SMB credential reflection vulnerability [@ms08-068][@nvd-cve-2008-4037]. The fix changed how SMB authentication replies were validated so that an attacker could no longer reflect a client&apos;s credentials back to the &lt;em&gt;same host&lt;/em&gt; that initiated the authentication.&lt;/p&gt;
&lt;p&gt;That closed one specific variant of Sir Dystic&apos;s attack. It did not close the cross-host case, where the attacker forwards credentials to a different SMB server that the victim has access to. That case was the architectural shape that future relay tooling like Impacket&apos;s &lt;code&gt;smbrelayx&lt;/code&gt; exploited for years.&lt;/p&gt;
&lt;p&gt;What MS08-068 demonstrated, more than anything else, was the cost of fixing a protocol with a single-issue patch when the load-bearing weakness was structural. The 2001 disclosure named the class. The 2008 patch closed one variant. The next defence was not another bulletin, and it was not going to be another patch. It was a complete redesign of the SMB header model and a new dialect family.&lt;/p&gt;

gantt
    title SMB cryptographic generations
    dateFormat YYYY
    axisFormat %Y
    section SMB1
    Cleartext on the LAN          :1983, 1996
    MD5 signing (opt-in)          :1997, 2006
    section SMB 2.x
    HMAC-SHA-256 signing          :2006, 2012
    section SMB 3.x
    AES-CMAC and AES-128-CCM      :2012, 2013
    Secure Negotiate FSCTL        :2013, 2015
    section SMB 3.1.1
    Pre-auth integrity, AES-128-GCM :2015, 2021
    AES-256 ciphers, AES-GMAC, SMB-over-QUIC :2021, 2024
    Signing required by default   :2024, 2026
&lt;h2&gt;3. Five Retrofits Before the Real Fix&lt;/h2&gt;
&lt;p&gt;Between 2006 and 2013, Microsoft tried four different cryptographic primitives and one post-hoc validation message. None of them closed the negotiate-downgrade primitive that SMBRelay opened.&lt;/p&gt;
&lt;h3&gt;SMB 2.0 (November 8, 2006) [@ms-smb2-versioning]&lt;/h3&gt;
&lt;p&gt;Windows Vista RTM shipped a redesigned SMB header. The protocol still carried a sequence number, but the per-packet signature now came from HMAC-SHA-256 keyed by the session key derived from authentication, not from a truncated MD5 [@ms-smb2-versioning]. The new MAC closed all the trivial attacks on the signing algorithm itself.&lt;/p&gt;
&lt;p&gt;But signing was still opt-in: a typical Windows network ran it only between domain controllers and member servers, not between general clients and file shares. And the NEGOTIATE Response still travelled unsigned, so the signing-required bit was still strippable by an in-path attacker.&lt;/p&gt;

A keyed message authentication code, defined in RFC 2104 with SHA-256 as the underlying hash, that produces a 256-bit tag binding a message and a key. HMAC&apos;s security reduces to the pseudorandomness of the underlying hash compression function; SHA-256 with HMAC has no known practical forgery for any key. SMB 2.0 and later use HMAC-SHA-256 to sign each SMB header when AES-CMAC and AES-GMAC are not negotiated [@ms-smb2-versioning].
&lt;h3&gt;SMB 2.1 (October 22, 2009) [@ms-smb2-versioning]&lt;/h3&gt;
&lt;p&gt;Windows 7 and Server 2008 R2 shipped SMB 2.1, dialect &lt;code&gt;0x0210&lt;/code&gt; [@ms-smb2-versioning]. The dialect introduced opportunistic locks, branch caching, and large MTUs. The cryptographic primitives did not change: HMAC-SHA-256 signing, still opt-in.&lt;/p&gt;
&lt;h3&gt;SMB 3.0 (October 26, 2012) [@ms-smb2-versioning]&lt;/h3&gt;
&lt;p&gt;Windows 8 and Server 2012 shipped the first cryptographically modern SMB dialect, &lt;code&gt;0x0300&lt;/code&gt; [@ms-smb2-versioning]. It introduced three things at once:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AES-CMAC signing&lt;/strong&gt;, the NIST SP 800-38B [@nist-sp-800-38b] block-cipher MAC, swapping the SHA-256 compression function for an AES-128 cipher operation that runs at hardware speed on chips with AES-NI. The standard identifier in the spec is &quot;AES-CMAC&quot;. Cryptographers will sometimes recognise the same construction as OMAC1 from Iwata and Kurosawa, 2003.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AES-128-CCM encryption&lt;/strong&gt;, the two-pass AEAD construction from NIST SP 800-38C [@nist-sp-800-38c], which produces an authenticated ciphertext that an attacker cannot tamper with without invalidating the tag.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A proper SP 800-108 key hierarchy.&lt;/strong&gt; Every per-session signing key, encryption key, and decryption key derives from a session-level secret via the counter-mode HMAC-SHA-256 KDF in NIST SP 800-108 [@nist-sp-800-108r1].&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This was a real cryptographic upgrade. But it did not close the negotiate-downgrade primitive. An attacker on the wire could still rewrite the NEGOTIATE Response to remove the &lt;code&gt;SMB2_GLOBAL_CAP_ENCRYPTION&lt;/code&gt; capability bit and the &lt;code&gt;SMB2_NEGOTIATE_SIGNING_REQUIRED&lt;/code&gt; bit; the client and server would then agree on a session that was neither signed nor encrypted, and the cryptographic primitives the attacker was trying to defeat were never invoked at all.&lt;/p&gt;

A block-cipher message authentication code standardised in NIST SP 800-38B in 2005 [@nist-sp-800-38b]. CMAC iterates AES in CBC mode over the message and applies a final subkey to the last block. The construction tolerates messages of any length, including the empty message, and has a security bound that matches the generic upper bound for any deterministic MAC built from a pseudorandom permutation. SMB 3.0 through 3.1.1 use AES-CMAC as the default signing algorithm; AES-GMAC, introduced as a negotiable alternative in 2021, replaces it on hardware where Galois-field multiplication is faster than AES-CBC.

Authenticated Encryption with Associated Data. A class of symmetric encryption scheme that simultaneously provides confidentiality of the message body and integrity of both the body and a separate &quot;associated data&quot; header. AES-CCM (SP 800-38C) [@nist-sp-800-38c] and AES-GCM (SP 800-38D) [@nist-sp-800-38d] are the two AEADs SMB 3.x uses. AEADs replace the older &quot;encrypt-then-MAC&quot; or &quot;MAC-then-encrypt&quot; compositions, which historically were a rich source of cryptographic mistakes.
&lt;p&gt;NIST identifies AES-CMAC by the cipher and mode strings; the construction is mathematically equivalent to Tetsu Iwata and Kaoru Kurosawa&apos;s OMAC1 from 2003. SP 800-38B notes the lineage, attributing the design to Iwata-Kurosawa with subsequent refinements by Black-Rogaway [@nist-sp-800-38b].&lt;/p&gt;
&lt;h3&gt;SMB 3.0.2 Secure Negotiate (October 18, 2013) [@ms-smb2-versioning]&lt;/h3&gt;
&lt;p&gt;Windows 8.1 and Server 2012 R2 shipped dialect &lt;code&gt;0x0302&lt;/code&gt; with a post-hoc validation message: &lt;code&gt;FSCTL_VALIDATE_NEGOTIATE_INFO&lt;/code&gt;. The idea was that after authentication, the client would send the server its view of what NEGOTIATE looked like, signed by the freshly-derived session key. The server compared the client&apos;s view against its own, and if they disagreed, the connection terminated. This was the first protocol-level attempt to detect negotiate-downgrade in SMB. It is also, retrospectively, the most instructive failure.&lt;/p&gt;
&lt;p&gt;Secure Negotiate had five structural limits, and each of them mattered:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;It was post-hoc, not preventive.&lt;/strong&gt; The session key was already derived. The encryption capability was already mutually decided. If an attacker had stripped encryption, you were going to &lt;em&gt;detect&lt;/em&gt; that you were in a degraded session and tear it down. You were not going to prevent the degradation in the first place.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The FSCTL was skippable.&lt;/strong&gt; A pre-3.0 client did not send &lt;code&gt;FSCTL_VALIDATE_NEGOTIATE_INFO&lt;/code&gt;. An attacker who downgraded a 3.0.2 client to 2.0 simply got a session that never asked the question.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It validated capability bits, not every byte of NEGOTIATE.&lt;/strong&gt; The FSCTL message contained a fixed structure with specific fields. Tampering that did not touch those specific fields could survive validation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It inherited the dialect-monopoly extensibility flaw.&lt;/strong&gt; Adding a new capability meant adding a new bit to the capability bitmap, which the Secure Negotiate FSCTL would also have to learn about. The structure was not future-proof.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It was trust-on-second-use, not first-use.&lt;/strong&gt; The signed FSCTL validated &lt;em&gt;that this session&apos;s NEGOTIATE was not tampered with&lt;/em&gt; only after authentication had completed. The first message of authentication itself, where the attacker could rewrite signing requirements, was still vulnerable.&lt;/li&gt;
&lt;/ol&gt;

An attack on a protocol with an in-band cryptographic capability negotiation in which an in-path attacker tampers with the negotiation messages so that the two endpoints agree on a weaker algorithm, or no algorithm at all. SMB-relay-class attacks before 2015 universally relied on negotiate-downgrade: the attacker stripped the `SMB2_NEGOTIATE_SIGNING_REQUIRED` bit from the NEGOTIATE Response, and the resulting session was unsigned and forwardable. The structural defence against negotiate-downgrade is to bind every byte of the negotiation transcript into the key-derivation function, which is what TLS 1.2 Finished and SMB 3.1.1 pre-authentication integrity both do, by different mechanics.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every SMB defence before 2015 was a tag applied after-the-fact to a message an attacker already controlled. Signing was opt-in. The signing-required bit was strippable during unsigned NEGOTIATE. Secure Negotiate detected tampering only after the attacker had already chosen what to tamper with. The shape of the fix is forced once you state the flaw this way: the negotiation has to bind into the key-derivation function itself, so that tampering does not produce a detectable mismatch -- it produces session keys that simply do not work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Five generations, one column&lt;/h3&gt;
&lt;p&gt;The shape of the failure is easiest to see in a table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Signing&lt;/th&gt;
&lt;th&gt;Encryption&lt;/th&gt;
&lt;th&gt;NEGOTIATE protection&lt;/th&gt;
&lt;th&gt;Why it failed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SMB1 cleartext&lt;/td&gt;
&lt;td&gt;1983-1996&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;No cryptography at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB1 + MD5&lt;/td&gt;
&lt;td&gt;1997-2006&lt;/td&gt;
&lt;td&gt;Opt-in MD5 truncated to 8 bytes&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Signing-required bit strippable in unsigned NEGOTIATE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB 2.0 / 2.1&lt;/td&gt;
&lt;td&gt;2006-2012&lt;/td&gt;
&lt;td&gt;HMAC-SHA-256&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Same NEGOTIATE-strip primitive, stronger MAC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB 3.0&lt;/td&gt;
&lt;td&gt;2012-2013&lt;/td&gt;
&lt;td&gt;AES-CMAC&lt;/td&gt;
&lt;td&gt;AES-128-CCM&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Strip the &lt;code&gt;SMB2_GLOBAL_CAP_ENCRYPTION&lt;/code&gt; bit and CCM never runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB 3.0.2&lt;/td&gt;
&lt;td&gt;2013-2015&lt;/td&gt;
&lt;td&gt;AES-CMAC&lt;/td&gt;
&lt;td&gt;AES-128-CCM&lt;/td&gt;
&lt;td&gt;Post-hoc FSCTL&lt;/td&gt;
&lt;td&gt;Detection, not prevention; skippable by older clients&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Read the &lt;strong&gt;NEGOTIATE protection&lt;/strong&gt; column top to bottom. &lt;em&gt;None / None / None / None / Post-hoc FSCTL.&lt;/em&gt; Twenty-five years of cryptographic work without a single defence that bound the negotiation transcript to the eventual session key. Then, in 2015, buried in the unremarkable &lt;code&gt;.1&lt;/code&gt; of a &lt;code&gt;.1&lt;/code&gt; dialect bump, the SMB team finally fixed the load-bearing weakness.&lt;/p&gt;

sequenceDiagram
    participant C as Client
    participant M as In-path attacker
    participant S as Server
    C-&amp;gt;&amp;gt;M: NEGOTIATE Request, signing required, ciphers AES-128-CCM
    M-&amp;gt;&amp;gt;S: NEGOTIATE Request, signing required, ciphers AES-128-CCM
    S-&amp;gt;&amp;gt;M: NEGOTIATE Response, signing required, encryption capability set
    M-&amp;gt;&amp;gt;C: NEGOTIATE Response with signing-required bit cleared, encryption capability removed
    Note over C,S: Client and server now agree on an unsigned, unencrypted session
    C-&amp;gt;&amp;gt;M: SESSION_SETUP Request, no signature
    M-&amp;gt;&amp;gt;S: Relayed SESSION_SETUP Request
    Note over M,S: Attacker controls the cleartext channel
&lt;h2&gt;4. The Hash Chain Becomes the Salt&lt;/h2&gt;
&lt;p&gt;On &lt;strong&gt;July 29, 2015&lt;/strong&gt;, Windows 10 RTM (build 10240, version 1507) shipped a protocol that no relay tool released since has been able to downgrade [@win10-release-info]. The fix was not what most readers remember. It was much stranger and much cleaner.&lt;/p&gt;
&lt;p&gt;The dialect was &lt;code&gt;0x0311&lt;/code&gt;, &quot;SMB 3.1.1&quot; [@ms-smb2-versioning]. Greg Kramer and Dan Lovinger of the Microsoft SMB team presented the design at the SNIA Storage Developer Conference that September [@kramer-lovinger-sdc2015]. The deck contains the single most-quoted sentence in modern SMB cryptography:&lt;/p&gt;

Preauthentication Integrity ... Provides end-to-end, dialect agnostic protection. Session&apos;s secret keys derived from hash of the preauthentication messages. -- Greg Kramer and Dan Lovinger, SNIA SDC 2015 [@kramer-lovinger-sdc2015]
&lt;p&gt;Most secondary references to the SDC 2015 deck cite &quot;Greg Kramer&quot; only. The title slide lists two authors: Greg Kramer, Principal Software Engineer, and Dan Lovinger, Principal Software Engineer, both at Microsoft. The 2015 design has two names on it [@kramer-lovinger-sdc2015].&lt;/p&gt;
&lt;p&gt;The misremembered framing of SMB 3.1.1 pre-authentication integrity is that &quot;negotiate contexts are signed by the eventual session key.&quot; That is not what happens. The actual mechanism is more elegant and structurally stronger.&lt;/p&gt;
&lt;h3&gt;The four updates of the hash chain&lt;/h3&gt;
&lt;p&gt;SMB 3.1.1 defines a per-connection variable called &lt;code&gt;PreauthIntegrityHashValue&lt;/code&gt;, initialised to 64 zero bytes [@ms-smb2-pdf]. Across the four messages of the pre-authentication phase, both client and server update it with the same rule:&lt;/p&gt;
&lt;p&gt;$$H_i = \mathrm{SHA{-}512}(H_{i-1} \mathbin{|} M_i)$$&lt;/p&gt;
&lt;p&gt;The four messages are NEGOTIATE Request, NEGOTIATE Response, SESSION_SETUP Request, and SESSION_SETUP Response. After all four are processed, the running hash &lt;code&gt;H_4&lt;/code&gt; contains a cryptographic commitment to every byte that crossed the wire during pre-authentication.&lt;/p&gt;
&lt;p&gt;This commitment has no value if it stays a local variable. The structural move is in the next step. SMB 3.1.1 uses the NIST SP 800-108 counter-mode KDF [@nist-sp-800-108r1] to derive every per-session key from the authentication-protocol session secret (the NTLM &lt;code&gt;ExportedSessionKey&lt;/code&gt; or the &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos&lt;/a&gt; service-ticket session key). The KDF takes two arguments alongside the secret: a &lt;code&gt;Label&lt;/code&gt; identifying the role of the derived key, and a &lt;code&gt;Context&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The &lt;code&gt;Context&lt;/code&gt; argument is &lt;code&gt;PreauthIntegrityHashValue&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That is the whole trick. The hash chain enters the key-derivation function as salt. It does not protect the negotiation by tagging it; it protects the negotiation by being part of the input to the function that produces the session keys.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Pre-authentication integrity is not a signed negotiate. It is a SHA-512 hash chain over the four pre-authentication messages whose final value becomes the &lt;code&gt;Context&lt;/code&gt; argument to the SP 800-108 KDF that derives every per-session key. Tampering does not get &lt;em&gt;detected&lt;/em&gt;. Tampering causes the two sides to compute different keys, and the first signed message after SESSION_SETUP simply fails to verify on both ends.&lt;/p&gt;
&lt;/blockquote&gt;

The SMB 3.1.1 mechanism that binds every byte of the four pre-authentication messages (NEGOTIATE Request and Response, SESSION_SETUP Request and Response) into the salt input of the SP 800-108 key-derivation function that derives all per-session SMB keys [@kramer-lovinger-sdc2015][@ms-smb2-pdf]. The bind is constructed by iterating SHA-512 over each pre-authentication message in turn. The mechanism is mandatory in dialect 0x0311; there is no policy switch to disable it.

A family of key-derivation functions standardised by NIST in Special Publication 800-108 [@nist-sp-800-108r1], parameterised by a pseudorandom function (HMAC, KMAC, or CMAC) and a mode (counter, feedback, double-pipeline). SMB 3.x uses CTR-HMAC-SHA-256. The function takes a secret key, a `Label`, a `Context`, and a desired output length, and returns the requested number of bits as a deterministic, distinguishable derivation of the key. In SMB 3.1.1, the `Context` argument is the pre-authentication hash chain; the `Label` is one of four constant strings naming the role of the derived key.
&lt;h3&gt;The four key labels&lt;/h3&gt;
&lt;p&gt;The four per-session keys SMB 3.1.1 derives are tagged with constant &lt;code&gt;Label&lt;/code&gt; strings, lifted directly from [MS-SMB2] §3.2.5.3.1 [@ms-smb2-pdf]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&quot;SMBSigningKey&quot;&lt;/code&gt; -- the key used for the per-packet AES-CMAC or AES-GMAC signature.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;SMBAppKey&quot;&lt;/code&gt; -- the application-layer key that some named pipes can use to derive sub-keys.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;SMBC2SCipherKey&quot;&lt;/code&gt; -- the client-to-server AES encryption key, fed to AES-CCM or AES-GCM.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;SMBS2CCipherKey&quot;&lt;/code&gt; -- the server-to-client encryption key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each label is passed as the SP 800-108 &lt;code&gt;Label&lt;/code&gt; argument; the same &lt;code&gt;PreauthIntegrityHashValue&lt;/code&gt; is passed as the &lt;code&gt;Context&lt;/code&gt; argument. Different labels produce different keys from the same secret and the same salt; that is what makes role separation work without four separate hash chains.&lt;/p&gt;
&lt;p&gt;The AES-256 ciphers in SMB 3.1.1 consume &lt;code&gt;Session.FullSessionKey&lt;/code&gt; rather than the truncated 16-byte &lt;code&gt;Session.SessionKey&lt;/code&gt; that AES-128 ciphers use [@ms-smb2-pdf]. This is the structural reason an AES-256 SMB session is cryptographically 256-bit-secure rather than capped at 128. The detail matters for anyone evaluating SMB against CNSA 2.0 requirements: the implementation does the right thing, but only because the specification said so explicitly.&lt;/p&gt;
&lt;h3&gt;Why this is stronger than Secure Negotiate&lt;/h3&gt;
&lt;p&gt;Place SMB 3.0.2 Secure Negotiate and SMB 3.1.1 pre-authentication integrity side by side:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;Secure Negotiate (SMB 3.0.2)&lt;/th&gt;
&lt;th&gt;Pre-auth integrity (SMB 3.1.1)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Coverage&lt;/td&gt;
&lt;td&gt;Dialect index + capability bitmap&lt;/td&gt;
&lt;td&gt;Every byte of all four pre-auth messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When&lt;/td&gt;
&lt;td&gt;Post-hoc, after session key derived&lt;/td&gt;
&lt;td&gt;At the moment of key derivation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Detection: signed FSCTL mismatches&lt;/td&gt;
&lt;td&gt;Implicit: derived keys diverge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disable switch&lt;/td&gt;
&lt;td&gt;Skipped by pre-3.0 clients&lt;/td&gt;
&lt;td&gt;None; mandatory in 0x0311&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extensibility&lt;/td&gt;
&lt;td&gt;Hard-coded fields in FSCTL&lt;/td&gt;
&lt;td&gt;Hashes whatever bytes flow&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Secure Negotiate had to know &lt;em&gt;what&lt;/em&gt; it was protecting. Pre-auth integrity does not. The hash chain absorbs whatever bytes the dialect happens to carry: new negotiate contexts in future dialects, new capability bits, new ciphers. The mechanism does not need to be updated to learn about them, because it does not parse them. It hashes them.&lt;/p&gt;
&lt;h3&gt;The per-context salts&lt;/h3&gt;
&lt;p&gt;There is one more subtlety. The &lt;code&gt;SMB2_PREAUTH_INTEGRITY_CAPABILITIES&lt;/code&gt; negotiate context, defined in [MS-SMB2] §2.2.3.1.1, contains a 32-byte &lt;code&gt;Salt&lt;/code&gt; field that the client and server populate with fresh PRNG output for each connection [@ms-smb2-pdf]. The salt is hashed in along with everything else, so two different connections from the same client to the same server end up with different &lt;code&gt;PreauthIntegrityHashValue&lt;/code&gt; values even if every other byte of NEGOTIATE is identical.&lt;/p&gt;
&lt;p&gt;The point is not to add entropy to the session key (which already gets entropy from the authentication exchange) but to defeat any attempt at pre-image or rainbow-table attacks on the hash chain itself. SHA-512 is the only hash function currently negotiated, and its 256-bit collision resistance is the protocol floor for pre-authentication integrity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Microsoft Learn pages, the docs aggregators, and several widely-cited tertiary references describe SMB 3.1.1 pre-authentication integrity as &quot;signing the negotiate contexts with the session key.&quot; That description is wrong in a way that matters. There is no separate signed message validating the negotiation. The protection is constructed by feeding the hash of every pre-authentication message into the KDF that produces the session key. If you remember it as a signed negotiate, you will not understand why it is structurally stronger than Secure Negotiate. The mechanism is a &lt;em&gt;KDF binding&lt;/em&gt;, not a signature.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The empirical demonstration&lt;/h3&gt;
&lt;p&gt;The fastest way to feel the mechanism is to watch keys diverge in real time. The runnable code below produces two parallel SP 800-108-style derivations: an honest one where client and server hash the same four messages, and a tampered one where an in-path attacker flips a single byte in &lt;code&gt;NEGOTIATE Response&lt;/code&gt;. The two derivations produce identical keys in the honest case and visibly different keys in the tampered case.&lt;/p&gt;
&lt;p&gt;{`
const { createHmac, createHash } = require(&apos;crypto&apos;);&lt;/p&gt;
&lt;p&gt;function sha512(buf) {
  return createHash(&apos;sha512&apos;).update(buf).digest();
}&lt;/p&gt;
&lt;p&gt;function updateChain(H, message) {
  return sha512(Buffer.concat([H, Buffer.from(message)]));
}&lt;/p&gt;
&lt;p&gt;// SP 800-108 CTR-HMAC-SHA-256 in its simplest 32-byte-output form
function kdfSP108(secret, label, context, length) {
  const out = [];
  let i = 1;
  while (out.reduce((n, b) =&amp;gt; n + b.length, 0) &amp;lt; length) {
    const counter = Buffer.alloc(4);
    counter.writeUInt32BE(i++, 0);
    const block = createHmac(&apos;sha256&apos;, secret)
      .update(counter)
      .update(Buffer.from(label, &apos;utf8&apos;))
      .update(Buffer.from([0]))
      .update(context)
      .update(Buffer.from([0, 0, 1, 0]))
      .digest();
    out.push(block);
  }
  return Buffer.concat(out).subarray(0, length);
}&lt;/p&gt;
&lt;p&gt;const NEGOTIATE_REQ  = &apos;NEGOTIATE Request (client, signing required)&apos;;
const NEGOTIATE_RESP = &apos;NEGOTIATE Response (server, signing required)&apos;;
const SESSION_REQ    = &apos;SESSION_SETUP Request (NTLM challenge response)&apos;;
const SESSION_RESP   = &apos;SESSION_SETUP Response (success)&apos;;&lt;/p&gt;
&lt;p&gt;function derive(messages) {
  let H = Buffer.alloc(64, 0);
  for (const m of messages) H = updateChain(H, m);
  const authSecret = Buffer.from(&apos;AUTHENTICATION_PROTOCOL_SHARED_SECRET&apos;);
  return kdfSP108(authSecret, &apos;SMBSigningKey&apos;, H, 16).toString(&apos;hex&apos;);
}&lt;/p&gt;
&lt;p&gt;const honestClient = derive([NEGOTIATE_REQ, NEGOTIATE_RESP, SESSION_REQ, SESSION_RESP]);
const honestServer = derive([NEGOTIATE_REQ, NEGOTIATE_RESP, SESSION_REQ, SESSION_RESP]);
console.log(&apos;honest client:&apos;, honestClient);
console.log(&apos;honest server:&apos;, honestServer);
console.log(&apos;match:&apos;, honestClient === honestServer);&lt;/p&gt;
&lt;p&gt;// Attacker flips one byte in NEGOTIATE Response only on the client side
const tamperedClient = derive([NEGOTIATE_REQ, NEGOTIATE_RESP.replace(&apos;required&apos;, &apos;optional&apos;), SESSION_REQ, SESSION_RESP]);
const honestServer2  = derive([NEGOTIATE_REQ, NEGOTIATE_RESP, SESSION_REQ, SESSION_RESP]);
console.log(&apos;tampered client:&apos;, tamperedClient);
console.log(&apos;honest server:  &apos;, honestServer2);
console.log(&apos;match:&apos;, tamperedClient === honestServer2);
`}&lt;/p&gt;
&lt;p&gt;The honest pair of keys match. The tampered pair do not. The first signed READ that arrives at the server gets verified with a key that does not match the one the client used to sign it, and the server returns &lt;code&gt;STATUS_USER_SESSION_DELETED&lt;/code&gt;. The attacker has not been detected by a validation message; she has been routed around by a key-derivation function.&lt;/p&gt;

sequenceDiagram
    participant C as Client
    participant S as Server
    Note over C,S: H starts as 64 zero bytes on both sides
    C-&amp;gt;&amp;gt;S: NEGOTIATE Request
    Note over C,S: H = SHA-512(H, NEGOTIATE Request)
    S-&amp;gt;&amp;gt;C: NEGOTIATE Response
    Note over C,S: H = SHA-512(H, NEGOTIATE Response)
    C-&amp;gt;&amp;gt;S: SESSION_SETUP Request
    Note over C,S: H = SHA-512(H, SESSION_SETUP Request)
    S-&amp;gt;&amp;gt;C: SESSION_SETUP Response
    Note over C,S: H = SHA-512(H, SESSION_SETUP Response)
    Note over C,S: H enters SP 800-108 KDF as Context, derives SigningKey, CipherKey

flowchart LR
    A[Authentication secret] --&amp;gt; B[SP 800-108 CTR-HMAC-SHA-256 KDF]
    L[Label: SMBSigningKey or SMBC2SCipherKey or SMBS2CCipherKey or SMBAppKey] --&amp;gt; B
    H[Context: PreauthIntegrityHashValue] --&amp;gt; B
    B --&amp;gt; K1[SigningKey]
    B --&amp;gt; K2[Client-to-server CipherKey]
    B --&amp;gt; K3[Server-to-client CipherKey]
    B --&amp;gt; K4[AppKey]

A type-length-value carrier introduced in SMB 3.1.1&apos;s NEGOTIATE Request and Response so that future dialects can add new cryptographic capabilities without changing the parent message structure. Each context has a 2-byte type identifier, a length, and a body. The defined types include `SMB2_PREAUTH_INTEGRITY_CAPABILITIES` (the hash function and salt), `SMB2_ENCRYPTION_CAPABILITIES` (the encryption ciphers offered), and `SMB2_SIGNING_CAPABILITIES` (the signing algorithms offered, added in 2021 to support AES-GMAC). Because all negotiate contexts are part of the pre-authentication message stream, they are all hashed into `PreauthIntegrityHashValue` automatically [@ms-smb2-pdf].
&lt;p&gt;From this moment forward, every byte of NEGOTIATE and SESSION_SETUP is cryptographically bound to the eventual session key. There is no way an in-path attacker can downgrade a 3.1.1 connection without producing two divergent session keys and therefore no signed message after authentication can possibly verify on both sides. The mechanism does have one limit, and it is the one that the next decade of SMB hardening had to deal with: pre-authentication integrity ensures that &lt;em&gt;if&lt;/em&gt; signing or encryption is negotiated, an attacker cannot tamper with the negotiation. It does not require either to be negotiated.&lt;/p&gt;
&lt;h2&gt;5. The 2021 Cipher Refresh and SMB-over-QUIC&lt;/h2&gt;
&lt;p&gt;Six years after pre-authentication integrity shipped, two parallel additions arrived in the same Windows release window. Windows 11 21H2 and Server 2022, both from the second half of 2021, extended the SMB cipher matrix and introduced a new transport that ran SMB inside QUIC instead of TCP.&lt;/p&gt;
&lt;h3&gt;The 2021 cipher refresh&lt;/h3&gt;
&lt;p&gt;The Negotiate Context machinery designed in 2015 absorbed three new values for &lt;code&gt;EncryptionAlgorithmId&lt;/code&gt; without a dialect bump [@ms-smb2-versioning]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0x0002&lt;/code&gt;: AES-128-GCM (already shipped with SMB 3.1.1 in 2015)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0x0003&lt;/code&gt;: AES-256-CCM (added 2021)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0x0004&lt;/code&gt;: AES-256-GCM (added 2021)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A fourth addition was the &lt;code&gt;SMB2_SIGNING_CAPABILITIES&lt;/code&gt; negotiate context, which let the dialect negotiate &lt;strong&gt;AES-GMAC&lt;/strong&gt; as a signing algorithm alongside AES-CMAC and HMAC-SHA-256 [@ms-smb2-versioning]. AES-GMAC is the authentication-only mode derived from AES-GCM, defined in NIST SP 800-38D [@nist-sp-800-38d].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;EncryptionAlgorithmId&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;First SMB version&lt;/th&gt;
&lt;th&gt;CNSA 2.0 compatible&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x0001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AES-128-CCM&lt;/td&gt;
&lt;td&gt;128 bits&lt;/td&gt;
&lt;td&gt;SMB 3.0 (2012)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Two-pass AEAD; pre-AES-NI baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x0002&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AES-128-GCM&lt;/td&gt;
&lt;td&gt;128 bits&lt;/td&gt;
&lt;td&gt;SMB 3.1.1 (2015)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Single-pass AEAD; faster than CCM on AES-NI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x0003&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AES-256-CCM&lt;/td&gt;
&lt;td&gt;256 bits&lt;/td&gt;
&lt;td&gt;SMB 3.1.1 (2021 cipher refresh)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;CNSA-grade; rarely chosen over GCM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0x0004&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;AES-256-GCM&lt;/td&gt;
&lt;td&gt;256 bits&lt;/td&gt;
&lt;td&gt;SMB 3.1.1 (2021 cipher refresh)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;CNSA-grade and AES-NI / VAES accelerated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The U.S. National Security Agency&apos;s Commercial National Security Algorithm Suite version 2.0, published in 2022 as the symmetric and asymmetric algorithm baseline for protecting U.S. classified information up to TOP SECRET. The symmetric component requires AES-256 in any AEAD mode for confidentiality and AES-256-GMAC or HMAC-SHA-384 for integrity. The SMB combination that satisfies CNSA 2.0 is AES-256-GCM for encryption and AES-GMAC for signing; AES-128 variants are not CNSA-eligible.
&lt;h3&gt;Why AES-GMAC won the speed argument&lt;/h3&gt;
&lt;p&gt;AES-CMAC runs AES in CBC mode over the message, with one AES block operation per 16 bytes of input. AES-GMAC reuses the GCM mode&apos;s Galois-field multiplier, GHASH, which can be implemented in parallel using a single AES key-schedule and the PCLMULQDQ carry-less multiplication instruction that Intel added with the Westmere generation in 2010 [@iacr-2018-392].PCLMULQDQ multiplies two 64-bit operands as polynomials over GF(2), bypassing the carry chain that makes integer multiplication slow. It is the workhorse of every modern AES-GCM implementation.&lt;/p&gt;
&lt;p&gt;Drucker, Gueron and Krasnov&apos;s 2018 ePrint &lt;em&gt;Making AES Great Again&lt;/em&gt; documents the performance ceiling on contemporary Intel hardware [@iacr-2018-392]. They measured &lt;strong&gt;0.64 cycles per byte for AES-GCM single-buffer&lt;/strong&gt; on Skylake-X with AES-NI and PCLMULQDQ, and projected the theoretical bound at &lt;strong&gt;0.16 cycles per byte&lt;/strong&gt; for the AVX-512 + VPCLMULQDQ multi-buffer variant on Ice Lake.&lt;/p&gt;
&lt;p&gt;The single-buffer ratio against AES-CMAC, which the same paper notes runs at roughly 2 to 3 cycles per byte on equivalent hardware, is about 3 to 5x. The multi-buffer ratio is larger, often 6x or more, because GMAC parallelises across independent 16-byte blocks where CMAC&apos;s CBC chain serialises them.&lt;/p&gt;
&lt;p&gt;Taken together, those numbers mean that on a modern file server saturating a 25 Gbit/s NIC, AES-GMAC signing costs roughly one-third the CPU of AES-CMAC for the same packet rate. That is not a marginal optimisation; it is the difference between needing two cores to sign and needing one.&lt;/p&gt;
&lt;h3&gt;SMB-over-QUIC&lt;/h3&gt;
&lt;p&gt;The second 2021 addition was a new transport. Microsoft demoed SMB-over-QUIC in early 2021 and shipped it for general availability in November 2021 with the Windows Server 2022 Datacenter: Azure Edition SKU [@smb-over-quic]. The transport runs SMB inside a QUIC connection (RFC 9000 [@rfc9000]) whose record layer is encrypted by TLS 1.3 (RFC 8446 [@rfc8446]) and bound to QUIC by RFC 9001 [@rfc9001]. The wire-layer port is UDP/443, the same port HTTPS-over-QUIC uses, which means SMB-over-QUIC traverses most firewalls that already pass web traffic.&lt;/p&gt;

A UDP-based multiplexed and secure transport protocol designed by Google in 2012 and standardised at IETF in 2021 as RFC 9000 [@rfc9000]. QUIC carries multiple independent streams of reliable bytes inside a single connection, uses TLS 1.3 for the cryptographic handshake (RFC 9001 [@rfc9001]), and identifies connections by a connection ID rather than the 5-tuple, which means a QUIC connection survives an IP address change. SMB-over-QUIC uses QUIC&apos;s reliable stream abstraction to carry the SMB packets that would otherwise go over TCP, and inherits QUIC&apos;s TLS 1.3 record-layer encryption.
&lt;h3&gt;The trust-anchor shift&lt;/h3&gt;
&lt;p&gt;SMB-over-TCP/445 trusts only the authentication protocol. If Kerberos or NTLM trusts the principal, the SMB session derives a key from that authentication and proceeds. There is no other trust input.&lt;/p&gt;
&lt;p&gt;SMB-over-QUIC adds &lt;strong&gt;server certificate PKI&lt;/strong&gt; to the trust model. The QUIC handshake authenticates the server with a TLS 1.3 X.509 certificate chain that must validate against the client&apos;s trust store. This is a real change in threat model: a compromised certificate authority in the client&apos;s root store can MITM SMB-over-QUIC the same way it can MITM HTTPS. For some organisations that is a feature, a trust anchor that lives in the certificate authority instead of in Kerberos. For others it is a regression.&lt;/p&gt;

Some descriptions of SMB-over-QUIC suggest the SMB application layer is unencrypted because QUIC already encrypts everything. That is wrong in a way that matters. SMB-over-QUIC still negotiates SMB 3.1.1 pre-authentication integrity and SMB signing; the SMB session key derives independently from the authentication protocol, not from the TLS 1.3 session secret. There are two layers of encryption (TLS 1.3 at the QUIC layer and AES-GCM at the SMB layer) precisely because the two layers have independent trust anchors. If the QUIC TLS 1.3 session is MITM&apos;d by a rogue CA, the SMB-layer signing keys still verify against the authentication protocol&apos;s session key; the inner layer is the structural backstop.
&lt;p&gt;The original SMB-over-QUIC release was restricted to Windows Server 2022 Datacenter: Azure Edition, a SKU available only as an Azure-hosted virtual machine [@smb-over-quic]. That restriction made SMB-over-QUIC effectively unusable for the on-premises file-server population that the protocol most needed. The restriction was lifted with Windows Server 2025, which broadens SMB-over-QUIC hosting to every edition of the server SKU [@ws-2025-whats-new][@smb-over-quic]. On the client side, Windows 11 24H2 became the first SMB-over-QUIC-capable mainstream desktop client [@smb-feature-descriptions].&lt;/p&gt;
&lt;p&gt;Samba 4.15.0 (September 2021) added the SMB3 signing-algorithm-negotiation parameters (&lt;code&gt;client smb3 signing algorithms&lt;/code&gt;, &lt;code&gt;server smb3 signing algorithms&lt;/code&gt;) and the SMB3 encryption-algorithm-negotiation parameters, and fixed AES-256-GCM/CCM server-side support that was previously broken under bug 14764 [@samba-4-15-0]. SMB-over-QUIC support for both &lt;code&gt;smbd&lt;/code&gt; and &lt;code&gt;smbclient&lt;/code&gt; did not arrive in Samba until 4.23.0, in September 2025, closing a four-year interop gap with the November 2021 Microsoft release [@samba-4-23-0].&lt;/p&gt;
&lt;p&gt;The 2021 refresh handed enterprises CNSA-grade ciphers and a no-VPN remote-file-access transport. But signing was still opt-in by default for general SMB shares, and the SMB-relay toolkit that Sir Dystic released in 2001 still worked against any 21H2 client that an administrator had not hardened by hand. The defaults had not caught up.&lt;/p&gt;
&lt;h2&gt;6. The 2024 Defaults: Locks Finally Turned On&lt;/h2&gt;
&lt;p&gt;On &lt;strong&gt;October 1, 2024&lt;/strong&gt;, Windows 11 24H2 shipped to retail [@win11-release-info]. A month later, on November 1, 2024, Windows Server 2025 followed [@ws-2025-whats-new]. The two releases changed seven defaults in one go, and exactly one of those changes mattered most.&lt;/p&gt;
&lt;p&gt;The headline change was structural: SMB signing required by default on both outbound and inbound connections for every share, not just SYSVOL and NETLOGON [@smb-security-hardening]. The Microsoft Learn SMB Security Hardening page states it directly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Starting with Windows 11 24H2 and Windows Server 2025, all outbound and inbound SMB connections are now required to be signed by default. Previously, SMB signing was only required by default for connections to shares named SYSVOL and NETLOGON, and for clients of AD domain controllers. [@smb-security-hardening]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ned Pyle, the Microsoft file server product manager who has shipped SMB releases for the better part of a decade, summarised the bundle in a Tech Community post that doubles as the canonical 2024 reference:&lt;/p&gt;

With the release of Windows Server 2025 and Windows 11 24H2, we have made the most changes to SMB security since the introduction of SMB 2 in Windows Vista. -- Ned Pyle, Microsoft [@pyle-techcom-4226591]
&lt;h3&gt;The bundle, in priority order&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Signing required by default&lt;/strong&gt;, the load-bearing change. The omission-downgrade attack that has worked since 2001 is structurally closed for any 24H2-or-later pair, because the server will refuse an unsigned session [@smb-security-hardening][@pyle-techcom-4226591].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Client-side encryption mandate&lt;/strong&gt;, available but &lt;strong&gt;not on by default&lt;/strong&gt;. &lt;code&gt;Set-SmbClientConfiguration -RequireEncryption $true&lt;/code&gt; now refuses any outbound SMB session that does not negotiate AES-GCM encryption [@smb-security-hardening]. The most-misreported fact about the 2024 rollout is whether this is on. It is not.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authentication rate limiter.&lt;/strong&gt; A 2-second delay between failed NTLM or local-KDC Kerberos authentication attempts, configurable but on by default. Microsoft&apos;s published arithmetic: an attack that sends 300 guesses per second for 5 minutes (90,000 attempts) now takes 50 hours [@smb-security-hardening].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NTLM blocking for outbound SMB.&lt;/strong&gt; &lt;code&gt;Set-SmbClientConfiguration -BlockNTLM $true&lt;/code&gt; refuses outbound NTLM fallback, forcing Kerberos or failing the session [@smb-security-hardening].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SMB dialect minimum and maximum&lt;/strong&gt;, configurable per-host on both client and server [@smb-security-hardening].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SMB alternative ports&lt;/strong&gt;, so that an administrator can run SMB-over-QUIC on a non-default UDP port without losing audit support [@smb-security-hardening].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Insecure guest authentication blocked by default&lt;/strong&gt;, on every edition of Windows 11, closing a gap that previously only Enterprise and Education had been opted into since Windows 10 1709 [@smb-interception-defense].&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The eighth change, also part of the 2024-2025 cycle but described in the Server 2025 release notes rather than the hardening page, was the &lt;strong&gt;broadening of SMB-over-QUIC hosting&lt;/strong&gt; from the Azure Edition SKU to every edition of Windows Server 2025 [@ws-2025-whats-new][@smb-over-quic]. That broadening is the transport-side enabler for the rest of the bundle, because it makes SMB-over-QUIC available to organisations that do not run their file servers in Azure.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 2024-2025 rollout made SMB &lt;strong&gt;signing&lt;/strong&gt; required by default. It did not make SMB &lt;strong&gt;encryption&lt;/strong&gt; required by default. A 24H2 client speaking to a Server 2025 file share without an administrator&apos;s opt-in will still send the file&apos;s contents over the wire in cleartext, with only the per-packet AES-CMAC signatures preventing tampering. A passive eavesdropper on the path can still read the file. The fix is one line of PowerShell (&lt;code&gt;Set-SmbClientConfiguration -RequireEncryption $true&lt;/code&gt;) or a per-share &lt;code&gt;Set-SmbShare -EncryptData $true&lt;/code&gt;. Several widely-circulated 2024 press summaries got this backwards; the Microsoft Learn page is the source of truth [@smb-security-hardening].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The arc, closed&lt;/h3&gt;
&lt;p&gt;The 2001 SMBRelay disclosure to the 2024 default-on flip is twenty-three years and seven months [@smbrelay-cdc][@smb-security-hardening]. That is the arithmetic of the SMB story. The mechanism that closed the omission-downgrade attack family for the typical Windows file share existed in production from July 2015 onwards; the defaults that made the mechanism universal arrived nine years later.&lt;/p&gt;
&lt;p&gt;The 2024 default does not retroactively secure the long tail of legacy hosts: the SMB-relay primitive that Sir Dystic shipped in 2001 still works against any pre-24H2 Windows client that an administrator has not turned signing on for by hand, and against any third-party SMB server that does not yet support signing. Default-on protects the leading edge; the legacy fleet upgrades on its own calendar.&lt;/p&gt;
&lt;h3&gt;The compatibility breakage&lt;/h3&gt;
&lt;p&gt;The default-on signing flip broke a long tail of consumer NAS devices that ship SMB server implementations without signing support. Synology and QNAP and NETGEAR home NAS units running older firmware refused 24H2 client connections starting October 2024, and the recovery path required either a firmware update from the vendor or a per-host policy exception. The DSInternals matrix tracks the exact set of clients and servers that pass the new defaults [@dsinternals-24h2].&lt;/p&gt;

The audit channel for tracking which peers an organisation&apos;s clients fail to sign with is `Applications and Services Logs\Microsoft\Windows\SmbClient\Audit`, populated by the SMB client itself whenever it refuses an unsigned session [@smb-security-hardening]. The transitional pattern administrators were forced to adopt in late 2024 was: (a) leave signing required globally, (b) maintain a per-host exception list for unupgradable NAS devices, (c) put the exception list under change control with a target removal date. A few months of audit-log data is usually enough to enumerate the long tail of peers an organisation actually depends on; the policy-exception approach is structurally sound because the exception is narrow and time-bounded.
&lt;h3&gt;What still works: the cross-protocol relay class&lt;/h3&gt;
&lt;p&gt;Default-on signing closed the &lt;em&gt;single-protocol&lt;/em&gt; SMB relay. It did nothing about the &lt;em&gt;cross-protocol&lt;/em&gt; relay class, which routes around SMB entirely. The exemplar attack is &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;PetitPotam&lt;/a&gt;, disclosed by Lionel &quot;Topotam&quot; Gilles in July 2021 [@petitpotam-gh][@nvd-cve-2021-36942], with a sibling variant CVE-2022-26925 on the LSARPC interface [@nvd-cve-2022-26925].&lt;/p&gt;
&lt;p&gt;PetitPotam abuses the Encrypting File System Remote Protocol (MS-EFSRPC). The &lt;code&gt;EfsRpcOpenFileRaw&lt;/code&gt; method, exposed via the LSARPC named pipe over SMB, accepts a UNC path that the server resolves by &lt;strong&gt;opening an outbound SMB connection&lt;/strong&gt; to whatever host the path points at, using the calling user&apos;s credentials [@petitpotam-gh].&lt;/p&gt;
&lt;p&gt;An attacker who can call &lt;code&gt;EfsRpcOpenFileRaw&lt;/code&gt; on a server with a UNC path pointing back at the attacker&apos;s host obtains an outbound NTLM authentication from the server, typically a domain controller, since DCs run the EFSRPC service. The attacker then relays that NTLM authentication, not to another SMB server, but to &lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;Active Directory Certificate Services&lt;/a&gt; Web Enrollment&lt;/strong&gt; at &lt;code&gt;/certsrv/&lt;/code&gt;, which speaks HTTP and historically did not require client-side signing of the authentication.&lt;/p&gt;
&lt;p&gt;Once the relay completes, the attacker has a certificate issued in the name of the coerced principal, which on a domain controller is a domain controller account. From there, the attacker forges Kerberos tickets and the domain is compromised.&lt;/p&gt;
&lt;p&gt;A 2019 result by Marina Simakov and Yaron Zinar at Preempt (now CrowdStrike), CVE-2019-1040, sharpens the cross-protocol concern further [@drop-the-mic][@nvd-cve-2019-1040]. The pair found that an in-path attacker could bypass the NTLM Message Integrity Code by manipulating SPNEGO fields, then strip the &quot;signing required&quot; bit from the relayed NTLM message itself.&lt;/p&gt;
&lt;p&gt;That meant a relay attack could survive against targets that required NTLM signing, because the signing-required negotiation could be tampered with on the NTLM authentication exchange. Microsoft patched CVE-2019-1040 in 2019, but the result underscored the same lesson at the NTLM layer that SMB had learned at the SMB layer: any signing negotiation that is not bound to the eventual key derivation can be stripped.&lt;/p&gt;

A coercion-and-relay attack family disclosed by Lionel Gilles in July 2021 [@petitpotam-gh] in which the attacker invokes MS-EFSRPC `EfsRpcOpenFileRaw` on a target server with a UNC path that the server resolves by opening an outbound SMB connection, leaking the server&apos;s NTLM credentials to the attacker. The leaked credentials are then relayed cross-protocol to AD CS Web Enrollment over HTTPS. The class subsumes CVE-2021-36942 (LSA over the LSARPC pipe) and CVE-2022-26925 (a sibling LSARPC variant). The defence is **not** SMB signing on the target; it is Extended Protection for Authentication on the relay-to endpoint [@kb5005413].

A defence against NTLM relay attacks that binds the underlying transport&apos;s channel (typically a TLS server certificate hash) into the GSS channel-binding token that the SPNEGO authentication exchange carries [@kb5005413]. An attacker who relays an NTLM authentication from a victim&apos;s connection to an attacker-controlled TLS connection finds that the channel bindings disagree, and the relay-to endpoint refuses the authentication. EPA on AD CS `/certsrv/` is the canonical fix for PetitPotam-class attacks [@kb5005413].
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; SMB at the wire layer is now cryptographically sufficient. Modern SMB-related attacks no longer try to break SMB. They coerce SMB into authenticating and then relay the authentication to a protocol that does not require signing. The defence is no longer a single-protocol problem. Extended Protection for Authentication on AD CS, and eventually NTLM removal, are the structural fixes -- nothing at the SMB layer can close the cross-protocol relay class.&lt;/p&gt;
&lt;/blockquote&gt;

sequenceDiagram
    participant A as Attacker
    participant V as Victim DC
    participant ADCS as ADCS Web Enrollment over HTTPS
    A-&amp;gt;&amp;gt;V: LSARPC EfsRpcOpenFileRaw, UNC path to attacker share
    V-&amp;gt;&amp;gt;A: Outbound SMB NEGOTIATE with NTLM credentials of DC machine account
    Note over A,V: SMB signing on V does not help, V is the client
    A-&amp;gt;&amp;gt;ADCS: Relayed NTLM authentication to /certsrv/certfnsh.asp
    ADCS-&amp;gt;&amp;gt;A: Issues certificate for DC machine account
    Note over A,ADCS: Without EPA on /certsrv/ the relay succeeds
&lt;p&gt;The 2024 hardening package is real progress. It is also explicitly bounded. The headline change closes one attack class structurally and leaves the cross-protocol class untouched. To see what is still open, we have to leave SMB for a moment and look at the cryptographic limits the protocol still inherits.&lt;/p&gt;
&lt;h3&gt;A short PowerShell-equivalent for the audit&lt;/h3&gt;
&lt;p&gt;To verify the new defaults on a freshly imaged 24H2 client, run &lt;code&gt;Get-SmbClientConfiguration | Select RequireSecuritySignature&lt;/code&gt; and the server analogue. The runnable snippet below shows the &lt;em&gt;logic&lt;/em&gt; of those commands in JavaScript: readable, not directly executable on Windows.&lt;/p&gt;
&lt;p&gt;{`
const smbClientPolicyOn24H2 = {
  RequireSecuritySignature: true,
  EnableSecuritySignature: true,
  BlockNTLM: false,
  RequireEncryption: false,
  AuditServerDoesNotSupportEncryption: true,
  AuditServerDoesNotSupportSigning: true,
};&lt;/p&gt;
&lt;p&gt;function reportPosture(cfg) {
  if (cfg.RequireSecuritySignature) {
    console.log(&apos;Signing: required (24H2 default).&apos;);
  } else {
    console.log(&apos;Signing: NOT required. Run Set-SmbClientConfiguration -RequireSecuritySignature true.&apos;);
  }
  if (cfg.RequireEncryption) {
    console.log(&apos;Encryption: required.&apos;);
  } else {
    console.log(&apos;Encryption: opt-in only. Consider Set-SmbClientConfiguration -RequireEncryption true.&apos;);
  }
  if (cfg.BlockNTLM) {
    console.log(&apos;NTLM outbound: blocked.&apos;);
  } else {
    console.log(&apos;NTLM outbound: allowed. Consider -BlockNTLM true on hardened hosts.&apos;);
  }
}&lt;/p&gt;
&lt;p&gt;reportPosture(smbClientPolicyOn24H2);
`}&lt;/p&gt;
&lt;h2&gt;7. What SMB 3.1.1 Cannot Do&lt;/h2&gt;
&lt;p&gt;Five things SMB 3.1.1 cannot do, even with every default flipped on and every primitive at full strength.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Pre-authentication integrity is dialect-internal.&lt;/strong&gt; The mechanism binds the negotiation transcript to the session key inside SMB. It cannot stop an in-path attacker from refusing to forward a connection at all. Denial of service is structurally outside the threat model of any signing or encryption primitive; the only defence is path redundancy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Signing requires both endpoints to support it.&lt;/strong&gt; A 24H2 client refuses to talk unsigned to a pre-24H2 server only if the server is willing to sign. A pre-24H2 server that runs without signing turned on -- the long tail of consumer NAS, embedded appliances, older Linux Samba installs, ESXi datastores -- still answers an unsigned NEGOTIATE and still produces an unsigned session. The omission-downgrade is closed only for 24H2-to-24H2 pairs (or 24H2-to-Samba-4.15+ pairs). The legacy fleet upgrades over years, not weeks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Encryption is not authenticated key exchange.&lt;/strong&gt; The SMB session key derives from the authentication protocol&apos;s session secret -- the NTLM &lt;code&gt;ExportedSessionKey&lt;/code&gt; or the Kerberos service-ticket session key [@ms-smb2-pdf]. SMB inherits whatever weakness the authentication protocol carries. A user with a 30-bit-entropy password who authenticates with NTLM has a session key whose effective entropy is bounded above by the password&apos;s. AES-256-GCM does not save that user; the symmetric ciphers are working as advertised, but the secret they are protecting is too weak to survive an offline attack on the password hash.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; SMB encryption is upper-bounded by the password entropy of the authentication protocol that derived the session key. AES-256 does not improve a weak password. Pre-authentication integrity does not improve a weak password. The cryptographic primitives are doing what they say they do; the limit is one layer higher.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the protocol-level analogue of the older cryptographic adage that you cannot create entropy from key-stretching alone. PBKDF2 with a million iterations slows an attacker down by a factor of a million, but if the password has 30 bits of entropy, the work factor is still 2^30 -- a million iterations on a modern GPU is on the order of an hour for a single targeted password.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. SMB-over-QUIC binds the trust anchor to TLS 1.3 PKI.&lt;/strong&gt; Over TCP/445, SMB trusts only Kerberos or NTLM. Over QUIC, SMB additionally trusts the certificate authorities in the client&apos;s TLS trust store.&lt;/p&gt;
&lt;p&gt;A compromised CA in that store can MITM SMB-over-QUIC the way it MITMs HTTPS. The inner SMB layer&apos;s pre-authentication integrity will catch tampering with the SMB session itself, but the outer QUIC layer is now in the threat model. Whether this is a feature or a regression depends on whether you trust your TLS trust store more than you trust the Kerberos service that issues your tickets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Cross-protocol relay survives single-protocol hardening.&lt;/strong&gt; This is the strongest impossibility result that touches SMB. If protocol A (SMB) coerces an outbound authentication from a victim host, and the attacker relays that authentication cross-protocol to a target running protocol B (HTTPS to AD CS Web Enrollment) that does not require signing, no amount of hardening on protocol A&apos;s session layer prevents the attack.&lt;/p&gt;
&lt;p&gt;The fix has to live in the target&apos;s session layer (EPA on &lt;code&gt;/certsrv/&lt;/code&gt;) or in the authentication protocol itself (NTLM disablement). Closing it at the SMB layer is, in the precise cryptographic sense, impossible.&lt;/p&gt;

The observation that the effective security of an SMB session against an offline attack is bounded above by the entropy of the authentication-protocol shared secret that derived the SMB session key, not by the bit length of the negotiated AES cipher. A 256-bit cipher protecting a session key derived from a 30-bit-entropy password offers, against an offline attacker who can capture the authentication exchange, no more than 30 bits of work-factor security. SMB inherits this property from any authentication protocol whose key-establishment phase is a password-equivalent shared-key derivation.
&lt;p&gt;Of these five, three are deployment posture and two are structural. You can fix #2 by replacing the legacy fleet. You can fix #4 by curating your TLS trust store, removing CAs you do not need to trust, and pinning the AD CS PKI explicitly. You can fix #5 by removing NTLM, which Microsoft is in the middle of doing. Limits #1 (denial of service) and #3 (password-equivalence) are not deployment posture; they are properties of the underlying cryptographic objects, and they will be true of any SMB-shaped protocol that inherits a session key from an authentication exchange.&lt;/p&gt;
&lt;h2&gt;8. Competing Protocols, Parallel Paths&lt;/h2&gt;
&lt;p&gt;SMB is one of four families of file-sharing protocols a modern enterprise might deploy. Each made different cryptographic choices, and each got something right that the others got wrong.&lt;/p&gt;
&lt;h3&gt;NFS v4.2 with &lt;code&gt;sec=krb5p&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;NFS version 4, standardised in RFC 7530 [@rfc7530] and refined in RFC 8881 for the 4.1 minor version [@rfc8881], replaced the optional RPCSEC_GSS security flavour of NFSv3 with a mandatory authentication negotiation step. With &lt;code&gt;sec=krb5p&lt;/code&gt;, NFS authenticates each user with a Kerberos service ticket and encrypts each RPC payload with the Kerberos session key.&lt;/p&gt;
&lt;p&gt;The cipher matrix tracks Kerberos&apos;s: RFC 8009 (October 2016) defined enctype 19 (AES-128-CTS-HMAC-SHA-256-128) and enctype 20 (AES-256-CTS-HMAC-SHA-384-192), and &lt;code&gt;sec=krb5p&lt;/code&gt; on a modern Linux client and server uses enctype 20 by default [@rfc8009]. The cryptographic posture is genuinely comparable to SMB 3.1.1 with AES-256-GCM. The differences are platform (NFS is native to Linux and Unix, SMB is native to Windows) and the way transcript binding is achieved (NFS relies on the underlying GSS context binding rather than a separate hash chain).&lt;/p&gt;
&lt;p&gt;NFS-over-QUIC is in IETF draft. The most recent revision of &lt;code&gt;draft-cel-nfsv4-rpc-over-quicv1&lt;/code&gt;, dated 16 May 2026, is at revision -05 and is not yet on a standards-track timeline [@draft-nfs-rpc-over-quic]. SMB-over-QUIC went generally available in November 2021. NFS is roughly four years behind on this transport.&lt;/p&gt;
&lt;h3&gt;WebDAV over HTTPS&lt;/h3&gt;
&lt;p&gt;WebDAV, defined in RFC 4918 [@rfc4918], is HTTP with the verbs &lt;code&gt;PROPFIND&lt;/code&gt;, &lt;code&gt;PROPPATCH&lt;/code&gt;, &lt;code&gt;MKCOL&lt;/code&gt;, &lt;code&gt;COPY&lt;/code&gt;, &lt;code&gt;MOVE&lt;/code&gt;, &lt;code&gt;LOCK&lt;/code&gt;, and &lt;code&gt;UNLOCK&lt;/code&gt;. Its security model is &quot;use TLS.&quot; The OPTIONS and PROPFIND prologue messages that a WebDAV client exchanges with a server are not transcript-bound at the WebDAV layer. The binding lives entirely in the TLS handshake.&lt;/p&gt;
&lt;p&gt;For internet-facing file access that does not need Active Directory integration, WebDAV is a sound choice, and it remains a common SMB alternative for shipping documents to mobile clients. For AD-integrated scenarios, where SMB&apos;s Kerberos integration is the point, WebDAV does not compete.&lt;/p&gt;
&lt;h3&gt;FTPS and SFTP&lt;/h3&gt;
&lt;p&gt;FTPS (RFC 4217 [@rfc4217]) adds opt-in TLS to FTP via the &lt;code&gt;AUTH TLS&lt;/code&gt; command, which is structurally similar to SMTP&apos;s STARTTLS or LDAP&apos;s StartTLS. The opt-in nature is its weakness; the historical &quot;stripping&quot; attacks against opt-in TLS apply to FTPS just as they applied to opt-in NEGOTIATE bits in SMB.&lt;/p&gt;
&lt;p&gt;SFTP runs over SSH-2 (RFC 4253 [@rfc4253]). Because SSH-2 mandatorily encrypts the transport layer, and because the SSH key exchange (§8 of RFC 4253) produces an exchange hash that is signed by the server&apos;s host key and binds the entire key-exchange transcript, SFTP gets transcript binding for free from its substrate.&lt;/p&gt;
&lt;p&gt;The closest cryptographic posture to SMB 3.1.1&apos;s pre-authentication integrity is, structurally, SFTP-over-SSH-2. Both protocols bind the entire negotiation into the session-key derivation. Both make tampering produce key divergence rather than detectable mismatch. SSH took ten years to get there; SMB took twenty-five.&lt;/p&gt;
&lt;p&gt;The reason SFTP is a popular SMB alternative in regulatory-burdened environments is precisely that the transport is mandatorily encrypted and the transcript is mandatorily bound. A PCI-DSS auditor who is asked whether a file transfer was protected against in-path tampering can point to RFC 4253 §8 and the SSH exchange-hash signature, and the answer is yes by construction.&lt;/p&gt;
&lt;h3&gt;Samba&lt;/h3&gt;
&lt;p&gt;Samba is the canonical open-source SMB server. The project tracks the Microsoft cipher matrix with a lag that has varied between months and years.&lt;/p&gt;
&lt;p&gt;Samba 4.15.0 (September 2021) added the SMB3 signing-algorithm-negotiation parameters and fixed AES-256-GCM/CCM server-side support [@samba-4-15-0]. Samba 4.23.0 (September 2025) added SMB-over-QUIC for both &lt;code&gt;smbd&lt;/code&gt; and &lt;code&gt;smbclient&lt;/code&gt;, closing the four-year interop gap with the Microsoft November 2021 SMB-over-QUIC release [@samba-4-23-0]. The Samba team has consistently been the authoritative third-party implementer of the SMB cipher matrix. The gap between Microsoft and Samba is the practical floor on how quickly the SMB world can absorb a new cipher.&lt;/p&gt;
&lt;h3&gt;SMB Direct&lt;/h3&gt;
&lt;p&gt;SMB Direct is not a competitor; it is a parallel transport. Defined in &lt;code&gt;[MS-SMBD]&lt;/code&gt; and shipped with Windows Server 2012 [@smb-direct], SMB Direct runs SMB over RDMA fabrics (RoCE or iWARP) on the LAN, bypassing the kernel TCP stack for high-throughput, low-latency file workloads.&lt;/p&gt;
&lt;p&gt;Encryption with placement was added in Windows Server 2022 [@smb-direct]. SMB Direct does not run over QUIC, because QUIC&apos;s user-space encryption is incompatible with RDMA&apos;s kernel-bypass placement model. The two transports are deployed for different workloads: SMB Direct on the data centre LAN, SMB-over-QUIC on the wide area.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Transport&lt;/th&gt;
&lt;th&gt;Encryption default&lt;/th&gt;
&lt;th&gt;Signing default&lt;/th&gt;
&lt;th&gt;Authentication&lt;/th&gt;
&lt;th&gt;Transcript binding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;SMB 3.1.1 over TCP/445&lt;/td&gt;
&lt;td&gt;TCP/445&lt;/td&gt;
&lt;td&gt;Opt-in (Server 2025)&lt;/td&gt;
&lt;td&gt;Required by default (24H2)&lt;/td&gt;
&lt;td&gt;Kerberos or NTLM&lt;/td&gt;
&lt;td&gt;Pre-auth integrity (SHA-512 into SP 800-108 KDF)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SMB-over-QUIC&lt;/td&gt;
&lt;td&gt;UDP/443&lt;/td&gt;
&lt;td&gt;TLS 1.3 (QUIC) + opt-in SMB AES-GCM&lt;/td&gt;
&lt;td&gt;Required by default (24H2 client)&lt;/td&gt;
&lt;td&gt;Kerberos or NTLM + TLS 1.3 cert&lt;/td&gt;
&lt;td&gt;Pre-auth integrity inside QUIC + TLS 1.3 transcript hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NFSv4.2 &lt;code&gt;sec=krb5p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TCP (and QUIC draft)&lt;/td&gt;
&lt;td&gt;AES-256-GCM via RFC 8009&lt;/td&gt;
&lt;td&gt;Per-RPC GSS integrity&lt;/td&gt;
&lt;td&gt;Kerberos&lt;/td&gt;
&lt;td&gt;Kerberos GSS context binding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebDAV over HTTPS&lt;/td&gt;
&lt;td&gt;TCP/443&lt;/td&gt;
&lt;td&gt;TLS-mandated&lt;/td&gt;
&lt;td&gt;TLS-mandated&lt;/td&gt;
&lt;td&gt;HTTP authentication header&lt;/td&gt;
&lt;td&gt;TLS 1.3 transcript hash only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SFTP over SSH-2&lt;/td&gt;
&lt;td&gt;TCP/22&lt;/td&gt;
&lt;td&gt;Mandatory&lt;/td&gt;
&lt;td&gt;Mandatory&lt;/td&gt;
&lt;td&gt;SSH user authentication&lt;/td&gt;
&lt;td&gt;Exchange-hash signed by host key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Across the four families, the convergence in 2026 is unmistakable. All paths lead to &lt;em&gt;authenticated transcript binding plus an AEAD over an established session key.&lt;/em&gt; SMB took twenty-five years to get there. SSH took ten. The two protocols arrived at the same shape from different starting points -- one a file-sharing protocol that picked up TLS-like primitives, the other a remote-shell protocol that always had them.&lt;/p&gt;
&lt;h2&gt;9. Open Problems for 2026 to 2028&lt;/h2&gt;
&lt;p&gt;Five problems the SMB team is working on now, and at least one nobody has a credible answer to.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. When does encryption-required-by-default flip?&lt;/strong&gt; The 24H2 client mandate exists, but it is opt-in. Microsoft has not made a public commitment to a default-flip date for &lt;code&gt;RequireEncryption $true&lt;/code&gt; [@smb-security-hardening].&lt;/p&gt;
&lt;p&gt;The stakes are real: passive eavesdropping on an unencrypted SMB session over TCP/445 still recovers the file contents. The deployment-side argument for not flipping yet is the long tail of pre-24H2 clients that cannot negotiate SMB encryption at all. A unilateral server-side flip locks them out. The deployment-side argument for flipping is that signing-required already locks them out of any signed share, and the marginal incompatibility cost is small. The decision is calendar, not cryptography.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. NTLM removal interplay.&lt;/strong&gt; Microsoft&apos;s three-phase NTLM disablement programme is on a multi-year timeline, with the explicit goal of removing the legacy authentication protocol from Windows entirely. The interaction with SMB is structural: an SMB session over Kerberos derives its keys differently than an SMB session over NTLM, and a long tail of NAS appliances and embedded SMB servers still expect NTLM.&lt;/p&gt;
&lt;p&gt;The transition pattern is: Kerberos by default, NTLM as a configurable fallback, NTLM disabled for outbound, NTLM removed. The PetitPotam class disappears the moment NTLM is gone. The cross-protocol relay requires the relayed authentication to be NTLM, because Kerberos service tickets are bound to a specific service principal and cannot be relayed to a different service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Post-quantum key exchange for SMB-over-TCP/445.&lt;/strong&gt; SMB-over-QUIC inherits TLS 1.3&apos;s &lt;a href=&quot;https://paragmali.com/blog/post-quantum-cryptography-on-windows-the-thirty-year-migrati/&quot; rel=&quot;noopener&quot;&gt;hybrid post-quantum KEM groups&lt;/a&gt; (ML-KEM-based [@nist-fips-203], currently being deployed by major browsers and CDNs). SMB-over-TCP/445 has no protocol-level key-exchange step; it inherits whatever the authentication protocol provides.&lt;/p&gt;
&lt;p&gt;Kerberos and NTLM today have no PQC posture. The SMB session key is therefore unprotected against a &quot;harvest now, decrypt later&quot; attacker with a future cryptanalytically relevant quantum computer. The fix is either (a) move long-confidentiality workloads to SMB-over-QUIC to get TLS 1.3&apos;s hybrid KEM, or (b) wait for Kerberos to absorb a hybrid PQC enctype.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Cross-protocol relay survival.&lt;/strong&gt; PetitPotam-style attacks are not closeable at the SMB layer (see Section 7, limit #5). The structural fix is NTLM removal, which is problem #2 above. In the interim, the deployment-side defence is Extended Protection for Authentication on every NTLM-accepting endpoint -- AD CS Web Enrollment is the canonical one, but the same logic applies to LDAP, WSMan, IIS-hosted enterprise applications, and any internal HTTP service that accepts NTLM [@kb5005413].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Formal analysis of the full SMB 3.1.1 handshake composition.&lt;/strong&gt; No published Tamarin or ProVerif model of the full pre-authentication integrity plus SP 800-108 KDF plus Kerberos-or-NTLM composition exists in the academic literature.&lt;/p&gt;
&lt;p&gt;Individual analyses of AES-GCM, AES-CMAC, SP 800-108, and SHA-512 are tight at the primitive level. The composition of these primitives in the SMB 3.1.1 handshake is the place where TLS 1.2 historically broke (Lucky 13, Triple Handshake, the renegotiation attack of 2009, the CBC-MAC issues of POODLE). The absence of a published formal model is the single most-cited research gap in the SMB-protocol-security literature.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Problem #5 (formal analysis) is the only one of the five that is a genuine open research problem. Problems #1, #2, and #4 are deployment-posture decisions waiting on calendar dates and platform migration. Problem #3 will look quaint by 2030, when hybrid PQC is everyone&apos;s default rather than the SMB team&apos;s. Problem #5 is hard in a different way: the composition seam between pre-authentication integrity, the SP 800-108 KDF, and the underlying authentication protocol is exactly the shape that historically produces protocol-composition vulnerabilities, and the SMB community has not yet had its TLS-1.3-formal-analysis moment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The TLS 1.2 vulnerability history is the standard cautionary tale here. Lucky 13 (2013), POODLE (2014), the Triple Handshake (2014), and the renegotiation attack (2009) all arose at composition seams between primitives that were individually sound. The TLS 1.3 design explicitly tried to remove those seams, and the IETF process required formal models (Tamarin and ProVerif) before the protocol could go to RFC. SMB 3.1.1 has not yet been through that process, and the absence is the strongest argument for funding the work.&lt;/p&gt;
&lt;p&gt;None of these five problems undo the 25-year arc that closed in October 2024. Pre-authentication integrity remains structurally sound; the cipher matrix remains at the CNSA 2.0 ceiling; the defaults remain on. The open problems are &lt;em&gt;what comes next&lt;/em&gt;, not &lt;em&gt;what is broken&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;10. Practical Recipes and Frequently Asked Questions&lt;/h2&gt;
&lt;p&gt;If you administer Windows estates, run a Samba server, or audit network traffic for a living, here is what changes in 2026.&lt;/p&gt;
&lt;h3&gt;A 30-minute audit&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A new Windows 11 24H2 client and a new Windows Server 2025 file server arrive with signing required by default. To verify that an existing estate matches the new posture, run on each client &lt;code&gt;Get-SmbClientConfiguration | Select RequireSecuritySignature, RequireEncryption, BlockNTLM&lt;/code&gt; and on each server &lt;code&gt;Get-SmbServerConfiguration | Select RequireSecuritySignature, EncryptData, RejectUnencryptedAccess&lt;/code&gt;. Any host where &lt;code&gt;RequireSecuritySignature&lt;/code&gt; is &lt;code&gt;False&lt;/code&gt; is at the pre-24H2 posture. Schedule those for either upgrade or a policy push. Pull &lt;code&gt;Applications and Services Logs\Microsoft\Windows\SmbClient\Audit&lt;/code&gt; to enumerate which third-party peers the estate actually fails to sign with; that audit log is the only practical way to find the long tail of NAS devices and ESXi datastores before they hit a user.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The commands below cover the recipes most administrators reach for first.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Verify 24H2 signing defaults&lt;/strong&gt;: &lt;code&gt;Get-SmbClientConfiguration | Select RequireSecuritySignature&lt;/code&gt;; &lt;code&gt;Get-SmbServerConfiguration | Select RequireSecuritySignature&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mandate encryption on the client (24H2 or later)&lt;/strong&gt;: &lt;code&gt;Set-SmbClientConfiguration -RequireEncryption $true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mandate encryption on a specific share (server)&lt;/strong&gt;: &lt;code&gt;Set-SmbShare -Name MyShare -EncryptData $true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block outbound NTLM fallback (24H2 or later)&lt;/strong&gt;: &lt;code&gt;Set-SmbClientConfiguration -BlockNTLM $true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy SMB-over-QUIC on Server 2025&lt;/strong&gt;: install the SMB Server role, bind a TLS 1.3-capable certificate via &lt;code&gt;New-SmbServerCertificateMapping&lt;/code&gt;, and optionally configure Client Access Control to restrict which principals can connect [@smb-over-quic].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit which peers refuse to sign&lt;/strong&gt;: enable the SmbClient Audit channel and review entries for hosts where signing was negotiated off.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove SMB1 entirely&lt;/strong&gt;: &lt;code&gt;Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol&lt;/code&gt; [@smb-detect-disable].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Block TCP/445 at the network edge&lt;/strong&gt;: Microsoft&apos;s authoritative recommendation is to block inbound TCP/445 from the public internet at the corporate firewall and to use SMB-over-QUIC for any external file access [@smb-secure-traffic].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit PetitPotam exposure&lt;/strong&gt;: verify Extended Protection for Authentication on AD CS &lt;code&gt;/certsrv/&lt;/code&gt; per KB 5005413 [@kb5005413], and ensure the AD CS Web Enrollment endpoint is HTTPS-only with channel binding enforced.&lt;/li&gt;
&lt;/ul&gt;

On a domain-joined audit workstation that has WinRM open to every member, the following pipeline collects the list of peers that any of those members has talked to over SMB without signing in the last 24 hours: `Invoke-Command -ComputerName (Get-ADComputer -Filter * | Select -Expand DnsHostName) -ScriptBlock { Get-WinEvent -LogName &apos;Microsoft-Windows-SmbClient/Audit&apos; -MaxEvents 1000 | Where-Object { $_.Id -eq 31010 } } | Sort-Object Message -Unique`. Event ID 31010 is the SmbClient audit signal that the server did not support signing. The output is the deduplicated list of peer hostnames you need a remediation plan for.
&lt;h3&gt;Frequently asked questions&lt;/h3&gt;


No. SMB signing provides per-packet integrity (AES-CMAC, AES-GMAC, or HMAC-SHA-256 depending on the negotiated algorithm); SMB encryption wraps each packet in an AEAD (AES-CCM or AES-GCM) for confidentiality and integrity. The two are negotiated independently. For 24H2 / Server 2025 default behaviour, see the FAQ entry on the 24H2 default-on push below.


No. SMB signing on the coerced server protects the SMB session that delivers the credentials, but PetitPotam captures and relays those credentials to a different service (AD CS Web Enrollment over HTTPS) -- the defence has to live on the relay-to endpoint as Extended Protection for Authentication, not at the SMB layer [@kb5005413]. See section 6 for the mechanism and section 7 limit 5 for the impossibility framing.


No. SMB-over-QUIC is an additional transport for SMB, primarily intended for clients outside the corporate perimeter that want SMB access without a VPN. Inside the perimeter, TCP/445 remains the default transport on Windows Server 2025 [@smb-over-quic]. SMB Direct over RDMA remains the high-throughput data-centre option [@smb-direct].


No. Secure Negotiate (SMB 3.0.2, 2013) was a post-hoc FSCTL message; pre-authentication integrity (SMB 3.1.1, 2015) is a SHA-512 hash chain that enters the SP 800-108 KDF as salt, causing tampering to produce divergent keys rather than a detected mismatch [@kramer-lovinger-sdc2015][@ms-smb2-pdf]. See section 4 for the mechanism and the five-property comparison table.


AES-128-GCM has no known practical attack at the cipher-level (the GCM forgery bound from RFC 8446 and SP 800-38D applies regardless of key length [@rfc8446][@nist-sp-800-38d]). AES-256-GCM matters because CNSA 2.0 -- the U.S. NSA&apos;s algorithm suite for protecting information up to TOP SECRET -- requires a 256-bit symmetric key. Organisations that need CNSA compliance, including most U.S. federal agencies and defence contractors, must negotiate `EncryptionAlgorithmId 0x0004` (AES-256-GCM) [@ms-smb2-versioning].


Probably only on legacy Windows 10 Home or Pro pre-22H2 hosts and a few pre-Server 2019 environments. SMB1 has not been installed by default on Windows 10 since the Fall Creators Update (1709) and not on Windows Server since Server 2019 [@smb-interception-defense]. To check, run `Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol`; the `State` field will be `Disabled` on a modern install. To remove a stray install, use `Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol` [@smb-detect-disable].


No, and this is the single most-misreported fact about the 2024-2025 rollout. The default change was for *signing*, not *encryption*. SMB encryption is now mandate-able from one line of PowerShell or one Group Policy setting, but Microsoft did not flip the default-on switch. A 24H2 client speaking to a Server 2025 file share without explicit opt-in still sends file contents in cleartext on the wire, signed but not encrypted [@smb-security-hardening][@pyle-techcom-4226591].

&lt;h3&gt;Study guide&lt;/h3&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;smb-3-1-1-security&quot; keyTerms={[
  { term: &quot;SMB-relay attack class&quot;, definition: &quot;Capture-and-replay attacks on an SMB authentication exchange, relayed in real time into a fresh session against a target where the same user has access; originally demonstrated by Sir Dystic on March 31, 2001.&quot; },
  { term: &quot;Negotiate downgrade&quot;, definition: &quot;Tampering with the SMB NEGOTIATE Response so that the client and server agree on a session without signing or encryption; the load-bearing primitive of every SMB-relay attack before 2015.&quot; },
  { term: &quot;Pre-authentication integrity&quot;, definition: &quot;SMB 3.1.1 mechanism that binds every byte of the four pre-authentication messages into the salt argument of the SP 800-108 KDF that derives the SMB session keys; tampering produces divergent keys rather than a detectable mismatch.&quot; },
  { term: &quot;Secure Negotiate&quot;, definition: &quot;SMB 3.0.2 post-hoc validation FSCTL that compared client and server views of the NEGOTIATE capabilities after authentication; superseded by pre-authentication integrity in SMB 3.1.1.&quot; },
  { term: &quot;SP 800-108 KDF&quot;, definition: &quot;NIST counter-mode HMAC-SHA-256 key-derivation function used by SMB 3.x to derive per-session keys from an authentication-protocol shared secret, the role label, and the pre-authentication hash chain as context.&quot; },
  { term: &quot;AES-CMAC&quot;, definition: &quot;Block-cipher message authentication code from NIST SP 800-38B, the default SMB 3.x signing algorithm before AES-GMAC was added as a negotiable alternative in 2021.&quot; },
  { term: &quot;AES-GMAC&quot;, definition: &quot;The authentication-only mode of AES-GCM from NIST SP 800-38D, faster than AES-CMAC on hardware with PCLMULQDQ and VAES; added as a negotiable SMB signing algorithm in 2021.&quot; },
  { term: &quot;AES-256-GCM&quot;, definition: &quot;256-bit AES in Galois/Counter Mode; the CNSA 2.0-compliant SMB encryption algorithm, encoded as EncryptionAlgorithmId 0x0004 and added to SMB 3.1.1 in 2021.&quot; },
  { term: &quot;SMB-over-QUIC&quot;, definition: &quot;SMB transport over RFC 9000 QUIC and RFC 9001 TLS 1.3 on UDP/443, generally available with Windows Server 2022 Datacenter Azure Edition in November 2021 and broadened to all Server 2025 editions in 2024.&quot; },
  { term: &quot;Extended Protection for Authentication&quot;, definition: &quot;Binding of the TLS channel into the GSS channel-binding token in SPNEGO authentication, defeating cross-protocol NTLM relay by causing the relayed authentication to disagree with the channel binding observed at the relay-to endpoint.&quot; },
  { term: &quot;PetitPotam&quot;, definition: &quot;Coercion-and-relay attack disclosed by Lionel Gilles in July 2021 that uses MS-EFSRPC EfsRpcOpenFileRaw to coerce outbound NTLM authentication from a target server, then relays the authentication cross-protocol to AD CS Web Enrollment over HTTPS.&quot; },
  { term: &quot;CNSA 2.0&quot;, definition: &quot;The U.S. NSA Commercial National Security Algorithm Suite 2.0; requires AES-256 in any AEAD mode for confidentiality and AES-256-GMAC or HMAC-SHA-384 for integrity; the SMB combination is AES-256-GCM plus AES-GMAC.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;On March 31, 2001, Sir Dystic walked onto a stage in Atlanta and demonstrated an attack that should have lasted a year. It lasted twenty-three.&lt;/p&gt;
&lt;p&gt;The cryptographic primitives that closed it -- AES-CMAC, AES-128-CCM, AES-128-GCM, AES-256-GCM, AES-GMAC, the SP 800-108 KDF, SHA-512 -- arrived between 2006 and 2021. The structural mechanism that bound them into a tamper-resistant SMB session, pre-authentication integrity, arrived in July 2015. The defaults that made all of it universal arrived in October 2024.&lt;/p&gt;
&lt;p&gt;The next twenty-five years of SMB security live in the protocols above it: Kerberos, NTLM removal, post-quantum key exchange. Those will be slower, because every protocol seam between SMB and what comes above it is a place where a future Sir Dystic can find new work.&lt;/p&gt;
</content:encoded><category>smb</category><category>cryptography</category><category>windows-security</category><category>network-protocols</category><category>pre-authentication-integrity</category><category>smb-over-quic</category><category>ntlm-relay</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>NTLMless: The Death of NTLM in Windows</title><link>https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/</link><guid isPermaLink="true">https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/</guid><description>Thirty years of pass-the-hash, NTLM relay, PetitPotam, and ESC8 -- and the Kerberos engineering that finally lets Microsoft turn NTLM off by default.</description><pubDate>Sun, 10 May 2026 00:00:00 GMT</pubDate><content:encoded>
**NTLM is the 30-year-old fallback authentication protocol that Active Directory still rests on whenever Kerberos cannot do the job -- and every consequential modern AD attack (pass-the-hash, NTLM relay, PetitPotam, ESC8) lives in that fallback path.** Microsoft&apos;s exit plan (IAKerb, Local KDC, NEGOEX, the Negotiate-everywhere refactor) closes the four reasons NTLM survived, and the January 2026 roadmap names &quot;disabled by default in the next major Windows release&quot; as Phase 3. This article tells the whole arc as one story: how NTLM works on the wire, every attack class against it, exactly what is being removed -- and what is not.
&lt;h2&gt;1. Eight Minutes&lt;/h2&gt;
&lt;p&gt;A defender has done every retrofit Microsoft has shipped over twenty years. SMB signing enforced on every member server. EPA enabled on every IIS endpoint. &lt;a href=&quot;https://paragmali.com/blog/the-windows-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; on. Restrict NTLM in audit mode. KB 5005413 applied to AD CS. An attacker with no credentials joins their network, runs &lt;code&gt;Coercer&lt;/code&gt; against a domain controller, and a handful of seconds later holds a Kerberos ticket-granting ticket for the Domain Admin account [@gh-coercer, @specterops-cert-preowned-blog]. Total elapsed time: less than the time it took you to read this paragraph. Total prerequisites for the chain: that NTLM still exists as a fallback path on Windows.&lt;/p&gt;
&lt;p&gt;The chain has a name. ESC8, from Will Schroeder and Lee Christensen&apos;s &quot;Certified Pre-Owned&quot; whitepaper, published June 17, 2021 [@specterops-cert-preowned-blog, @specterops-cert-preowned-pdf]. Its coercion primitive has another name. PetitPotam, from Lionel Gilles, published the next month. Together they take a fully retrofitted Active Directory environment to Domain Admin in four steps.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 1. &lt;strong&gt;Coerce.&lt;/strong&gt; Call &lt;code&gt;EfsRpcOpenFileRaw&lt;/code&gt; against any Windows server -- including a DC -- over LSARPC. The service, running as SYSTEM, NTLM-authenticates back to an attacker-controlled UNC path. No credentials required. 2. &lt;strong&gt;Relay.&lt;/strong&gt; &lt;code&gt;ntlmrelayx.py&lt;/code&gt; from Impacket sits on the listening side and forwards the live NTLM exchange to the AD CS Web Enrollment endpoint at &lt;code&gt;/certsrv/certfnsh.asp&lt;/code&gt; [@gh-impacket]. 3. &lt;strong&gt;Enroll.&lt;/strong&gt; The relayed authentication enrolls the DC&apos;s machine account for a client certificate against the &lt;code&gt;Machine&lt;/code&gt; template (or any default-enabled template that allows enrollment) [@specterops-cert-preowned-pdf]. 4. &lt;strong&gt;Forge.&lt;/strong&gt; The attacker uses the certificate to perform PKINIT against the KDC, obtains a TGT for the DC&apos;s machine account, and uses the DC machine account&apos;s TGT to DCSync the domain&apos;s hashes -- including the krbtgt hash -- achieving full domain compromise. Domain Admin in under ten minutes [@specterops-cert-preowned-blog].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pause on what is and is not true here. SMB signing did not fail; SMB signing was not in the chain. EPA failed because it was deployed on IIS authentication endpoints generally but the &lt;code&gt;/certsrv/&lt;/code&gt; deployment lagged [@ms-kb5005413]. Credential Guard did not fail; Credential Guard protects the NT-hash, and the attacker never touched a hash. Restrict NTLM in audit mode worked exactly as labelled: it audited.&lt;/p&gt;
&lt;p&gt;The retrofits are not wrong. They patch the named primitives. The chain exploits the &lt;em&gt;existence&lt;/em&gt; of the fallback path, not a primitive. Every protective control is honest about what it does and silent about what it does not.&lt;/p&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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