<?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</title><description>Posts tagged ntlm.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Thu, 18 Jun 2026 02:11:08 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/ntlm/rss.xml" rel="self" type="application/rss+xml"/><item><title>Five Ways Windows Authentication Breaks: A Machine-Checked Tour -- and Why Finding Nothing New Is the Point</title><link>https://paragmali.com/blog/five-ways-windows-authentication-breaks-a-machine-checked-to/</link><guid isPermaLink="true">https://paragmali.com/blog/five-ways-windows-authentication-breaks-a-machine-checked-to/</guid><description>A Tamarin and Dolev-Yao tour of 23 Windows authentication protocols: five recurring failure patterns, what a prover can prove, and the boundary it cannot cross.</description><pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate><content:encoded>
Twenty-three Windows `[MS-*]` authentication protocols, machine-checked in the Tamarin prover under one network (&quot;Dolev-Yao&quot;) adversary, each as a flawed/fixed pair reproducing a known, published break -- turned up **zero new vulnerabilities**. That is the point. Nearly every Windows-auth failure within symbolic reach collapses into **five recurring structural patterns**: missing channel binding, keyed-vs-unkeyed integrity, symmetric-credential reflection, identity-binding gaps, and delegation or composition failure. Deepening the models proved *positive* guarantees too -- forward secrecy and key-compromise-impersonation resistance for PKINIT-DH and IKE, hybrid post-quantum transcript binding, Silver-Ticket containment. The catch, and the honest core, is the **symbolic/computational boundary**: a perfect-crypto model sees protocol *logic*, not the probabilistic flaws (like Zerologon&apos;s zero-IV) that live one layer down.
&lt;h2&gt;1. Was Kerberos Broken, or Did It Just Look Broken?&lt;/h2&gt;
&lt;p&gt;In 2014, a domain user could become a domain administrator by changing a single field in a &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos ticket&lt;/a&gt; [@cve-2014-6324]. Not by breaking any cryptography. The attacker built a Privilege Attribute Certificate that claimed membership in the administrators group, signed it with a checksum that needed no secret key, and handed it to the domain controller. The controller checked the signature, found it valid, read the forged groups, and issued back a ticket carrying full administrative authority [@cve-2014-6324]. Microsoft shipped MS14-068, the hole closed, and the penetration testers moved on [@ms14-068].&lt;/p&gt;

A signed data structure that Kerberos carries inside a ticket to tell a service who you are and which groups you belong to. Windows trusts the PAC for authorization decisions, so anyone who can forge a PAC the server will accept can rewrite their own group memberships [@ms-pac].
&lt;p&gt;The patch fixed the bug. It never answered the question underneath it: was Kerberos &lt;em&gt;broken&lt;/em&gt;, or did it just &lt;em&gt;look&lt;/em&gt; broken? The whole escalation turned on one mechanism -- whether the controller demanded a &lt;em&gt;keyed&lt;/em&gt; signature or accepted an &lt;em&gt;unkeyed&lt;/em&gt; checksum. Flip that one switch and the verdict flips with it.&lt;/p&gt;

flowchart TD
    A[User submits a ticket request with a self-made PAC] --&amp;gt; B{&quot;Does the KDC require a keyed signature on the PAC?&quot;}
    B --&amp;gt;|&quot;No, pre-patch&quot;| C[Unkeyed checksum, recomputable by anyone]
    C --&amp;gt; D[Forged group memberships accepted]
    D --&amp;gt; E[User gains domain administrator authority]
    B --&amp;gt;|&quot;Yes, MS14-068 fix&quot;| F[Forged PAC fails verification]
    F --&amp;gt; G[Request rejected, privileges unchanged]
&lt;p&gt;Windows runs dozens of authentication protocols, each specified in a Microsoft &lt;code&gt;[MS-*]&lt;/code&gt; open specification and each broken, at some point, by its own published CVE. The bulletin recorded MS14-068 only as a privately reported vulnerability and named no discoverer.The widely repeated attribution to Tom Maddock is community folklore, not a vendor confirmation; the bulletin itself says only &quot;privately reported&quot; [@ms14-068]. So here is the question this article answers. I took 23 of those &lt;code&gt;[MS-*]&lt;/code&gt; protocols and machine-checked them in the Tamarin prover under one network attacker, each modeled as a flawed version that reproduces its real break and a fixed version that closes it. The result was zero new vulnerabilities -- and that is the finding worth your time.&lt;/p&gt;
&lt;p&gt;Three claims, in order. First, the analysis surfaced nothing new: every break it exhibits was already published. Second, nearly every one of those breaks, across protocols that share no code, collapses into just &lt;strong&gt;five recurring structural patterns&lt;/strong&gt;. Third, finding nothing new across a corpus this well-studied is not an anticlimax -- it is the evidence that the five patterns are real and that the protocols, within the model, behave as their specifications claim.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is a tour of protocol &lt;em&gt;logic&lt;/em&gt; -- the failures a symbolic model can see. It does not cover offline password cracking, credential theft, or stolen-key attacks. Those live one layer down, and Section 9 explains exactly why a perfect-crypto model is blind to them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By the end you will have a vocabulary that predicts where an authentication protocol is likely to break before you have read a line of its CVE history. To explain why finding nothing can be a finding, though, we have to back up four decades -- to the first time a machine found a break that every human had missed.&lt;/p&gt;
&lt;h2&gt;2. Why Anyone Models Protocols at All&lt;/h2&gt;
&lt;p&gt;The Needham-Schroeder public-key protocol was published in 1978 and taught as correct for seventeen years [@needham-schroeder].Lowe&apos;s &lt;em&gt;first&lt;/em&gt; attack appeared in 1995 -- seventeen years after the 1978 publication -- with the model-checked break-and-fix following in 1996 [@lowe-nsfdr-ps]. The protocol was used, taught, and trusted the entire time -- which is precisely why a machine-checkable method, rather than careful reading, turned out to matter. Then Gavin Lowe pointed a model checker at it and the tool found a man-in-the-middle in an afternoon: an attacker can interleave two runs so that the responder completes believing it authenticated the initiator, when it actually ran with the attacker [@lowe-nsfdr-ps]. The attack had been sitting in plain sight the whole time. How did we get a machine that could find what a generation of careful readers had missed?&lt;/p&gt;
&lt;p&gt;The answer is a forty-year lineage, and it starts with a precise definition of the enemy. Needham and Schroeder gave the field its genre -- the challenge-response authentication handshake -- and, with it, a habit of arguing informally that a protocol &quot;obviously&quot; works [@needham-schroeder]. Five years later Danny Dolev and Andrew Yao replaced the hand-waving with a model so pessimistic it became the foundation of everything after it [@dolev-yao-ieee].&lt;/p&gt;

The attacker *is* the network. It can read, drop, replay, reorder, and inject any message; it can start any number of sessions; and it composes honest parties however it likes. The one thing it cannot do is break cryptography, which the model treats as perfect: ciphertext reveals nothing without the key, and signatures cannot be forged. Security means holding against this worst-case network attacker [@dolev-yao-ieee].
&lt;p&gt;That single abstraction is the load-bearing assumption behind every result in this article, and behind its central limitation. By assuming perfect cryptography, the Dolev-Yao model throws away the bit-level details so it can reason cleanly about message flow -- which is exactly why it sees logic flaws and misses arithmetic ones.&lt;/p&gt;

Symbolic analysis models messages as abstract terms and assumes cryptography is perfect, so it reasons about protocol *logic* under a Dolev-Yao attacker. Computational analysis models messages as bitstrings and the attacker as a probabilistic polynomial-time algorithm, so it reasons about *probabilities*, key sizes, and the strength of primitives. The two methods answer different questions and see different failures [@sok-cac].
&lt;p&gt;Next came a tool to reason inside the model. Burrows, Abadi, and Needham published BAN logic in 1990, a belief calculus that let analysts write down what each party is entitled to conclude from the messages it sees, layered on top of the Dolev-Yao attacker rather than inventing it [@ban-logic]. BAN made formal reasoning usable. It also showed how a verification method can be confidently wrong.&lt;/p&gt;

In 1990 Dan Nessett published a protocol that BAN logic &quot;proves&quot; secure even though it transmits the session key signed under a private key, so anyone with the corresponding public key can recover it -- the key is effectively in the clear [@nessett]. The lesson is not that BAN was useless; it is that a proof inherits the blind spots of its model. The same caution governs everything a symbolic prover tells us today.
&lt;p&gt;Then the machines arrived. Lowe&apos;s 1996 break used the FDR refinement checker, and his paper did something subtle that turned out to matter for decades: it did not just break the protocol, it &lt;em&gt;fixed&lt;/em&gt; it and re-checked the repair [@lowe-nsfdr-ps]. Break, patch, prove the patch -- that loop is the direct ancestor of the method in this article. Automated provers followed, in two families ordered by power rather than by date. Lowe&apos;s FDR sits at the head of the bounded, finite-state lineage -- explore every protocol run up to a fixed size -- a line later consolidated into toolsets such as AVISPA in 2005 [@avispa]. The unbounded symbolic provers, which lift that ceiling to arbitrarily many sessions, were led by ProVerif in 2001 [@blanchet-proverif] and eventually Tamarin in 2013 [@tamarin-cav].The split is conceptual, not a timeline: AVISPA (CAV 2005) [@avispa] postdates ProVerif (CSFW 2001) [@blanchet-proverif] by four years, and the genuinely earlier bounded exemplar is Lowe&apos;s FDR in 1996 [@lowe-nsfdr-ps].&lt;/p&gt;

Machines find what intuition misses. Lowe&apos;s 1996 result was not a cleverer human reading; it was a tool exploring runs a human would never enumerate by hand.
&lt;p&gt;While that method matured, a second, separate history was unfolding inside Windows. The protocols Kerberos, NTLM, CredSSP, LDAP, and their relatives were each specified in a Microsoft &lt;code&gt;[MS-*]&lt;/code&gt; document [@ms-nlmp] [@ms-pac] and each broken, in turn, by its own CVE across more than twenty years -- the breaks Section 4 lays out end to end. The two lineages -- method and application -- ran side by side and barely touched.&lt;/p&gt;

flowchart LR
    subgraph M[&quot;Method lineage&quot;]
      M1[Needham-Schroeder 1978] --&amp;gt; M2[Dolev-Yao adversary 1983]
      M2 --&amp;gt; M3[BAN belief logic 1990]
      M3 --&amp;gt; M4[Lowe and FDR model checker 1996]
      M4 --&amp;gt; M5[Unbounded provers, ProVerif 2001]
      M5 --&amp;gt; M6[Tamarin 2013]
    end
    subgraph A[&quot;Windows application lineage&quot;]
      A1[SMBRelay 2001] --&amp;gt; A2[MS08-068 2008]
      A2 --&amp;gt; A3[MS14-068 2014]
      A3 --&amp;gt; A4[Relay family 2017-2019]
      A4 --&amp;gt; A5[Bronze Bit 2020 and Certifried 2022]
    end
    M6 --&amp;gt; C[One adversary, whole corpus]
    A5 --&amp;gt; C
&lt;p&gt;Lowe broke one protocol and fixed it. The Windows world had dozens, and for two decades each one was broken, and patched, entirely on its own. The first people to point the new machines at these specific protocols could say something rigorous about each -- but only one at a time.&lt;/p&gt;
&lt;h2&gt;3. One Protocol at a Time&lt;/h2&gt;
&lt;p&gt;The machines did get pointed at the protocols Windows actually runs, and the early results were genuinely good. They were also, by construction, local.&lt;/p&gt;
&lt;p&gt;Start with public-key Kerberos. PKINIT lets a client authenticate to the Key Distribution Center with a certificate instead of a password, extending the Kerberos V5 service defined in RFC 4120 [@rfc4120].PKINIT is the public-key front door to Kerberos: it is how smart-card logon [@ms-pkca] and Windows Hello for Business [@whfb-auth] get an initial ticket. In 2006, Cervesato, Jaggard, Scedrov, Tsay, and Walstad formally analyzed it and found a man-in-the-middle: the KDC&apos;s reply was not bound to the requesting client&apos;s identity, so an insider could sit between a client and the KDC and make the client accept a session it never established [@cjstw-eprint]. They did not stop at the break. They specified fixes that bind the reply to the client and machine-checked the repair [@cjstw-asian], with the canonical journal version following in 2008 [@cjstw-infcomput]. Break, fix, prove the fix -- Lowe&apos;s loop, applied to a protocol shipping in every enterprise.&lt;/p&gt;
&lt;p&gt;Two years later, in 2008, Armando, Carbone, Compagna, Cuellar, and Tobarra turned the same lens on SAML 2.0 web-browser single sign-on, the protocol family behind federated login. A missing binding between an assertion and its intended audience let a dishonest service provider redirect a user&apos;s authentication to a different one, breaking SSO for Google Apps as their worked example [@armando-saml]. A few years later Cas Cremers re-analyzed IPsec&apos;s IKEv1 and IKEv2 and showed cross-mode confusion: properties that hold for one authentication mode can fail once an attacker mixes modes the designers reasoned about separately [@cremers-ipsec].&lt;/p&gt;
&lt;p&gt;Underneath two of those results sat one idea that had already been named. In 2003, Asokan, Niemi, and Nyberg described the man-in-the-middle in tunnelled authentication protocols: when an inner authentication runs inside an outer protected channel without being bound to it, an attacker can relay the inner exchange through a channel of its own choosing [@asokan-spw-doi]. Their fix was a cryptographic binding between the inner authentication and the protection protocol [@asokan-eprint] -- the academic root of what Windows would later call channel binding, and the seed of the first of our five patterns.&lt;/p&gt;
&lt;p&gt;Each of these was rigorous. Each shipped a real fix that is still in the specifications today. But notice the shape of the work: every analysis built its &lt;em&gt;own&lt;/em&gt; model of the attacker, its own idealization of the protocol, its own security goals. PKINIT&apos;s adversary was not SAML&apos;s adversary, which was not IKE&apos;s. So when a practitioner squinted and said &quot;these all feel like the same mistake,&quot; that intuition had nowhere rigorous to land. The recurrence was an analogy across papers that did not share a model.&lt;/p&gt;
&lt;p&gt;That is the wall the rest of this article is built to climb. Every one of these was a verdict on a single protocol. Nobody had asked, in a checkable way, what the breaks had in common -- because with a different model under each one, nobody could.&lt;/p&gt;
&lt;h2&gt;4. Twenty Years, the Same Five Mistakes&lt;/h2&gt;
&lt;p&gt;Lay the famous Windows-auth breaks end to end and a shape jumps off the page. SMBRelay in 2001, NTLM credential reflection in 2008, the unkeyed Kerberos checksum in 2014, a cluster of relay and channel-binding failures from 2017 to 2019, the Bronze Bit delegation bypass in 2020, the Certifried certificate misissuance in 2022. Different teams, different protocols, different decades -- and a small number of mistakes underneath, repeating.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Public break&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;The mechanism that failed&lt;/th&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;2001&lt;/td&gt;
&lt;td&gt;SMBRelay [@cdc-smbrelay]&lt;/td&gt;
&lt;td&gt;SMB / NTLM&lt;/td&gt;
&lt;td&gt;authenticator not bound to the channel it was used on&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2008&lt;/td&gt;
&lt;td&gt;MS08-068, CVE-2008-4037 [@ms08-068]&lt;/td&gt;
&lt;td&gt;NTLM (SMB)&lt;/td&gt;
&lt;td&gt;a credential reflected straight back at its sender&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2014&lt;/td&gt;
&lt;td&gt;MS14-068, CVE-2014-6324 [@cve-2014-6324]&lt;/td&gt;
&lt;td&gt;Kerberos PAC&lt;/td&gt;
&lt;td&gt;an unkeyed checksum accepted where a keyed signature was required&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2017&lt;/td&gt;
&lt;td&gt;CVE-2017-8563 [@cve-2017-8563]&lt;/td&gt;
&lt;td&gt;LDAP&lt;/td&gt;
&lt;td&gt;the bind not bound to the TLS channel underneath it&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2018&lt;/td&gt;
&lt;td&gt;CVE-2018-0886 [@cve-2018-0886]&lt;/td&gt;
&lt;td&gt;CredSSP&lt;/td&gt;
&lt;td&gt;the key-authentication value not bound to the TLS session&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;CVE-2019-1040 [@cve-2019-1040]&lt;/td&gt;
&lt;td&gt;NTLM&lt;/td&gt;
&lt;td&gt;an integrity field stripped without invalidating the signature&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;CVE-2020-17049 (Bronze Bit) [@cve-2020-17049]&lt;/td&gt;
&lt;td&gt;Kerberos S4U&lt;/td&gt;
&lt;td&gt;a delegation restriction not protected by a keyed signature&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;CVE-2022-26923 (Certifried) [@cve-2022-26923]&lt;/td&gt;
&lt;td&gt;AD CS&lt;/td&gt;
&lt;td&gt;a certificate subject not bound to the requester&apos;s identity&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The first entry is the oldest and the least formal. SMBRelay was demonstrated by the handle Sir Dystic in 2001, and its provenance is an archived Cult of the Dead Cow page rather than an academic paper [@cdc-smbrelay].That archival fragility is itself worth noting: a foundational attack in Windows security history survives mainly as a web-archive snapshot, not a citable primary [@cdc-smbrelay]. It showed that an NTLM authenticator, captured on one connection, could be forwarded to a second service that would happily accept it.&lt;/p&gt;

timeline
    title Windows authentication breaks, 2001-2022
    2001 : SMBRelay, NTLM relayed to a second service
    2008 : MS08-068, NTLM credential reflection
    2014 : MS14-068, unkeyed PAC checksum forged
    2017 : CVE-2017-8563, LDAP bind unbound from TLS
    2018 : CVE-2018-0886, CredSSP TLS splice
    2019 : CVE-2019-1040, drop-the-MIC integrity strip
    2020 : CVE-2020-17049, Bronze Bit delegation bypass
    2022 : CVE-2022-26923, Certifried misissuance
&lt;p&gt;Every one of these got a fix, and every fix was sound. Channel binding closed the relay and tunnelling failures, formalized for TLS as the bindings in RFC 5929 [@rfc5929]. Requiring a keyed signature closed the forged-PAC escalation [@cve-2014-6324]. Detecting and rejecting a reflected authenticator stopped NTLM credential reflection: MS08-068 changed the way SMB validates authentication replies, so a credential bounced straight back at its sender no longer passes [@ms08-068]. Binding an issued token to its audience and its requester closed the misissuance and redirection failures [@cve-2022-26923]. Protecting a delegation flag with a key closed the Bronze Bit bypass [@cve-2020-17049]. Each repair was correct, shipped quickly, and -- this is the important part -- entirely local to its own protocol.&lt;/p&gt;
&lt;p&gt;That locality is the trap. NTLM reflection [@ms08-068] and the unkeyed PAC checksum [@cve-2014-6324] are the same family of mistake -- trusting an integrity value that carries no secret or no direction -- yet they live in protocols that share no code and were fixed years apart by different teams. The relay family of 2017 through 2019 [@cve-2017-8563] [@cve-2018-0886] [@cve-2019-1040] is one idea, missing channel binding, wearing three protocol costumes. Bronze Bit [@cve-2020-17049] and Certifried [@cve-2022-26923] rhyme with breaks a decade older. The pattern is real, but it is spread across the seams between protocols, exactly where per-protocol work cannot look.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Per-CVE point-fixing is indispensable engineering and a terrible microscope for structure. Each patch is local to one protocol, and each one-protocol analysis rebuilds the attacker model from scratch. So the recurring shape is invisible by construction: you cannot see a cross-protocol pattern one protocol at a time. The fixes were never wrong -- they were just the wrong instrument for the question &quot;what keeps going wrong?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which sets up the move the rest of the article depends on. If the shapes are real, you should be able to &lt;em&gt;prove&lt;/em&gt; they are real -- not protocol by protocol, but all of them at once, every model facing the same attacker, with the recurrence stated as a checkable claim rather than a feeling. What would it take to build that?&lt;/p&gt;
&lt;h2&gt;5. One Adversary, One Method, the Whole Corpus&lt;/h2&gt;
&lt;p&gt;The move that makes the recurrence checkable is almost embarrassingly simple to state: model 23 of the &lt;code&gt;[MS-*]&lt;/code&gt; protocols in a single prover, under one shared attacker, and for each known break build not two models but three. I used the Tamarin prover for this, and its feature list is the reason [@tamarin-cav].&lt;/p&gt;
&lt;p&gt;Tamarin represents a protocol as multiset-rewriting rules over a mutable global state, reasons natively about Diffie-Hellman exponentiation, and verifies properties over an &lt;em&gt;unbounded&lt;/em&gt; number of sessions rather than a fixed few [@tamarin-cav]. It produces both proofs and concrete attack traces, and it has been used on protocols at the scale of TLS 1.3, 5G-AKA, and EMV [@tamarin-home]. Windows authentication needs exactly that combination: key exchange with real DH and &lt;a href=&quot;https://paragmali.com/blog/post-quantum-cryptography-on-windows-the-thirty-year-migrati/&quot; rel=&quot;noopener&quot;&gt;post-quantum KEMs&lt;/a&gt;, credential state that changes as tickets are issued, unbounded concurrent sessions, and the ability to show &lt;em&gt;both&lt;/em&gt; that a fix works and that the flawed version breaks. Security goals are written as trace properties.&lt;/p&gt;

A security goal phrased as a statement about every possible run of the protocol: on no trace does something bad happen. Secrecy says no run ever leaks the secret to the attacker. Agreement says that whenever one party finishes believing it authenticated another, that other party really did take part in a matching run [@tamarin-manual].

Agreement strengthened with a one-to-one matching between a party&apos;s completed runs and its peer&apos;s genuine runs, so that no single legitimate exchange can be replayed to satisfy two separate acceptances. Injectivity is the part of the property that rules out replay [@tamarin-manual].
&lt;p&gt;The third model is the one that turns analogy into evidence.&lt;/p&gt;

Three models of the same protocol. The *fixed* model includes the defended mechanism and verifies the security lemma. The *flawed* model removes exactly that one mechanism, and the same lemma falsifies -- reproducing the published break. The *control* re-enables the mechanism and the lemma verifies again. Because only one thing changed between the three, the cause of the break is pinned to that mechanism rather than to some accident of how the model was written [@lowe-nsfdr-ps].
&lt;p&gt;Here is one lemma, in Tamarin&apos;s own property language, for the MS14-068 case -- the claim that only the KDC can produce a PAC a server will accept:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;lemma pac_only_kdc_can_sign:
  &quot;All srv pac #i.
       AcceptPAC(srv, pac) @i
   ==&amp;gt; ( Ex #j. KdcSignedPAC(pac) @j &amp;amp; j &amp;lt; i )
     | ( Ex #r. RevealKey(&apos;krbtgt&apos;) @r )&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Read it as: on every trace, if a server accepts a PAC at time &lt;code&gt;i&lt;/code&gt;, then either the KDC actually produced that PAC&apos;s keyed signature earlier, or the long-term &lt;code&gt;krbtgt&lt;/code&gt; key was revealed [@tamarin-manual]. In the fixed model, where the integrity check is a keyed signature under &lt;code&gt;krbtgt&lt;/code&gt;, Tamarin finds no violating trace and the lemma holds for unbounded sessions. In the flawed model, where the server accepts an unkeyed checksum, Tamarin returns a concrete counterexample -- an acceptance with no prior KDC signature and no key reveal -- which is the forged-PAC escalation, machine-checked [@cve-2014-6324]. The operators and templates are standard Tamarin; the action-fact names are the model&apos;s own and are not themselves a citable claim.&lt;/p&gt;
&lt;p&gt;Two disciplines keep this honest. The first guards against a lemma that is true only because nothing ever reaches it.A property can be vacuously satisfied if no honest run ever triggers its premise. Non-vacuity sanity lemmas prove an honest party really can complete the protocol, so a &quot;verified&quot; guarantee has teeth rather than being true by absence [@tamarin-manual]. The second guards against overclaiming: every falsification is matched to a published CVE or paper before I call it a reproduction. Nothing in this corpus is presented as a discovery.&lt;/p&gt;

flowchart TD
    P[One protocol, one Dolev-Yao adversary] --&amp;gt; F[Fixed model, mechanism present]
    P --&amp;gt; X[Flawed model, one mechanism removed]
    P --&amp;gt; K[Control model, mechanism re-enabled]
    F --&amp;gt; FR[Security lemma verifies]
    X --&amp;gt; XR[Same lemma falsifies, the published break]
    K --&amp;gt; KR[Same lemma verifies again]
    FR --&amp;gt; D{&quot;Did only the toggled mechanism move the verdict?&quot;}
    XR --&amp;gt; D
    KR --&amp;gt; D
    D --&amp;gt;|Yes| C[Cause localized to the mechanism, not the harness]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The control model is the difference between a story and a proof. Without it, &quot;these breaks are all the same pattern&quot; is a nice grouping of war stories. With it, the claim becomes machine-checked and specific: toggle this one mechanism and the security property flips, restore it and the property returns. The recurrence is no longer an analogy across papers -- it is a falsifiable statement about a mechanism, repeated across protocols that share no code.&lt;/p&gt;
&lt;/blockquote&gt;

Finding nothing new across a well-studied corpus is not a null result. It is the evidence that the taxonomy is real -- the protocols behave, within the model, exactly as their fixes claim.
&lt;p&gt;With the instrument built, the corpus gives up its structure without much further argument. There are five shapes. Here is each one, with the worked break behind it.&lt;/p&gt;
&lt;h2&gt;6. The Five Patterns&lt;/h2&gt;
&lt;p&gt;Before you read a single CVE, ask five questions of any authentication protocol. Each question targets one of the recurring shapes, and a &quot;no&quot; to any of them names the family of break to expect. This decision tree is the article&apos;s centerpiece -- the audit you can run from memory.&lt;/p&gt;

flowchart TD
    S[Any authentication protocol] --&amp;gt; Q1{&quot;Is every authenticator bound to the channel and endpoint it is used on?&quot;}
    Q1 --&amp;gt;|No| P1[Pattern 1, relay and MITM]
    Q1 --&amp;gt;|Yes| Q2{&quot;Is every integrity check keyed, never a bare checksum?&quot;}
    Q2 --&amp;gt;|No| P2[Pattern 2, keyed-vs-unkeyed confusion]
    Q2 --&amp;gt;|Yes| Q3{&quot;Does every symmetric credential carry a direction or role tag?&quot;}
    Q3 --&amp;gt;|No| P3[Pattern 3, credential reflection]
    Q3 --&amp;gt;|Yes| Q4{&quot;Does every signed token bind requester, key, and audience?&quot;}
    Q4 --&amp;gt;|No| P4[Pattern 4, identity-binding gap]
    Q4 --&amp;gt;|Yes| Q5{&quot;Does every delegation chain keep its restriction under composition?&quot;}
    Q5 --&amp;gt;|No| P5[Pattern 5, delegation and composition]
    Q5 --&amp;gt;|Yes| OK[No break in these five shapes within symbolic reach]
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;The mechanism that fails&lt;/th&gt;
&lt;th&gt;Worked break&lt;/th&gt;
&lt;th&gt;The fix&lt;/th&gt;
&lt;th&gt;Public anchor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1. Channel binding&lt;/td&gt;
&lt;td&gt;authenticator not bound to its channel or endpoint&lt;/td&gt;
&lt;td&gt;NTLM relay, drop-the-MIC, CredSSP, LDAP&lt;/td&gt;
&lt;td&gt;TLS channel binding, SPNEGO mechListMIC&lt;/td&gt;
&lt;td&gt;[@rfc5929] [@cve-2019-1040]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Keyed-vs-unkeyed&lt;/td&gt;
&lt;td&gt;an unkeyed checksum accepted as integrity&lt;/td&gt;
&lt;td&gt;MS14-068 PAC forgery&lt;/td&gt;
&lt;td&gt;require a keyed KDC signature&lt;/td&gt;
&lt;td&gt;[@cve-2014-6324]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Reflection&lt;/td&gt;
&lt;td&gt;a symmetric credential with no direction tag&lt;/td&gt;
&lt;td&gt;NTLM credential reflection (MS08-068)&lt;/td&gt;
&lt;td&gt;reflection/replay detection (a direction tag in the model)&lt;/td&gt;
&lt;td&gt;[@ms08-068] [@cve-2008-4037]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Identity binding&lt;/td&gt;
&lt;td&gt;a token not bound to requester, key, or audience&lt;/td&gt;
&lt;td&gt;PKINIT, SAML SSO, Certifried&lt;/td&gt;
&lt;td&gt;bind reply, audience, and subject&lt;/td&gt;
&lt;td&gt;[@cve-2022-26923] [@rfc4556]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5. Delegation&lt;/td&gt;
&lt;td&gt;a restriction not preserved across a chain&lt;/td&gt;
&lt;td&gt;Bronze Bit S4U&lt;/td&gt;
&lt;td&gt;protect the flag with a keyed signature&lt;/td&gt;
&lt;td&gt;[@cve-2020-17049]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; These five questions are a predictive vocabulary. You do not need to formally model a protocol to ask them, and you do not need its CVE history. A &quot;no&quot; to any question tells you which family of failure to look for first -- which is what a taxonomy is for.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Pattern 1: Missing or ignored channel binding&lt;/h3&gt;
&lt;p&gt;The first pattern is the relay. An authenticator -- an NTLM response, a signed bind, a delegated credential -- is computed without naming the channel it is supposed to travel on, so an attacker can carry it to a different service that will accept it just the same. This is the modern form of the tunnelled-authentication man-in-the-middle that Asokan, Niemi, and Nyberg described in 2003 [@asokan-spw-doi].&lt;/p&gt;

Channel binding ties an inner authenticator to the outer channel it travels on, usually identified by the TLS endpoint [@rfc5929]. Windows ships it as Extended Protection for Authentication (EPA) and a Channel Binding Token (CBT) [@adv190023]. With the binding present, an authenticator captured on one connection is useless on another, because it names the channel it was made for.
&lt;p&gt;The worked model is &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;. With no channel binding, a victim&apos;s NTLM exchange relays cleanly to a second service [@ms-nlmp]; add the binding and the relayed authenticator no longer matches the channel it arrives on, and the target rejects it.&lt;/p&gt;

sequenceDiagram
    participant V as Victim client
    participant M as Attacker relay
    participant T as Target server
    V-&amp;gt;&amp;gt;M: Connect, NTLM NEGOTIATE
    M-&amp;gt;&amp;gt;T: Relay NEGOTIATE as the victim
    T-&amp;gt;&amp;gt;M: NTLM CHALLENGE, server nonce
    M-&amp;gt;&amp;gt;V: Forward the same CHALLENGE
    V-&amp;gt;&amp;gt;M: NTLM AUTHENTICATE over the nonce
    M-&amp;gt;&amp;gt;T: Relay AUTHENTICATE unchanged
    Note over M,T: No channel binding, so the target cannot tell the response came from a different connection
    T-&amp;gt;&amp;gt;M: Access granted as the victim
&lt;p&gt;The same shape recurs across protocols that share no code. CredSSP failed to bind its &lt;code&gt;pubKeyAuth&lt;/code&gt; value to the TLS session, so a man-in-the-middle could splice itself into an &lt;a href=&quot;https://paragmali.com/blog/rdp-authentication-26-years/&quot; rel=&quot;noopener&quot;&gt;RDP credential handshake&lt;/a&gt; [@cve-2018-0886]. LDAP accepted a bind without tying it to the TLS channel underneath, and Microsoft&apos;s own documentation is blunt that the default performed no channel-binding validation at all [@kb4034879] [@cve-2017-8563]. The companion guidance spells out the man-in-the-middle risk [@kb4520412] under the umbrella advisory for LDAP hardening [@adv190023]. And drop-the-MIC removed NTLM&apos;s integrity check without invalidating the surrounding signature.drop-the-MIC strips the NTLM message-integrity check from the negotiated flags without invalidating the outer signature, so a tampered exchange still verifies as authentic [@cve-2019-1040].&lt;/p&gt;
&lt;p&gt;The fixes are all the same idea wearing different names: the TLS channel bindings &lt;code&gt;tls-server-end-point&lt;/code&gt; and &lt;code&gt;tls-unique&lt;/code&gt; defined in RFC 5929 [@rfc5929], and the SPNEGO &lt;code&gt;mechListMIC&lt;/code&gt; that stops a negotiation downgrade [@rfc4178]. One subtlety decides whether the fix actually closes the door.RFC 5929&apos;s &lt;code&gt;tls-server-end-point&lt;/code&gt; hashes the server certificate, so it is per-&lt;em&gt;certificate&lt;/em&gt;, not per-&lt;em&gt;service&lt;/em&gt;. Two services sharing one certificate share one binding value -- which is exactly the gap that kept some LDAP deployments relayable even after binding was nominally enabled [@rfc5929].&lt;/p&gt;
&lt;h3&gt;Pattern 2: Keyed-vs-unkeyed integrity&lt;/h3&gt;
&lt;p&gt;The second pattern is a confusion between two things that look alike and behave nothing alike: a checksum and a keyed signature.&lt;/p&gt;

A checksum -- a CRC, a bare hash -- detects accidental corruption and needs no secret, so anyone can recompute it over data they forged. A message authentication code or signature is *keyed*: producing a valid tag requires a secret held by the legitimate sender -- a shared key the verifier also holds (a MAC), or a private key the verifier checks against the sender&apos;s public key (a signature). A verifier that accepts an unkeyed checksum where a keyed tag was required is trusting a value any attacker can produce [@cve-2014-6324].
&lt;p&gt;This is MS14-068 exactly. The KDC accepted a PAC whose integrity &quot;signature&quot; could be an unkeyed checksum, so a user could forge group memberships and compute a matching checksum themselves [@cve-2014-6324]. Require that the PAC carry a keyed signature under the &lt;code&gt;krbtgt&lt;/code&gt; key, and the same forgery fails because the user cannot produce the tag [@ms14-068]. The identical class shows up at the server-to-domain-controller PAC validation step, where a service asks a DC to vouch for a ticket&apos;s PAC [@ms-pac]. The fix and the failure are one mechanism, toggled.&lt;/p&gt;
&lt;p&gt;{`
// A toy checksum: no secret, so anyone can recompute it over any data.
function checksum(data) {
  let sum = 0;
  for (const ch of data) sum = (sum + ch.charCodeAt(0)) % 65521;
  return sum;
}
// A toy keyed tag: the value depends on a secret the attacker does not hold.
function tag(key, data) {
  let acc = key.length * 131;
  for (const ch of (key + data)) acc = (acc * 31 + ch.charCodeAt(0)) % 1000003;
  return acc;
}&lt;/p&gt;
&lt;p&gt;const forged = &quot;groups=domain-admins&quot;;&lt;/p&gt;
&lt;p&gt;// Unkeyed: the attacker computes the same checksum the verifier will recompute.
const attached = checksum(forged);
const verifier = checksum(forged);
console.log(&quot;unkeyed checksum accepts forged data:&quot;, attached === verifier); // true&lt;/p&gt;
&lt;p&gt;// Keyed: without the KDC secret, the attacker cannot match the expected tag.
const kdcSecret = &quot;krbtgt-secret&quot;;
const serverExpects = tag(kdcSecret, forged);
const attackerTag = tag(&quot;no-secret&quot;, forged);
console.log(&quot;forged keyed tag accepted:&quot;, attackerTag === serverExpects); // false
`}&lt;/p&gt;
&lt;h3&gt;Pattern 3: Symmetric-credential reflection&lt;/h3&gt;
&lt;p&gt;The third pattern is reflection. A credential computed by a keyed function that carries no direction or role tag can be bounced back at the party that produced it. The canonical Windows instance is NTLM credential reflection, fixed in MS08-068 [@ms08-068]: an attacker who receives a victim&apos;s challenge-response can send that same authenticator back to the victim&apos;s own machine and be accepted as the victim [@cve-2008-4037]. It sits in the SMBRelay lineage that opened our timeline [@cdc-smbrelay].&lt;/p&gt;
&lt;p&gt;The toggle is a direction tag. Remove it and the value a client produces is exactly the value a server will accept, so the reflection works. Restore a role offset -- so the two directions compute different values -- and the reflected response no longer matches.&lt;/p&gt;
&lt;p&gt;{`
// A symmetric response: both ends compute the same function of nonce and key.
function respond(key, nonce, role) {
  let acc = 0;
  for (const ch of (role + key + nonce)) acc = (acc * 33 + ch.charCodeAt(0)) % 1000003;
  return acc;
}&lt;/p&gt;
&lt;p&gt;const key = &quot;shared-session-key&quot;;
const nonce = &quot;server-nonce-1234&quot;;&lt;/p&gt;
&lt;p&gt;// No direction tag: what a client sends equals what a server would accept.
const clientSends = respond(key, nonce, &quot;&quot;);
const serverAccepts = respond(key, nonce, &quot;&quot;);
console.log(&quot;reflected response accepted, no tag:&quot;, clientSends === serverAccepts); // true&lt;/p&gt;
&lt;p&gt;// With a direction tag, the two directions diverge and reflection fails.
const clientTagged = respond(key, nonce, &quot;client-to-server&quot;);
const serverTagged = respond(key, nonce, &quot;server-to-client&quot;);
console.log(&quot;reflected response accepted, tagged:&quot;, clientTagged === serverTagged); // false
`}&lt;/p&gt;
&lt;p&gt;There is one place this pattern is easy to overclaim, and the honesty frame of this whole article depends on not doing so.In my Tamarin model of &lt;code&gt;[MS-NRPC]&lt;/code&gt;, a client may pick its Netlogon &lt;code&gt;NetrServerAuthenticate3&lt;/code&gt; challenge to coincide with the server&apos;s -- a &lt;em&gt;structural&lt;/em&gt; reflection the symbolic model can express. This is a modeling observation, not a separately published Netlogon weakness; the famous Zerologon escalation turns on the computational AES-CFB8 zero-IV weakness that a perfect-crypto model cannot represent. Zerologon appears here only as the Section 9 boundary illustration -- encoded as an equation, never discovered [@cve-2020-1472].&lt;/p&gt;
&lt;h3&gt;Pattern 4: Identity-binding gaps in signed tokens&lt;/h3&gt;
&lt;p&gt;The fourth pattern is a signed thing -- a reply, a ticket, an assertion, a certificate -- that is correctly signed and yet fails to bind &lt;em&gt;who&lt;/em&gt; it is for. PKINIT is the textbook case: the KDC&apos;s reply was not bound to the requesting client&apos;s identity, the gap Cervesato and colleagues formalized [@cjstw-infcomput]. In Diffie-Hellman mode this becomes an unknown-key-share risk, where a client can be steered into misattributing a key. The fix binds the request itself with the &lt;code&gt;paChecksum&lt;/code&gt; defined in RFC 4556 Section 3.2.1, a checksum over the request body [@rfc4556]. RFC 8636 later made its hash negotiable under &quot;paChecksum Agility&quot; -- it did not add the field, it standardized the field&apos;s agility [@rfc8636].&lt;/p&gt;
&lt;p&gt;The same gap appears wherever a token crosses a trust boundary. SAML single sign-on needed an audience restriction so an assertion minted for one service could not be redirected to another [@armando-saml]. AD CS certificate enrollment needed the issued certificate&apos;s subject bound to the requester&apos;s real identity -- absent that, the Certifried technique let a low-privilege account enroll a certificate for a domain controller [@cve-2022-26923], a later escalation across the &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;AD CS attack surface&lt;/a&gt; that SpecterOps&apos;s Certified Pre-Owned had first mapped in June 2021 [@specterops-cpo]. OAuth&apos;s on-behalf-of exchange needs its token audience checked to avoid a confused-deputy redirection [@rfc6819], and device registration needs a proof-of-possession binding so a bearer token cannot be replayed against a key the device never held [@rfc7800].&lt;/p&gt;
&lt;h3&gt;Pattern 5: Delegation and composition&lt;/h3&gt;
&lt;p&gt;The fifth pattern is the subtlest, because every component is sound on its own. The failure lives in the &lt;em&gt;chain&lt;/em&gt;. Kerberos constrained delegation lets a service act on a user&apos;s behalf, gated by whether a ticket is marked forwardable. The Bronze Bit technique flipped that restriction: a compromised service could tamper with a service ticket that was not valid for delegation and force the KDC to accept it, because the relevant integrity was not protected by the KDC&apos;s own ticket signature [@cve-2020-17049]. Restore the check on the &lt;code&gt;krbtgt&lt;/code&gt; ticket signature and the tampered ticket is rejected [@netspi-bronzebit].&lt;/p&gt;
&lt;p&gt;Composition multiplies the surface. Resource-based constrained delegation chains can be assembled into escalation paths that no single hop authorizes [@shamir-wagging]. A cross-protocol NTLM relay shares one credential across SMB, LDAP, and CredSSP at once, so a binding omitted in any one leg reopens the whole composition. And IKE&apos;s cross-mode confusion is a composition failure at the key-exchange layer, where mixing modes defeats a property each mode satisfies alone [@cremers-ipsec].&lt;/p&gt;

You can run these five questions against a protocol you have never modeled formally and never will: channel binding, keyed integrity, direction tags, identity binding, and a restriction that survives composition. Asked of a design document, they catch the families behind two decades of Windows-auth CVEs before any of them ships. Section 11 turns them into a checklist, each paired with the fix that already exists.
&lt;p&gt;Every pattern so far is a way something &lt;em&gt;broke&lt;/em&gt;. But the instrument that exhibits a break can also prove a guarantee -- and when I pushed twelve of these models under stronger attackers, what came back was not new bugs but stronger proofs. What did the deep models actually prove?&lt;/p&gt;
&lt;h2&gt;7. What the Deep Models Proved&lt;/h2&gt;
&lt;p&gt;A prover does not only produce counterexamples. When a lemma holds, you get a proof -- a statement that across every run, under this attacker, nothing violates the property. So I took twelve of the models and deepened them: same protocols, stronger attacker. The headline stayed the same. No new breaks. What changed is that the guarantees got stronger, and I can say precisely which attacker capability each one now survives. Everything below is my Tamarin verification within the Dolev-Yao model, each item anchored to the public specification or CVE it concerns -- not an independently published finding.&lt;/p&gt;

A session&apos;s keys stay secret even if the parties&apos; long-term keys are compromised later. Traffic captured today remains protected against a key leak tomorrow, because the session key depended on ephemeral values that no longer exist [@rfc4556].

Compromising a party&apos;s own long-term key obviously lets an attacker impersonate that party. KCI resistance is the narrower guarantee that it does not *also* let the attacker impersonate other parties *to* the compromised one [@cremers-ipsec].
&lt;p&gt;The deepenings follow a single recipe: add an attacker capability the per-protocol models had assumed away, then see which lemma still holds.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Guarantee&lt;/th&gt;
&lt;th&gt;Attacker capability added&lt;/th&gt;
&lt;th&gt;Lemma that still holds&lt;/th&gt;
&lt;th&gt;Public anchor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Forward secrecy, PKINIT-DH&lt;/td&gt;
&lt;td&gt;reveal &lt;em&gt;both&lt;/em&gt; client and KDC long-term signing keys after the run&lt;/td&gt;
&lt;td&gt;AS reply key stays secret; only the two ephemerals protect it&lt;/td&gt;
&lt;td&gt;[@rfc4556]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KCI resistance, PKINIT-DH&lt;/td&gt;
&lt;td&gt;compromise the client&apos;s own long-term key&lt;/td&gt;
&lt;td&gt;client still authenticates the genuine KDC&lt;/td&gt;
&lt;td&gt;[@rfc4556]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mutual auth and PFS, IPsec IKE&lt;/td&gt;
&lt;td&gt;ephemeral reveal, then &lt;em&gt;both&lt;/em&gt; parties&apos; long-term keys&lt;/td&gt;
&lt;td&gt;injective mutual authentication and forward secrecy survive&lt;/td&gt;
&lt;td&gt;[@cremers-ipsec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid PQ-KEX transcript binding&lt;/td&gt;
&lt;td&gt;reveal &lt;em&gt;both&lt;/em&gt; the DH and KEM legs (both-leg compromise)&lt;/td&gt;
&lt;td&gt;acceptance still binds the genuine transcript and key&lt;/td&gt;
&lt;td&gt;author&apos;s Tamarin model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-channel bindings under composition&lt;/td&gt;
&lt;td&gt;one shared NTLMv2 credential feeding SMB, LDAP, and CredSSP under a relay attacker&lt;/td&gt;
&lt;td&gt;each acceptor&apos;s binding holds inside the composition&lt;/td&gt;
&lt;td&gt;[@cve-2019-1040] [@cve-2018-0886] [@cve-2017-8563] [@rfc5929]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SID filtering and Silver-Ticket containment&lt;/td&gt;
&lt;td&gt;cross-domain referrals, the full four-signature PAC, and service-key reveal&lt;/td&gt;
&lt;td&gt;external forests stay contained; DC-validated PACs defeat Silver Tickets&lt;/td&gt;
&lt;td&gt;[@ms-pac]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bronze-Bit and Protected-User non-delegation&lt;/td&gt;
&lt;td&gt;arbitrary service-key compromise across S4U, RBCD, and PKINIT at once&lt;/td&gt;
&lt;td&gt;every delegated impersonation traces to a legitimate KDC grant; Protected Users are never delegated&lt;/td&gt;
&lt;td&gt;[@cve-2020-17049] [@protected-users] [@shamir-wagging]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A few deserve a sentence. PKINIT&apos;s public-key-encryption mode structurally &lt;em&gt;cannot&lt;/em&gt; offer forward secrecy, because the reply key arrives encrypted to a long-term key; the DH mode can, and the deepened model proves it does even when both signing keys leak after the run [@rfc4556]. The hybrid post-quantum result is the strongest-sounding and has no public primary, so I flag it as model-only: binding the KEM ciphertext into the transcript keeps a client&apos;s acceptance tied to the genuine server even when both the classical and post-quantum legs are revealed. The delegation result matters most operationally: a &lt;a href=&quot;https://paragmali.com/blog/who-is-allowed-to-log-in-where-the-kdc-side-answer-to-creden/&quot; rel=&quot;noopener&quot;&gt;Protected Users account&lt;/a&gt; is never delegated by any path -- classic, resource-based, or PKINIT-issued -- even under arbitrary service-key compromise [@protected-users].&lt;/p&gt;
&lt;p&gt;Honesty requires one scar on this table.One deepening did not yield an independent re-proof in my sandbox. The heaviest cross-domain four-signature-PAC model exhausted memory -- an out-of-memory EXIT 137 -- before Tamarin terminated. I record that result as reported, not independently re-proved [@ms-pac]. A guarantee I cannot re-derive is a guarantee I report with an asterisk, not one I assert.&lt;/p&gt;
&lt;p&gt;These proofs are strong, but they are exactly as strong as the model they live in -- no stronger. So the fair next question is how Tamarin compares with the other instruments on the bench, and, more pointedly, what it is choosing not to see.&lt;/p&gt;
&lt;h2&gt;8. Symbolic, Computational, and the Tools Between&lt;/h2&gt;
&lt;p&gt;Tamarin was the right instrument for this corpus, but it is one of several, and the honest comparison is about what each one buys and what it costs. The computer-aided cryptography community&apos;s own survey lays out the taxonomy, and I follow it here [@sok-cac].&lt;/p&gt;
&lt;p&gt;The first split is the model. Symbolic tools -- Tamarin, ProVerif, Scyther -- work in the Dolev-Yao world of perfect cryptography and reason about protocol logic. Computational tools -- CryptoVerif, EasyCrypt -- model the attacker as a probabilistic polynomial-time algorithm and produce bounds on its success probability [@sok-cac]. They answer different questions, which is why a single benchmark number rarely transfers between them.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Termination&lt;/th&gt;
&lt;th&gt;DH and state&lt;/th&gt;
&lt;th&gt;Style&lt;/th&gt;
&lt;th&gt;Best at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Tamarin&lt;/td&gt;
&lt;td&gt;symbolic, Dolev-Yao&lt;/td&gt;
&lt;td&gt;may not terminate&lt;/td&gt;
&lt;td&gt;DH plus mutable state, unbounded&lt;/td&gt;
&lt;td&gt;automated and interactive&lt;/td&gt;
&lt;td&gt;stateful key exchange, proofs and attack traces [@tamarin-cav]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ProVerif&lt;/td&gt;
&lt;td&gt;symbolic, applied pi and Horn clauses&lt;/td&gt;
&lt;td&gt;usually terminates, over-approximates&lt;/td&gt;
&lt;td&gt;limited state&lt;/td&gt;
&lt;td&gt;automated&lt;/td&gt;
&lt;td&gt;fast unbounded analysis, but can report false attacks [@proverif-home]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scyther&lt;/td&gt;
&lt;td&gt;symbolic, pattern refinement&lt;/td&gt;
&lt;td&gt;guaranteed on its protocol class&lt;/td&gt;
&lt;td&gt;limited&lt;/td&gt;
&lt;td&gt;automated&lt;/td&gt;
&lt;td&gt;guaranteed termination on a restricted class [@scyther-repo] [@scyther-cav-2008-tool]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CryptoVerif&lt;/td&gt;
&lt;td&gt;computational, game-based&lt;/td&gt;
&lt;td&gt;semi-automated&lt;/td&gt;
&lt;td&gt;not applicable&lt;/td&gt;
&lt;td&gt;guided&lt;/td&gt;
&lt;td&gt;concrete probability bounds [@cryptoverif-home]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EasyCrypt&lt;/td&gt;
&lt;td&gt;computational, proof assistant&lt;/td&gt;
&lt;td&gt;manual&lt;/td&gt;
&lt;td&gt;not applicable&lt;/td&gt;
&lt;td&gt;interactive&lt;/td&gt;
&lt;td&gt;primitive-level and game-based proofs [@easycrypt-home]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Why Tamarin for Windows authentication, then? Because these protocols need Diffie-Hellman and post-quantum KEMs, credential state that mutates as tickets are issued, unbounded sessions, and both proofs and concrete attack traces in one tool [@tamarin-cav]. ProVerif is often faster, but its Horn-clause over-approximation makes stateful DH flows awkward and can surface attacks that do not really exist [@proverif-home]. Scyther guarantees termination, but only on a restricted protocol class that this corpus repeatedly steps outside of [@scyther-repo]. The pattern-refinement technique behind Scyther is worth reading in its own right [@scyther-ccs-2008].&lt;/p&gt;
&lt;p&gt;Could a symbolic proof simply hand off to a computational guarantee? Sometimes, and that bridge has a name.&lt;/p&gt;

A theorem that carries a symbolic proof over to a computational guarantee, provided the cryptographic primitives satisfy specific conditions. The Abadi-Rogaway results established it for formal encryption, but only under strong, primitive-specific side-conditions [@abadi-rogaway-ifip]. There is no universal computational-soundness theorem [@abadi-rogaway-joc].
&lt;p&gt;So the bridge is real but partial, which is why the survey&apos;s recommendation is not &quot;pick the best tool&quot; but &quot;combine them&quot;: symbolic for protocol logic at scale, computational for primitive strength, and a third layer for the code [@sok-cac]. That third layer is the active frontier. DY* embeds Dolev-Yao symbolic analysis as a library for executable F* code and used it to mechanize Signal end to end, closing the gap between a model and the program that ships [@dystar-ieee] [@dystar-repo]. Verifpal trades some expressiveness for a gentler modeling language with formal semantics, aiming to lower the rate of modeling mistakes [@verifpal-eprint].&lt;/p&gt;
&lt;p&gt;Every one of those tools, the symbolic ones especially, shares a single blind spot. It is not a defect in any implementation. It is the definition of the model itself -- and it is where this article has been heading all along.&lt;/p&gt;
&lt;h2&gt;9. The Boundary the Method Cannot Cross&lt;/h2&gt;
&lt;p&gt;Return to the question from the first paragraph: was Kerberos broken, or did it just look broken? The honest answer is that a perfect-crypto model can prove a protocol&apos;s &lt;em&gt;logic&lt;/em&gt; sound and still be completely blind to a flaw that ships a domain takeover. Two results make that boundary precise, and neither is a defect you could engineer away.&lt;/p&gt;
&lt;p&gt;The first is about decidability. Durgin, Lincoln, Mitchell, and Scedrov showed that secrecy for protocols with an unbounded number of sessions is undecidable [@dlms-2004]. Restrict to a bounded number of sessions and the problem becomes &quot;merely&quot; NP-complete, as Rusinowitch and Turuani proved [@rusinowitch-turuani]. Put those together and you get a hard fact about tooling: no symbolic verifier can be simultaneously sound, complete, and guaranteed to terminate. Each tool gives up one. Tamarin may not terminate; ProVerif sacrifices completeness and can report false attacks; Scyther restricts the protocol class it accepts [@sok-cac].&lt;/p&gt;
&lt;p&gt;The second boundary is sharper, and it is the heart of the whole article. The Dolev-Yao model abstracts cryptography to perfect operations, so it provably cannot represent a flaw that lives in the cryptographic arithmetic itself. Zerologon is the flagship example. The Netlogon credential used AES in CFB8 mode with an all-zero initialization vector, and with probability $\approx 1/256$ per attempt an all-zero plaintext produced an all-zero ciphertext, letting an unauthenticated attacker forge the credential and ultimately seize a domain controller [@cve-2020-1472]. The mechanism is laid out in the disclosure whitepaper [@secura-zerologon]. No symbolic model sees this, because the model has no notion of an IV, a block-cipher mode, or a $1/256$ probability. There is nothing to find.&lt;/p&gt;

flowchart TD
    F[A protocol failure] --&amp;gt; Q{&quot;Is it in the message logic or in the cryptographic arithmetic?&quot;}
    Q --&amp;gt;|Message logic| S[Symbolic model sees it: relay, reflection, missing binding, signature confusion]
    Q --&amp;gt;|Cryptographic arithmetic| C[Symbolic model is blind: zero-IV, weak hash, probability gaps]
    C --&amp;gt; Z[Zerologon lives here, encoded as an equation, never discovered]
    S --&amp;gt; V[Tamarin can verify or falsify]
&lt;p&gt;This is why the article has been so insistent about one phrase. Where the corpus shows a computational consequence, it &lt;em&gt;encoded&lt;/em&gt; the published weakness as an equation in the model; it did not find it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A symbolic prover that &quot;reproduces&quot; Zerologon has not discovered anything about the cipher. It has had the weakness hand-fed to it as an algebraic identity. Reporting an encoded computational flaw as a symbolic finding is the single most tempting way to overclaim with these tools, and it is wrong every time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A proof inherits the blind spots of its model. &quot;Verified in Tamarin&quot; means the protocol logic holds against a Dolev-Yao attacker -- it says nothing about the primitives, the probabilities, or the implementation. Always validate the model against the specification, and never read &quot;verified&quot; as &quot;safe.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The boundary is the result, not a failure. Unbounded verification is undecidable, and a perfect-crypto model provably cannot represent a probabilistic flaw. So &quot;nothing new across a well-studied corpus&quot; is not an anticlimax. It is the model telling you, precisely, that the protocol logic is sound and that whatever risk remains must live one layer down. That is the most useful thing a symbolic prover can say -- and it can only say it honestly if you respect the wall.&lt;/p&gt;
&lt;/blockquote&gt;

Verified means: within this model, against this adversary, no trace violates this property. Nothing more, and nothing less.
&lt;p&gt;The boundary also tells you which famous attacks were never in scope to begin with.&lt;/p&gt;

Kerberoasting [@attack-t1558-003] and AS-REP roasting [@attack-t1558-004] are offline password cracking. Pass-the-Hash is credential theft [@attack-t1550-002]. Golden and Silver tickets are forgeries that start from a compromised key [@attack-t1558-001] [@attack-t1558-002]. DCSync is permission abuse over a replication interface [@attack-t1003-006]. None of these is a protocol-logic flaw, so a perfect-crypto symbolic model cannot see them -- not because the model failed, but because they live, by definition, outside it. A model can encode a stolen key and check whether a containment holds; it cannot &quot;discover&quot; theft as a logic bug.
&lt;p&gt;If the boundary is permanent -- and it is -- then the most interesting questions live right up against it. Where does the method, and this particular corpus, still strain?&lt;/p&gt;
&lt;h2&gt;10. Where the Method Still Strains&lt;/h2&gt;
&lt;p&gt;The boundary is not the end of the work; it is where the hardest open problems begin. Five of them bound this corpus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Computational soundness at full-protocol scale.&lt;/strong&gt; The dream is to lift a symbolic proof of a deployed protocol automatically to a computational guarantee covering the real primitives -- exactly the gap that hides Zerologon-class flaws. Soundness theorems exist, but only for restricted primitives and conditions [@abadi-rogaway-ifip]. The working answer today is the survey&apos;s layered stack -- combine symbolic, computational, and code-level tools -- not a universal bridge [@sok-cac].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Termination with full algebraic theories.&lt;/strong&gt; Tamarin reasons about Diffie-Hellman and exclusive-or, but with those theories it may not terminate, and terminating results exist only for restricted equational fragments such as Scyther&apos;s class. The undecidability wall keeps this an open trade between expressiveness and automation [@dlms-2004].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Composition and whole deployments.&lt;/strong&gt; Composition theorems are provable for specific seams -- per-channel bindings survive a shared-credential relay, for instance. But scaling to a whole interacting deployment is unsolved, and this corpus hit the wall directly: the heaviest cross-domain four-signature-PAC model exhausted memory on independent re-proof, a concrete state-explosion failure rather than a theoretical one [@cremers-ipsec].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Privacy and equivalence at scale.&lt;/strong&gt; Secrecy and authentication are reachability properties. Privacy properties -- unlinkability, anonymity -- are equivalence properties, which are markedly harder and scale worse. Tamarin&apos;s observational equivalence and ProVerif&apos;s equivalence checking handle modest protocols, but the frontier here is genuinely hard [@sok-cac].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;From verified models to verified deployments.&lt;/strong&gt; A proof about a model is only as good as the model&apos;s fidelity to the running code. DY* mechanized Signal end to end from executable F* code [@dystar-ieee], and Verifpal lowers the modeling-error rate with friendlier semantics [@verifpal-eprint]. But &lt;code&gt;[MS-*]&lt;/code&gt; implementations are closed, so for this corpus model fidelity has to be &lt;em&gt;argued&lt;/em&gt; from the public specification rather than mechanically derived from the binaries.&lt;/p&gt;
&lt;p&gt;Those are the frontier&apos;s problems, and none of them has to be solved before the five patterns become useful. Here is what you can do with them this afternoon.&lt;/p&gt;
&lt;h2&gt;11. Auditing With the Five Patterns&lt;/h2&gt;
&lt;p&gt;The taxonomy earns its keep as a checklist. You do not need Tamarin to use it -- you need a specification, a design review, and five questions. Each maps to a concrete Windows mechanism and a documented fix.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; 1. &lt;strong&gt;Channel binding.&lt;/strong&gt; Is every authenticator bound to the endpoint it is used on? The fix is a TLS channel binding such as &lt;code&gt;tls-server-end-point&lt;/code&gt;, Extended Protection for Authentication, and the SPNEGO &lt;code&gt;mechListMIC&lt;/code&gt; against downgrade [@rfc5929] [@rfc4178]. 2. &lt;strong&gt;Keyed integrity.&lt;/strong&gt; Is every integrity check keyed, never a bare checksum? The fix is the keyed PAC signature MS14-068 should have required [@cve-2014-6324]. 3. &lt;strong&gt;Direction tags.&lt;/strong&gt; Does every symmetric credential carry a direction or role tag? In a model the remedy is a direction/role offset; MS08-068 itself shipped it as reflection/replay detection -- the SMB endpoint records the challenge it issued and rejects an authenticator that comes back carrying it [@ms08-068]. 4. &lt;strong&gt;Identity binding.&lt;/strong&gt; Does every signed token bind requester, key, and audience? For PKINIT that is the &lt;code&gt;paChecksum&lt;/code&gt; request-binding of RFC 4556 Section 3.2.1, whose hash RFC 8636 made agile [@rfc4556] [@rfc8636]. 5. &lt;strong&gt;Delegation.&lt;/strong&gt; Does every delegation chain keep its restriction under composition? The fix is the &lt;code&gt;krbtgt&lt;/code&gt; ticket signature Bronze Bit bypassed [@cve-2020-17049].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A &quot;no&quot; to any question does not prove a break -- it tells you where to look first, and which published fix already exists. That is the difference between a taxonomy and a vulnerability scanner: the taxonomy makes you faster at the questions, not lazier about the answers.&lt;/p&gt;
&lt;p&gt;If you go further and model a protocol yourself, the corpus&apos;s method carries two warnings worth repeating.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Keep each flawed/fixed pair minimal: toggle exactly one mechanism, so a falsification points at one cause. Always add a control that re-enables the mechanism and flips the verdict back, or you cannot tell a real break from a modeling artifact. Validate the model against the specification it claims to represent. And never report an encoded probabilistic flaw as a symbolic finding [@sok-cac].&lt;/p&gt;
&lt;/blockquote&gt;

The most common channel-binding gaps in a real domain are LDAP, RDP, and SMB. Microsoft&apos;s guidance is to move `LdapEnforceChannelBinding` toward enforcement once clients are ready [@kb4034879], following the staged requirements in the LDAP hardening advisory [@adv190023] and its companion timeline [@kb4520412]; to keep CredSSP patched so the `pubKeyAuth` binding is enforced [@cve-2018-0886]; and to require SMB signing so a relayed session cannot be tampered mid-stream [@ms-smb-signing]. None of these is exotic -- they are Pattern 1, three times.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;formally-verifying-windows-authentication&quot; keyTerms={[
  { term: &quot;Channel binding&quot;, definition: &quot;Tying an inner authenticator to the outer channel or endpoint it travels on, so it cannot be relayed elsewhere.&quot; },
  { term: &quot;Keyed vs unkeyed integrity&quot;, definition: &quot;A MAC or signature requires a secret to produce; a checksum does not, so an unkeyed check is forgeable by anyone.&quot; },
  { term: &quot;Credential reflection&quot;, definition: &quot;Bouncing a symmetric authenticator back at its sender when it carries no direction or role tag.&quot; },
  { term: &quot;Identity binding&quot;, definition: &quot;Binding a signed token to its requester, key, and intended audience so it cannot be substituted or redirected.&quot; },
  { term: &quot;Delegation and composition&quot;, definition: &quot;Preserving a delegation restriction across chains and across protocols that share a credential.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;Run those five questions and you are doing by hand what the corpus did by machine. Which leaves only the questions people ask out loud when they hear the phrase &quot;I verified Windows authentication and found nothing.&quot;&lt;/p&gt;
&lt;h2&gt;12. Questions People Ask&lt;/h2&gt;


No, and that is the point. Every break in this article was already published, with its own CVE, RFC, or paper. The contribution is not a bug; it is the unified, machine-checked taxonomy that shows these breaks are five recurring shapes rather than two dozen unrelated accidents. Finding zero new vulnerabilities across a corpus this well-studied is the evidence the taxonomy is real, not a disappointment.


No -- &quot;verified&quot; and &quot;secure&quot; are different claims. A Dolev-Yao proof certifies that the protocol *logic* holds against the modeled adversary, and nothing more: the strength of the primitives, the probabilities, and the shipped implementation all sit outside the model. Section 9 draws that line precisely and explains why a clean proof narrows where the remaining risk can live without eliminating it.


No. Zerologon is a computational flaw -- AES in CFB8 mode with a zero initialization vector -- that a perfect-crypto symbolic model cannot represent [@cve-2020-1472]. In my Tamarin model, Netlogon also exhibits a structural reflection a symbolic prover can express -- a modeling observation, not a separately published Netlogon weakness -- but the real escalation turns on that arithmetic weakness, which a symbolic model can only be told about, not derive. Section 6 introduces the distinction where the pattern appears, and Section 9 places it exactly on the symbolic/computational boundary.


No. The computational layer -- primitives, key sizes, probabilities -- and the implementation layer are both outside symbolic scope. A clean symbolic proof narrows where the risk can live; it does not eliminate it. The right move is to combine symbolic, computational, and code-level tools [@sok-cac].


Because a single one-adversary model turns scattered analogies into a checked taxonomy, and because the same models prove *positive* guarantees that the per-CVE view could never produce -- forward secrecy, key-compromise-impersonation resistance, delegation containment under composition [@cremers-ipsec]. The known breaks are the calibration; the guarantees and the structure are the payoff.


Both, for different questions. Symbolic analysis scales to protocol logic across a whole corpus; computational analysis bounds the strength of the primitives; code-level analysis binds a model to the program that runs. The survey&apos;s recommendation is a layered stack, not a single winner [@sok-cac].


Section 8 has the full tool-by-tool comparison; the short answer is that ProVerif&apos;s speed advantage does not buy much here. The features that define this corpus -- Diffie-Hellman and post-quantum KEM key exchange, credentials whose state changes with every issued ticket, and unbounded sessions that need a concrete counterexample when a proof fails -- are exactly the combination that falls outside ProVerif&apos;s comfortable analysis fragment and lands inside Tamarin&apos;s [@tamarin-cav] [@proverif-home].

&lt;p&gt;So: was Windows authentication broken, or did it just look broken? The answer the corpus gives is precise. Twenty-three protocols, one adversary, twelve of them pushed harder -- and every break it could exhibit was one already on the record, each reducible to one of five structural shapes: a missing channel binding, an unkeyed integrity check, an untagged symmetric credential, an unbound token, or a restriction that dissolves under composition. The same models that exhibit those breaks also prove the fixes hold, even when you hand the attacker more power than the original analyses dared.&lt;/p&gt;
&lt;p&gt;The shapes themselves are old news. Channel binding, keyed integrity, direction tags, audience binding, and delegation protection were each understood when they were each invented. What was missing was a way to say, in one breath and with a machine to back it, that they are the &lt;em&gt;same five mistakes&lt;/em&gt; recurring across protocols that share no code -- and to draw the line, exactly, where a symbolic prover stops seeing and Zerologon&apos;s arithmetic begins.&lt;/p&gt;
&lt;p&gt;That line is the gift. It tells you that &quot;nothing new&quot; is not the tool shrugging; it is the tool reporting, honestly, that the logic is sound and the remaining risk lives one layer down. Carry the five questions with you. The next authentication protocol has not been written yet -- but when it is, you already know the five ways it is most likely to break.&lt;/p&gt;
</content:encoded><category>formal-verification</category><category>windows-authentication</category><category>tamarin-prover</category><category>kerberos</category><category>ntlm</category><category>dolev-yao</category><category>protocol-security</category><category>symbolic-analysis</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;No (per-exchange challenge + timestamp added to the response, not a hash salt)&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 the 16-byte MD5 hash of the GSS channel-bindings structure; for TLS EPA, that structure carries the RFC 5929 &lt;code&gt;tls-server-end-point&lt;/code&gt; certificate hash, binding the authentication to the HTTPS channel 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].

An MD5 hash of the GSS channel-bindings structure (which carries the server&apos;s `tls-server-end-point` certificate hash) 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 enforcement as off, when-supported, and required (WCF `Never` / `WhenSupported` / `Always`) [@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 AD CS web endpoint runs with EPA disabled or merely opportunistic (WCF &lt;code&gt;policyEnforcement=&quot;Never&quot;&lt;/code&gt; or &lt;code&gt;&quot;WhenSupported&quot;&lt;/code&gt;), the binding is not enforced. 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>