<?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: windows-authentication</title><description>Posts tagged windows-authentication.</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/windows-authentication/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>Inside the Primary Refresh Token: The Cryptographic Seam Between Windows Logon and Microsoft Entra ID</title><link>https://paragmali.com/blog/inside-the-primary-refresh-token-the-cryptographic-seam-betw/</link><guid isPermaLink="true">https://paragmali.com/blog/inside-the-primary-refresh-token-the-cryptographic-seam-betw/</guid><description>How one TPM-bound JWT issued at first sign-in bridges Windows logon and Microsoft Entra ID -- and how Pass-the-PRT taught Microsoft to bind the derivation to the message.</description><pubDate>Tue, 12 May 2026 00:00:00 GMT</pubDate><content:encoded>
The **Primary Refresh Token (PRT)** is the cryptographic seam where a Windows logon becomes a Microsoft Entra ID transaction. It is a JWT issued by Microsoft Entra ID to the CloudAP plugin in `lsass` at first interactive sign-in on an Entra-registered, Entra-joined, or Entra-hybrid-joined device. The PRT is signed at issuance by a TPM-bound **device key** (`dkpriv`); every downstream artifact -- the `x-ms-RefreshTokenCredential` browser cookie, app-token requests via WAM, Conditional Access claim flow -- is signed by a session key returned encrypted under the device&apos;s **transport key** (`tkpub`). In 2020, Dirk-jan Mollema and Lee Christensen showed that even with TPM-bound keys, admin on the live device could mint cookies anywhere -- the Pass-the-PRT class. Microsoft closed off-device replay with **KDFv2** (CVE-2021-33779, July 2021), then layered Continuous Access Evaluation, Token Protection, and Cloud Kerberos Trust on top. On-device Cookie-on-Demand attacks remain the open residual.
&lt;h2&gt;1. Three sign-ins, one credential&lt;/h2&gt;
&lt;p&gt;A user signs into a freshly enrolled Entra-joined laptop with &lt;a href=&quot;https://paragmali.com/blog/your-face-is-not-your-password-inside-windows-hellos-hardwar/&quot; rel=&quot;noopener&quot;&gt;Windows Hello for Business&lt;/a&gt;. Ten seconds later they open Outlook, which silently authenticates against Microsoft 365. An hour later they type &lt;code&gt;outlook.office.com&lt;/code&gt; into Edge -- and they are already signed in there too.&lt;/p&gt;
&lt;p&gt;Three sign-ins, one credential. The credential was issued during the Windows logon itself, and the user has never seen it.&lt;/p&gt;
&lt;p&gt;This article is about that credential -- the &lt;strong&gt;Primary Refresh Token&lt;/strong&gt; -- and about the cryptographic seam where Windows logon stops being a local NT-style event and becomes a Microsoft Entra ID transaction.&lt;/p&gt;

A device-bound JSON Web Token issued by Microsoft Entra ID to the Cloud Authentication Provider in `lsass.exe` at first interactive sign-in on a Microsoft Entra-registered, Entra-joined, or Entra-hybrid-joined device. The PRT is the artifact every other token broker on the device references to mint app access tokens, browser SSO cookies, and Conditional Access claims for the lifetime of the sign-in session [@prt-msft-learn].
&lt;p&gt;The questions worth asking are concrete. What does that token actually contain? How did it get from &lt;code&gt;lsass&lt;/code&gt; to a browser cookie without the user ever pasting it? Why is the cookie that rides in the browser called &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; when the PRT itself never leaves the device? And -- the question that will define everything in §5 and §6 -- if the credential is bound to a TPM, how did three independent researchers in the summer of 2020 mint cookies anywhere they wanted to?&lt;/p&gt;
&lt;p&gt;The plan is to answer those questions in order. We will name every load-bearing primitive in the stack. We will walk a token request end-to-end. We will explain what the July 2021 KDFv2 patch actually changed at the byte level. And we will be honest about what the PRT cannot do -- because the rest of this series is about the identity surfaces that run alongside it, not under it.&lt;/p&gt;
&lt;p&gt;Before we can read the PRT itself, we have to understand the problem it was built to solve. That means going back to 2013, before Azure AD Join was a thing.&lt;/p&gt;
&lt;h2&gt;2. The cloud-identity gap, 2011 to 2014&lt;/h2&gt;
&lt;p&gt;Windows authentication, in 2011, did not speak cloud. &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; resolved against a local SAM database. &lt;a href=&quot;https://paragmali.com/blog/kerberos-in-windows-the-other-half-of-ntlmless/&quot; rel=&quot;noopener&quot;&gt;Kerberos&lt;/a&gt; resolved against an on-prem Key Distribution Center. Both predate the notion of a cloud identity provider by more than a decade. When a Windows endpoint authenticated, it talked to a domain controller it could see on the network -- and if it could not see a domain controller, it talked to the local SAM and called it a day.&lt;/p&gt;
&lt;p&gt;For a cloud-only workload, that left a gap shaped like a question. Where, exactly, does the user&apos;s identity live when there is no on-prem domain to resolve it against?&lt;/p&gt;
&lt;p&gt;The first answer was OAuth. RFC 6749 had shipped in October 2012, edited by Dick Hardt while at Microsoft, with refresh tokens explicitly modeled as long-lived bearer credentials redeemed at a token endpoint for short-lived access tokens [@rfc-6749]. Microsoft&apos;s Active Directory Authentication Library -- ADAL -- took the obvious next step: every application that wanted to talk to Microsoft&apos;s cloud APIs got its own client, its own redirect, and its own refresh token. SSO was approximated by sharing the underlying password prompt or, on a domain-joined machine, by hoping Integrated Windows Authentication smuggled the right Kerberos ticket to the right endpoint.&lt;/p&gt;
&lt;p&gt;That patchwork held for a while. It also taught Microsoft two things.&lt;/p&gt;
&lt;p&gt;The first lesson was about Conditional Access. If every app maintained its own refresh-token cache and re-presented credentials independently, the policy engine could only see what each token request happened to surface. Whether the request came from a managed Surface or from an unmanaged consumer laptop was anyone&apos;s guess. The device, in other words, was invisible.&lt;/p&gt;
&lt;p&gt;The second lesson was about the user. Ten apps meant ten silent renewal pipelines, ten password prompts when those pipelines broke, and ten different broker components asking &quot;are you sure?&quot; in slightly different language. The user experience and the security posture were on the same side of the ledger: both wanted a single device-bound credential that every broker could reference.&lt;/p&gt;
&lt;p&gt;The first move was small. On 28 June 2013, Adam Hall announced &lt;strong&gt;Workplace Join&lt;/strong&gt; as part of Windows Server 2012 R2: a device-registration primitive that put an X.509 certificate from the Device Registration Service into Active Directory, so that &quot;users can register their device using Workplace Join which creates a new device object in Active Directory and installs a certificate on the device, allowing IT to take into account the user&apos;s device authentication as part of conditional access policies&quot; [@workplace-join-2013].&lt;/p&gt;
&lt;p&gt;Workplace Join taught the directory that a device existed. It did not make the Windows sign-in itself a cloud event. The artifact it produced was a long-lived certificate, not a session-scoped credential, and it lived on the on-prem AD side of the seam, not the cloud side. For the rest, Microsoft would need a credential the cloud could mint &lt;em&gt;during&lt;/em&gt; the sign-in.&lt;/p&gt;
&lt;p&gt;That credential arrived in 2015 -- but its design took another year to harden.&lt;/p&gt;
&lt;h2&gt;3. Workplace Join, Azure AD Join, and the OAuth-refresh-token patchwork&lt;/h2&gt;
&lt;p&gt;What does it cost a Windows endpoint to authenticate to ten cloud apps if it has no PRT?&lt;/p&gt;
&lt;p&gt;Counting tokens is a good way to find out. Each app maintains its own refresh-token cache. Each refresh redeems against the same &lt;code&gt;login.microsoftonline.com&lt;/code&gt; endpoint but with a different &lt;code&gt;client_id&lt;/code&gt; and a different audience claim. Each app re-asserts the device claim as a separate transaction -- if it can; an app that does not ride a broker can only surface what its own credential flow knows. The architectural failure mode is not that authentication is &lt;em&gt;bad&lt;/em&gt;; it is that authentication is &lt;em&gt;redundant&lt;/em&gt;, and the policy engine sees a hundred small claims instead of one big one.&lt;/p&gt;
&lt;p&gt;Microsoft walked out of that failure mode in three steps.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step one (June 2013): Workplace Join.&lt;/strong&gt; A device cert, signed by the Device Registration Service, written to a new device object in Active Directory. Adam Hall&apos;s announcement is the load-bearing primary source [@workplace-join-2013]. Nothing about a session: the certificate lives across reboots, across sign-ins, across user accounts. Microsoft now calls this state &lt;strong&gt;Microsoft Entra registered&lt;/strong&gt; -- the same primitive, renamed [@entra-devices-overview].&quot;Workplace Join&quot; was the 2013 marketing name. The same artifact is now called &quot;Microsoft Entra registered&quot; and is the device state used for personal (BYOD) devices that get conditional-access policies applied to corporate workloads. The taxonomy in §3 of the current Microsoft Learn documentation lists three states: Microsoft Entra registered, Microsoft Entra joined, and Microsoft Entra hybrid joined [@entra-devices-overview].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step two (May 2015): Azure AD Join.&lt;/strong&gt; On 28 May 2015, Alex Simons and Gary Henderson announced that Windows 10, build 1507, would let a device sign in against a cloud-only Microsoft identity at first boot. &quot;Azure AD join is optimized for users that primarily access cloud resources,&quot; the announcement reads -- a quiet way of saying that for the first time, a Windows machine did not need a domain controller on the network to give a user a sign-in surface [@techcomm-azure-ad-join-2015].&lt;/p&gt;
&lt;p&gt;This 28 May 2015 Tech Community post is the corrected primary source. An older URL in the same series (&lt;code&gt;.../ba-p/247010&lt;/code&gt;) was re-tagged by Microsoft&apos;s CMS to a 2010 RemoteFX article and now resolves to unrelated content; the 244005 post is the load-bearing technical announcement.&lt;/p&gt;
&lt;p&gt;The Azure AD Join story introduced one more component: &lt;strong&gt;CloudAP&lt;/strong&gt;, the Cloud Authentication Provider, an authentication-package framework hosted inside &lt;code&gt;lsass.exe&lt;/code&gt;. CloudAP is the LSASS-resident broker that an enterprise SSO surface talks to from inside the operating system. It is not yet a PRT engine -- in May 2015, it is mostly a routing layer for cloud sign-in primitives. The PRT itself does not exist yet.&lt;/p&gt;

A pluggable authentication-package framework introduced inside `lsass.exe` to host cloud-identity sign-in plugins. The Microsoft Entra ID plugin (`aadcloudap.dll`) is the canonical implementation; CloudAP is the LSASS-resident broker that, from Windows 10 1607 onward, owns the device-side PRT lifecycle on Entra-joined and Entra-hybrid-joined machines [@prt-msft-learn].
&lt;p&gt;&lt;strong&gt;Step three (August 2016): the first PRT.&lt;/strong&gt; Windows 10, version 1607 -- the Anniversary Update -- began rolling out on 2 August 2016 [@win10-anniv-1607]. In that build, CloudAP gained an Entra ID plugin that minted a PRT during interactive sign-in, alongside a &lt;a href=&quot;https://paragmali.com/blog/the-tpm-in-windows-one-primitive-twenty-five-years-and-the-c/&quot; rel=&quot;noopener&quot;&gt;TPM&lt;/a&gt;-bound key pair for proof of possession. From that moment, every other broker on the machine -- the Web Account Manager that backed native apps, Edge for browser SSO, third-party &lt;code&gt;mstsc&lt;/code&gt; flows that wanted to redirect a sign-in -- had a single artifact to reference. The architectural gap from §2 closed; the patchwork became a stack.&lt;/p&gt;
&lt;p&gt;By the time Microsoft Open Specifications publication MS-OAPXBC went public on 16 October 2015, version 1.0 -- contemporaneous with the Windows 10 1507 release, not three years later -- the protocol scaffolding was already in place [@ms-oapxbc-index]. The PRT itself was the credential the scaffolding had been waiting for.&lt;/p&gt;
&lt;p&gt;By 2016, Microsoft had a name for the missing primitive: one device-bound, session-scoped, cloud-issued credential that all brokers could reference. The Anniversary Update made it real. The next question is what that credential &lt;em&gt;is&lt;/em&gt; cryptographically -- and to answer that, we need to be precise about two key pairs that most descriptions of the PRT conflate.&lt;/p&gt;

timeline
    title PRT generations, 2013 to 2022
    2013 : Workplace Join (Windows Server 2012 R2)
         : Device cert in AD; no session credential
    2015 : Azure AD Join (Windows 10 1507)
         : CloudAP framework in lsass; no PRT yet
    2016 : First PRT (Windows 10 1607)
         : CloudAP + Entra plugin issue device-bound JWT
    2020 : Pass-the-PRT class disclosed
         : Christensen + Mollema + Syynimaa
    2021 : KDFv2 (CVE-2021-33779)
         : SHA256 of payload mixed into derivation
    2022 : CAE GA + Cloud Kerberos Trust + TROOPERS 22
         : Composition era begins
&lt;h2&gt;4. The two-key cryptographic model&lt;/h2&gt;
&lt;p&gt;Most descriptions of the PRT online say the cookie is &quot;DKey-signed.&quot; That phrase has been wrong since July 2021. Here is the actual cryptographic substrate.&lt;/p&gt;
&lt;p&gt;When a Windows device joins Microsoft Entra ID -- by way of the Out-of-Box Experience, by &lt;code&gt;dsreg&lt;/code&gt;&apos;s join command, or by the implicit registration that happens on a personal device -- the registration component generates &lt;strong&gt;two&lt;/strong&gt; key pairs on the device. One pair signs PRT &lt;em&gt;issuance&lt;/em&gt; requests. The other unwraps session keys returned &lt;em&gt;with&lt;/em&gt; the PRT. Microsoft&apos;s own documentation enumerates the two pairs the &lt;code&gt;dsreg&lt;/code&gt; component generates at device registration: Device key (&lt;code&gt;dkpub&lt;/code&gt;/&lt;code&gt;dkpriv&lt;/code&gt;) and Transport key (&lt;code&gt;tkpub&lt;/code&gt;/&lt;code&gt;tkpriv&lt;/code&gt;) [@prt-msft-learn].&lt;/p&gt;

The first of the two key pairs minted at Microsoft Entra registration. The private half (`dkpriv`) is TPM-resident on supported hardware (TPM 2.0 from Windows 10 1903 onward) and signs the JWT used to *request* a Primary Refresh Token from Microsoft Entra ID. The public half (`dkpub`) is registered with Microsoft Entra ID at join time and is what Entra ID uses to verify that the request originated from the registered device [@prt-msft-learn].

The second registration-time key pair. Entra ID encrypts the freshly minted PRT session key under `tkpub`; only `tkpriv` -- TPM-resident on supported hardware -- can unwrap it. Every downstream signing operation flows through a key derived from that session key, so the transport key is the asymmetric on-ramp to the device&apos;s symmetric proof-of-possession surface [@prt-msft-learn].

The Windows component that performs Microsoft Entra registration -- mints the device and transport key pairs, registers `dkpub`/`tkpub` with Entra ID, and produces the device certificate that backs the Microsoft Entra device object. `dsregcmd.exe` is its operator-facing interrogation tool; `dsregcmd /status` reports current state including AzureAdPrt, AzureAdPrtUpdateTime, and AzureAdPrtExpiryTime [@prt-msft-learn].
&lt;p&gt;The two-key model is not a typo, and the second-most-common reading of it is wrong. The device key signs &lt;em&gt;the request for&lt;/em&gt; a PRT. The transport key unwraps &lt;em&gt;the session key that arrives with&lt;/em&gt; a PRT. Once unwrapped, the session key signs everything from there on -- not the device key.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The device key signs PRT issuance, once per PRT mint. The transport key unwraps a &lt;em&gt;session key&lt;/em&gt;. Every downstream artifact -- the &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; browser cookie, every WAM-mediated app-token request -- is signed by a key &lt;em&gt;derived from&lt;/em&gt; that session key, not by &lt;code&gt;dkpriv&lt;/code&gt; directly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The eight-step issuance flow makes this explicit.&lt;/p&gt;

sequenceDiagram
    participant User
    participant CloudAP as CloudAP (lsass)
    participant TPM
    participant Entra as Microsoft Entra ID
    participant CA as Conditional Access
    participant WAM
    User-&amp;gt;&amp;gt;CloudAP: 1. Interactive sign-in (Hello, password, FIDO2)
    CloudAP-&amp;gt;&amp;gt;TPM: 2. Sign authorization JWT with dkpriv
    TPM--&amp;gt;&amp;gt;CloudAP: 3. Signed assertion
    CloudAP-&amp;gt;&amp;gt;Entra: 4. Issuance request (signed assertion)
    Entra-&amp;gt;&amp;gt;CA: 5. Evaluate device + user + risk claims
    CA--&amp;gt;&amp;gt;Entra: 6. Issuance permitted
    Entra--&amp;gt;&amp;gt;CloudAP: 7. PRT + session_key encrypted under tkpub
    CloudAP-&amp;gt;&amp;gt;TPM: 8. Unwrap session_key with tkpriv
    Note over CloudAP,WAM: Session key now resident -- WAM, browser SSO, and CAE all derive from it
&lt;p&gt;A user provides an interactive credential -- a Hello gesture, a password, a FIDO2 security key. The CloudAP plugin in &lt;code&gt;lsass&lt;/code&gt; constructs a JWT carrying the user&apos;s authorization material and asks the TPM to sign it with &lt;code&gt;dkpriv&lt;/code&gt;. That signed assertion goes to Microsoft Entra ID. Entra evaluates Conditional Access; if the device, the user, and the risk profile pass policy, Entra returns a PRT (a long-lived JWT) and a fresh session key encrypted under &lt;code&gt;tkpub&lt;/code&gt;. The TPM unwraps the session key with &lt;code&gt;tkpriv&lt;/code&gt;. The session key now lives on the device, in CloudAP&apos;s hot path, available for every broker to use.&lt;/p&gt;

The symmetric key Microsoft Entra ID generates per PRT mint and returns to the device encrypted under `tkpub`. After the TPM unwraps it with `tkpriv`, the session key is the *proof-of-possession key* for the PRT lifetime: every renewal request, every `x-ms-RefreshTokenCredential` cookie, and every app-token request signed via the Web Account Manager is HMAC-signed by a key *derived from* the session key via SP800-108 KDF [@prt-msft-learn] [@ms-oapxbc-jwt].
&lt;p&gt;The session key is the part the rest of this article keeps coming back to. It is the artifact that, in 2020, three independent researchers would prove the TPM was not protecting in the way Microsoft&apos;s documentation implied.&lt;/p&gt;
&lt;p&gt;Once the session key is on the device, the &lt;strong&gt;Web Account Manager (WAM)&lt;/strong&gt; -- the user-mode broker process that handles native-app token requests -- and the browser SSO surface used by Edge, Chrome, and Firefox can mint subordinate artifacts. The most interesting one is a cookie.&lt;/p&gt;

The Windows user-mode broker that mediates access-token requests from native applications to Microsoft Entra ID. WAM presents each app-token request alongside a PRT-derived signed assertion, eliminating the per-app refresh-token cache that the pre-2016 ADAL design required. WAM is the Windows analogue of the Microsoft Enterprise SSO plug-in for Apple devices [@prt-msft-learn] [@apple-sso-plugin-learn].

The HTTP cookie Edge, Chrome, and Firefox attach to requests against `login.microsoftonline.com` and a small set of Microsoft cloud surfaces. It carries a JWT signed with `alg: HS256` whose header field `kdf_ver` indicates whether the cookie used KDFv1 or KDFv2 derivation [@ms-oapxbc-jwt]. The cookie is what makes the third sign-in in the §1 hook -- the silent Edge sign-in to `outlook.office.com` -- not require a credential prompt.
&lt;p&gt;Inside that cookie, the signing key is &lt;strong&gt;derived&lt;/strong&gt; from the session key via the SP800-108 key-derivation function. The label is the constant string &lt;code&gt;AzureAD-SecureConversation&lt;/code&gt;. The context (&lt;code&gt;ctx&lt;/code&gt;) is a per-cookie value chosen by the client. The MS-OAPXBC protocol specification gives the rule verbatim: under KDFv2, &quot;the client MUST use SHA256(ctx || assertion payload) instead of ctx as the context for deriving the signing key&quot; [@ms-oapxbc-jwt]. We will come back to that sentence in §6, because it is &lt;em&gt;the&lt;/em&gt; sentence.Microsoft Learn documents TPM 2.0 as the recommended version for all Microsoft Entra device-registration scenarios on Windows 10 or newer, and states that after the Windows 10 1903 update, Microsoft Entra ID no longer uses TPM 1.2 for any of the PRT keys due to reliability issues. In practice, TPM 2.0 is the only supported configuration on Windows 10 1903 or higher [@prt-msft-learn].&lt;/p&gt;
&lt;p&gt;On supported hardware, both &lt;code&gt;dkpriv&lt;/code&gt; and &lt;code&gt;tkpriv&lt;/code&gt; are non-extractable TPM 2.0 keys. On a device with &lt;a href=&quot;https://paragmali.com/blog/pluton-a-tpm-on-silicon-microsoft-can-patch/&quot; rel=&quot;noopener&quot;&gt;Microsoft Pluton&lt;/a&gt; (a TPM 2.0 implementation embedded in the SoC), the same model applies; Pluton is a TPM 2.0 implementation, not a replacement. On non-TPM Windows -- a virtual machine without a vTPM, a desktop where the TPM is disabled, certain consumer SKUs -- DPAPI is the fallback. DPAPI-protected keys live in user-profile state and can be unwrapped with the user&apos;s credentials, which is a meaningfully weaker contract than TPM non-extractability. We will come back to that distinction in §9.&lt;/p&gt;

The shorthand &quot;the PRT cookie is DKey-signed&quot; was already imprecise before July 2021, and it became actively wrong after the KDFv2 update. The cookie is HMAC-signed with `alg: HS256`, using a symmetric key derived from the *session key* via SP800-108 KDF, not signed with the asymmetric device key. blog.3or.de&apos;s reverse-engineering captures the post-2021 mechanic precisely: &quot;Before CVE-2021-33779, the key to sign the PRT Cookie was derived from the session key using a function that only required a client-chosen `ctx` value. Although the session key and derivation process were handled inside the TPM, the derived key was managed outside the TPM&quot; [@dimi-3or-de-kdfv2]. The asymmetric device key only signs the PRT *issuance* request; everything afterwards is HMAC over a derived key.
&lt;p&gt;If both keys live in the TPM and the cookie is signed with a key derived from a TPM-resident session key, the whole architecture &lt;em&gt;should&lt;/em&gt; make Pass-the-PRT impossible. In 2020, three independent researchers proved it didn&apos;t.&lt;/p&gt;
&lt;h2&gt;5. When TPM-binding is not enough&lt;/h2&gt;
&lt;p&gt;In July 2020, two researchers, working independently, asked the same question: if the session key is in the TPM, can I still mint a PRT cookie?&lt;/p&gt;
&lt;p&gt;The answer, on the architecture Microsoft shipped at the time, was yes -- and the answer came from three angles in less than two months.&lt;/p&gt;

A Primary Refresh Token can be compared to a long-term persistent Ticket Granting Ticket (TGT) in Active Directory... the Primary Refresh Token however can be used to authenticate to any application, and is thus even more valuable. This is why Microsoft has applied extra protection to this token. -- Dirk-jan Mollema, 21 July 2020
&lt;p&gt;&lt;strong&gt;Lee Christensen at SpecterOps, mid-July 2020.&lt;/strong&gt; Christensen&apos;s blog post -- &quot;Requesting Azure AD Refresh Tokens on Azure AD-joined Machines for Browser SSO&quot; -- documented a path through a Component Object Model interface, &lt;code&gt;IProofOfPossessionCookieInfoManager.GetCookieInfoForUri&lt;/code&gt;, that returned a fully signed &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; cookie to a user-mode caller [@christensen-specterops-2020]. The CLSID is &lt;code&gt;{a9927f85-a304-4390-8b23-a75f1c668600}&lt;/code&gt;; the implementation lives in &lt;code&gt;MicrosoftAccountTokenProvider.dll&lt;/code&gt;; the workflow rides through &lt;code&gt;BrowserCore.exe&lt;/code&gt; over a named pipe. Christensen released the proof-of-concept as &lt;code&gt;RequestAADRefreshToken&lt;/code&gt; on GitHub [@gh-requestaadrefreshtoken]. An attacker -- specifically, a process running as the signed-in user -- could call the COM interface, lift the cookie, and paste it into a browser running anywhere on the planet.&lt;/p&gt;
&lt;p&gt;The COM-API path did not require admin. It did not require touching the TPM. It did not need to know anything about the session key. The operating system politely produced a signed cookie because that is what the COM API was built to do, and the contract did not distinguish the legitimate browser from the attacker process.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dirk-jan Mollema, 21 July 2020.&lt;/strong&gt; A week later, Mollema published &quot;Abusing Azure AD SSO with the Primary Refresh Token&quot; on &lt;code&gt;dirkjanm.io&lt;/code&gt;. Mollema&apos;s framing was different: he wanted to understand the PRT as a forensic artifact. The blog opens with the TGT analogy quoted above and explicitly attributes parallel discovery to Christensen [@mollema-prt-2020-07]. The toolchain he documented, ROADtoken, lived inside the larger ROADtools framework that he was building for offensive Azure AD research [@gh-roadtools]. The threat model was the same as Christensen&apos;s: an attacker on the live device could mint cookies, and the TPM was not in the way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mollema, 5 August 2020.&lt;/strong&gt; This is the blog that mattered most. In &quot;Digging further into the Primary Refresh Token,&quot; Mollema reverse-engineered &lt;code&gt;aadcloudap.dll&lt;/code&gt;. He isolated the session-key handling, the cookie-construction routine, the SP800-108 derivation call, the eventual &lt;code&gt;BCryptKeyDerivation&lt;/code&gt;-then-HMAC flow. And he wrote the sentence that, in retrospect, defined the next year of Microsoft&apos;s response: &quot;despite the session key of the PRT is stored in the TPM whenever possible, this doesn&apos;t prevent us from extracting the PRT and the required information to create SSO cookies. The result of this is that regardless of whether the PRT is protected by the TPM or not, with Administrator access it is possible to extract the PRT from LSASS and use the PRT on a different device than it was issued to&quot; [@mollema-prt-2020-08].&lt;/p&gt;

despite the session key of the PRT is stored in the TPM whenever possible, this doesn&apos;t prevent us from extracting the PRT and the required information to create SSO cookies. -- Dirk-jan Mollema, 5 August 2020
&lt;p&gt;The reason is the most important thing in this article. The session key never left the TPM. But the &lt;em&gt;signing key derived from the session key&lt;/em&gt; did. The TPM dutifully performed an SP800-108 derivation -- HMAC-SHA256 with the label &lt;code&gt;AzureAD-SecureConversation&lt;/code&gt; and the client-chosen &lt;code&gt;ctx&lt;/code&gt; value -- and returned the derived key to caller memory. The TPM was protecting the root of the derivation, not the output of it. Once the derived key materialized in &lt;code&gt;lsass&lt;/code&gt;, an admin-with-debug-privilege attacker could simply read it.&lt;/p&gt;
&lt;p&gt;Around the same time, Benjamin Delpy -- the author of Mimikatz -- picked up Mollema&apos;s &quot;challenge&quot; of recovering PRT data from &lt;code&gt;lsass&lt;/code&gt;. Two days after Mollema&apos;s 5 August post, that collaboration produced the Mimikatz release tagged &lt;code&gt;2.2.0-20200807&lt;/code&gt;, which added the &lt;code&gt;sekurlsa::cloudap&lt;/code&gt; and &lt;code&gt;dpapi::cloudapkd&lt;/code&gt; modules [@gh-mimikatz]. The tag URL itself was later collapsed in GitHub&apos;s modern UI -- it returns 404 today, almost certainly because of repeated takedown requests during the Azure-PRT release period -- but a Wayback Machine snapshot from 20 September 2020 preserves the release page and proves the tag existed at the time [@wayback-mimikatz-tag].The GitHub URL &lt;code&gt;https://github.com/gentilkiwi/mimikatz/releases/tag/2.2.0-20200807&lt;/code&gt; returns HTTP 404 in the current GitHub UI; the modern releases list starts at &lt;code&gt;2.2.0-20210729&lt;/code&gt;. The Wayback snapshot at &lt;code&gt;web.archive.org/web/20200920005113/...&lt;/code&gt; preserves the release page (including the &quot;prt3&quot; animated demonstration GIF). Nestori Syynimaa&apos;s AADInternals post and Mollema&apos;s 5 August 2020 blog both reference the same tag URL, which is how we know the artifact was real [@wayback-mimikatz-tag] [@syynimaa-aadinternals-prt] [@mollema-prt-2020-08].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nestori Syynimaa and AADInternals, August through September 2020.&lt;/strong&gt; Syynimaa&apos;s AADInternals PowerShell module shipped &lt;code&gt;Get-AADIntUserPRTToken&lt;/code&gt; as part of v0.4.1 alongside the disclosure. On 29 September 2020, AADInternals&apos; blog post about the tool gained an inline update: &quot;It seems that PRT tokens must now include the &lt;code&gt;request_nonce&lt;/code&gt;. If not, Azure AD sends a redirect with &lt;code&gt;sso_nonce&lt;/code&gt; which must be added to the PRT token. This means that without access to session key, PRT tokens can&apos;t be used anymore&quot; [@syynimaa-aadinternals-prt]. That update is the first observable Microsoft mitigation: Entra ID began demanding that PRT cookies contain a server-issued nonce. It bought time. It did not solve the architectural problem.&lt;/p&gt;

sequenceDiagram
    participant Attacker
    participant LSASS
    participant TPM
    participant COM as IProofOfPossessionCookieInfoManager
    participant Entra as Microsoft Entra ID
    Note over Attacker,LSASS: Attacker has user or admin on the live device
    Attacker-&amp;gt;&amp;gt;LSASS: sekurlsa::cloudap (admin path)
    LSASS--&amp;gt;&amp;gt;Attacker: PRT + derived signing key + context
    Note over Attacker: Or, parallel user-only path:
    Attacker-&amp;gt;&amp;gt;COM: GetCookieInfoForUri(target_url)
    COM--&amp;gt;&amp;gt;Attacker: Pre-baked x-ms-RefreshTokenCredential
    Note over Attacker: Cookie is now portable
    Attacker-&amp;gt;&amp;gt;Entra: Replay cookie from an attacker-controlled host
    Entra--&amp;gt;&amp;gt;Attacker: SSO honored, access token issued
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; With admin on an Entra-joined device in summer 2020, an attacker could lift the PRT and the derived signing key from &lt;code&gt;lsass&lt;/code&gt;, mint fresh &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; cookies on any host they controlled, and pass Conditional Access checks that included the cloned &lt;code&gt;DeviceId&lt;/code&gt; claim. Even without admin, the COM-API path returned signed cookies to a user-context process. The TPM was busy doing exactly what its contract said, and that contract was insufficient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The community quickly settled on a name for this class: &lt;strong&gt;Pass-the-PRT&lt;/strong&gt;. By analogy to Pass-the-Hash and Pass-the-Ticket, the attack is &quot;lift a long-lived authentication artifact from one host, present it as your own elsewhere.&quot; For a credential that the entire cloud sign-in stack was about to trust, the implications were severe.&lt;/p&gt;
&lt;p&gt;By September 2020 Microsoft had bolted a nonce onto the cookie. By July 2021 they had something architecturally different: a single SHA-256 over the cookie&apos;s full payload that killed off-device Pass-the-PRT for good.&lt;/p&gt;
&lt;h2&gt;6. KDFv2 and the death of off-device Pass-the-PRT&lt;/h2&gt;
&lt;p&gt;The fix Microsoft shipped on 13 July 2021 fits on one line.&lt;/p&gt;
&lt;p&gt;The CVE is &lt;strong&gt;CVE-2021-33779&lt;/strong&gt;. NIST&apos;s National Vulnerability Database describes it as &quot;Windows AD FS Security Feature Bypass Vulnerability&quot; and provides no further public detail [@nvd-cve-2021-33779]. Microsoft&apos;s own KDFv2 documentation ties the patch explicitly to that CVE: &quot;On July 13, 2021, updates were released for AD FS to address token replay attacks, as described in CVE-2021-33779. These updates introduce new settings to enable and control a new, Key Derivation Function (KDF) called KDFv2&quot; [@kdfv2-learn].&lt;/p&gt;

The version-2 key-derivation rule introduced for the `x-ms-RefreshTokenCredential` cookie on 13 July 2021. Under KDFv2, the SP800-108 KDF context is `SHA256(ctx || assertion_payload)` rather than the bare client-chosen `ctx` value. The JWT header field `kdf_ver` carries the value `2` to indicate that KDFv2 was used. KDFv1 is preserved for backward compatibility but is disabled by default on a service that has been moved to &quot;Enforced&quot; mode [@ms-oapxbc-jwt] [@kdfv2-learn].
&lt;p&gt;A small subtlety lives in the attribution. NVD names AD FS. The community-side coverage -- blog.3or.de, Mollema&apos;s TROOPERS 22 deck, AADInternals -- names PRT-cookie forgery. The Microsoft KDFv2 page sits in the middle: it ties the patch to CVE-2021-33779 and walks through the same derivation change that closed off-device Pass-the-PRT, but it does not use the term &quot;Pass-the-PRT&quot; on the page itself. We will keep the hedge in mind.&lt;/p&gt;

NVD&apos;s one-line description -- &quot;Windows AD FS Security Feature Bypass Vulnerability&quot; -- is authoritative for the federal CVE record [@nvd-cve-2021-33779]. The community attribution to the Pass-the-PRT class comes from independent reverse-engineering: blog.3or.de&apos;s analysis is the most precise public reading. Both can be true; KDFv2 is the rollout vehicle, and it ships into both AD FS (the on-prem federation server) and the Microsoft Entra ID PRT path. The article reads CVE-2021-33779 as &quot;the rollout vehicle for KDFv2,&quot; not as a one-to-one CVE-to-attack mapping.
&lt;p&gt;The load-bearing rule is one sentence. MS-OAPXBC §3.2.5 puts it like this: &quot;If the client chooses to use KDFv2, the client MUST use &lt;code&gt;SHA256(ctx || assertion payload)&lt;/code&gt; instead of &lt;code&gt;ctx&lt;/code&gt; as the context for deriving the signing key. The client MUST also add the JWT header field &lt;code&gt;kdf_ver&lt;/code&gt; with value set to 2 to communicate that KDFv2 was used for creating the derived signing key&quot; [@ms-oapxbc-jwt].&lt;/p&gt;
&lt;p&gt;To see why that line matters, picture what the attacker in §5 was actually copying. The attacker lifted the derived signing key out of &lt;code&gt;lsass&lt;/code&gt;. The derived signing key was, under KDFv1, a function of the session key (TPM-resident) and the client-chosen context &lt;code&gt;ctx&lt;/code&gt; (any 256 bits the attacker liked). Any cookie the attacker built using the same &lt;code&gt;ctx&lt;/code&gt; would verify against the same derived key. The attacker could pick &lt;code&gt;ctx&lt;/code&gt; first, derive the key once, and stamp out as many cookies as they wanted.&lt;/p&gt;
&lt;p&gt;Under KDFv2, the context is no longer arbitrary. The context is &lt;code&gt;SHA256(ctx || assertion_payload)&lt;/code&gt;. The &lt;code&gt;assertion_payload&lt;/code&gt; is the JWT body the cookie is trying to assert. Change a single claim in the body, and the SHA-256 hash changes, and the SP800-108 derivation produces a different key. A key derived for one cookie cannot sign any other cookie. There is nothing to precompute.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The architectural insight is the same one Kerberos learned with PA-FX-FAST and TLS learned with channel binding: a session-key derivation must be bound to the message being signed, not just to a per-session label. Before KDFv2, the derivation contract was &quot;derive a key for this session, then sign anything.&quot; After KDFv2, the contract is &quot;derive a key for this specific message.&quot; An attacker who exfiltrates the session key off-device cannot precompute a useful signing key; an attacker who exfiltrates a derived signing key for one cookie cannot reuse it for the next. Off-device Pass-the-PRT is dead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The residual is also explicit. The attacker who is still &lt;em&gt;on the device&lt;/em&gt; -- still has a process running as the user or as &lt;code&gt;SYSTEM&lt;/code&gt; -- can ask CloudAP to mint a fresh cookie. The TPM happily performs the new SHA-256-bound derivation, because that is its job; CloudAP returns the signed cookie to the calling process, because that is its job. The blog.3or.de reverse-engineering names this class precisely: &quot;This attack, referred to as Pass-the-PRT-Cookie, still works today but requires presence on the targeted device&quot; [@dimi-3or-de-kdfv2]. Mollema&apos;s TROOPERS 22 talk calls the same residual &quot;Cookie-on-Demand&quot; and walks the in-place cookie-minting flow on a fully patched Entra-joined endpoint [@troopers22-mollema-pdf] [@troopers22-abstract].&lt;/p&gt;
&lt;p&gt;The minimal cryptographic statement of the fix is small enough to write down. Let $H$ be HMAC-SHA256, $k_s$ be the session key, $\ell$ be the constant label &lt;code&gt;AzureAD-SecureConversation&lt;/code&gt;, $\mathit{ctx}$ be the per-cookie context, and $p$ be the JWT body to be signed. Under KDFv1, the derived signing key was $k_d = H(k_s, \ell \parallel \mathit{ctx})$. Under KDFv2, the derived signing key is $k_d = H(k_s, \ell \parallel \mathrm{SHA256}(\mathit{ctx} \parallel p))$. The difference is exactly the hash of the message body inside the derivation context.&lt;/p&gt;
&lt;p&gt;{`
// Illustrative; do NOT use as production crypto.
const crypto = require(&apos;crypto&apos;);&lt;/p&gt;
&lt;p&gt;function sha256(buf) { return crypto.createHash(&apos;sha256&apos;).update(buf).digest(); }
function hmac(key, data) { return crypto.createHmac(&apos;sha256&apos;, key).update(data).digest(); }&lt;/p&gt;
&lt;p&gt;function deriveKdfv2SigningKey(sessionKey, ctx, assertionPayload) {
  const label = Buffer.from(&apos;AzureAD-SecureConversation&apos;, &apos;utf8&apos;);
  const boundCtx = sha256(Buffer.concat([ctx, assertionPayload]));
  // SP800-108 KDF in counter mode is more involved; one HMAC stands in here.
  return hmac(sessionKey, Buffer.concat([label, boundCtx]));
}&lt;/p&gt;
&lt;p&gt;// The signing key is now uniquely tied to assertionPayload.
`}&lt;/p&gt;
&lt;p&gt;A side-by-side flowchart makes the structural shift legible.&lt;/p&gt;

flowchart LR
    subgraph KDFv1 [&quot;KDFv1 (pre-July 2021)&quot;]
        A1[Session key in TPM] --&amp;gt; A2[&quot;SP800-108 KDF&lt;br /&gt;label = AzureAD-SecureConversation&lt;br /&gt;context = ctx&quot;]
        A2 --&amp;gt; A3[Derived signing key]
        A3 --&amp;gt; A4[HMAC over any JWT body]
    end
    subgraph KDFv2 [&quot;KDFv2 (July 2021+)&quot;]
        B1[Session key in TPM] --&amp;gt; B2[&quot;SP800-108 KDF&lt;br /&gt;label = AzureAD-SecureConversation&lt;br /&gt;context = SHA256 of ctx || payload&quot;]
        B2 --&amp;gt; B3[Derived signing key]
        B3 --&amp;gt; B4[HMAC over the specific JWT body]
    end
&lt;p&gt;KDFv2 killed off-device replay. It did not kill the on-device signing oracle, and it did not shorten the PRT&apos;s 90-day lifetime. The next generation tackled both -- not by closing the on-device gap, which is architecturally hard, but by making issued access tokens revocable in seconds.&lt;/p&gt;
&lt;h2&gt;7. The seam: CAE, Token Protection, Cloud Kerberos Trust&lt;/h2&gt;
&lt;p&gt;By 2022 the PRT was &lt;em&gt;the&lt;/em&gt; credential. The work that remained was to make every artifact issued &lt;em&gt;from&lt;/em&gt; it -- every access token, every Kerberos TGT, every Conditional Access claim -- share the same device-binding contract.&lt;/p&gt;
&lt;p&gt;That work has three named pieces, and a quiet rename in the middle.&lt;/p&gt;
&lt;h3&gt;Continuous Access Evaluation&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Continuous Access Evaluation&lt;/strong&gt; entered public preview in late 2020, a few months after Mollema&apos;s August blog. By 10 January 2022, Microsoft announced General Availability across Microsoft Entra ID; the announcement post came from Alex Simons, Corporate Vice President for Program Management in the Microsoft Identity Division [@twu-cae-ga-mirror]. CAE is the mechanism by which a &lt;em&gt;long-lived&lt;/em&gt; access token issued from a PRT can be invalidated in seconds when something critical changes.&lt;/p&gt;

An industry-standard near-real-time revocation channel for OAuth access tokens, implemented by Microsoft Entra ID as a claim-challenge protocol between Entra and CAE-aware resource providers. CAE is anchored in the OpenID Continuous Access Evaluation Profile (CAEP) [@caep-openid-spec]. CAE-aware resources reject a previously valid access token when Entra signals one of five critical events: user account deletion or disablement, password change, MFA enablement, admin token revocation, or high user-risk classification. Microsoft Learn documents an event-propagation upper bound of 15 minutes, with IP-location enforcement instantaneous [@cae-learn].
&lt;p&gt;Mechanically: a CAE-aware client requests an access token from Entra ID, and Entra issues a &lt;em&gt;long-lived&lt;/em&gt; token -- up to 28 hours rather than the conventional one hour -- with a &lt;code&gt;xms_cc&lt;/code&gt; claim signaling that the bearer understands the protocol. The resource provider serves requests against that token. When something changes -- the user gets disabled in HR, the IT admin resets the password, a sign-in trips a high-risk classification -- Entra ID fires a CAEP event. The resource provider receives the event and, on the next request, returns an HTTP 401 with a &lt;code&gt;WWW-Authenticate&lt;/code&gt; claim challenge. The client returns to Entra, presents the PRT, and asks for a fresh access token; Entra evaluates Conditional Access at that moment and either issues a new token or refuses. The user sees, at worst, a fast re-authentication; the access window for the revoked credential is on the order of seconds rather than the access token&apos;s original lifetime.&lt;/p&gt;

sequenceDiagram
    participant Admin
    participant Entra as Microsoft Entra ID
    participant Resource as Exchange Online
    participant Client
    Admin-&amp;gt;&amp;gt;Entra: Force password reset for user
    Entra--&amp;gt;&amp;gt;Resource: CAEP event: Credential Change
    Client-&amp;gt;&amp;gt;Resource: GET /mail (with long-lived token)
    Resource--&amp;gt;&amp;gt;Client: 401 WWW-Authenticate (claim challenge)
    Client-&amp;gt;&amp;gt;Entra: Refresh token + claim challenge
    Note over Entra: Re-evaluate Conditional Access against current user state
    Entra--&amp;gt;&amp;gt;Client: New short access token (or deny)
    Client-&amp;gt;&amp;gt;Resource: GET /mail (new token)
    Resource--&amp;gt;&amp;gt;Client: 200 OK
&lt;p&gt;The initial CAE deployment was constrained: only Exchange Online, SharePoint Online, and Teams understood the claim-challenge protocol at GA [@cae-learn]. Microsoft Graph followed. Other workloads still honor an access token until natural expiry, which is the open scope of the §9 caveat list.&lt;/p&gt;
&lt;h3&gt;Token Protection&lt;/h3&gt;
&lt;p&gt;If CAE is the &lt;em&gt;time&lt;/em&gt; dimension, &lt;strong&gt;Token Protection&lt;/strong&gt; is the &lt;em&gt;space&lt;/em&gt; dimension. The Conditional Access feature, also referred to as &quot;token binding,&quot; demands that an app-token request originate from a device-bound session token -- in practice, a PRT-signed assertion. The Microsoft Learn page defines it as a &quot;Conditional Access session control that attempts to reduce token replay attacks by ensuring only device bound sign-in session tokens, like Primary Refresh Tokens (PRTs), are accepted by Microsoft Entra ID when applications request access to protected resources&quot; [@token-protection-learn].&lt;/p&gt;

A Microsoft Entra Conditional Access session control that enforces device-bound sign-in for app-token requests against supported resources. Token Protection is the per-app analogue of the PRT&apos;s device-binding contract: every access token must originate from a device-bound session token. As of 2026, Token Protection is generally available on Windows for Exchange Online, SharePoint Online, Teams, Azure Virtual Desktop, and Windows 365; it is in preview on iOS/iPadOS and macOS via the Microsoft Enterprise SSO plug-in [@token-protection-learn] [@apple-sso-plugin-learn].
&lt;p&gt;The current scope is intentionally narrow. Native applications and the Microsoft Enterprise SSO plug-in for Apple devices both implement the device-bound assertion. Browsers do not. A browser visiting a Microsoft cloud resource still rides the &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; cookie path. Closing that gap is what Device Bound Session Credentials -- the cross-vendor web standard Microsoft co-designed with Google -- exists to do, and we will return to that in §10.&lt;/p&gt;
&lt;h3&gt;Cloud Kerberos Trust&lt;/h3&gt;
&lt;p&gt;The third piece bridges the cloud-mediated PRT path back to on-prem Kerberos. The mechanism is simple in framing and intricate in implementation: Microsoft Entra ID provisions a virtual &lt;code&gt;AzureADKerberos&lt;/code&gt; read-only domain controller object inside the on-prem Active Directory domain, and an Entra-signed partial Kerberos TGT issued to a Hello-for-Business-signed-in device can be exchanged at any on-prem DC for a fully-formed TGT carrying SID and authorization data.&lt;/p&gt;

A Microsoft Entra ID mechanism by which Entra ID can mint Kerberos TGTs for one or more Active Directory domains. An Entra-signed partial TGT carries the user&apos;s identity; an on-prem domain controller, holding the cryptographic shared key represented by the virtual `AzureADKerberos` RODC computer object, completes the TGT with on-prem SID and group claims. The bridge requires Windows 10 21H2 (with KB5010415+) or later, and a Windows Server 2016+ functional level on the domain controller; it shipped in April-June 2022 [@cloud-kerberos-trust-learn] [@entra-passwordless-onprem].
&lt;p&gt;The Microsoft Learn deployment guide is explicit about the AzureADKerberos object&apos;s role: &quot;When Microsoft Entra Kerberos is enabled in an Active Directory domain, an AzureADKerberos computer object is created in the domain. This object: Appears as a read only domain controller (RODC) object, but isn&apos;t associated with any physical servers; Is only used by Microsoft Entra ID to generate TGTs for the Active Directory domain&quot; [@cloud-kerberos-trust-learn]. The architectural property to notice is that the user&apos;s NTLM hash is &lt;em&gt;not&lt;/em&gt; the binding key. Microsoft Entra ID never holds the on-prem NTLM hash; the cryptographic root is the AzureADKerberos RODC&apos;s keys, which Entra and the on-prem domain controller share without involving any user-side long-term secret.&lt;/p&gt;
&lt;p&gt;Cloud Kerberos Trust is the Kerberos PKINIT pattern from RFC 4556 [@rfc-4556-pkinit], reframed: the cloud identity provider is the public-key initial authenticator, and Entra ID issues the partial TGT exactly as a PKINIT-aware KDC would.&lt;/p&gt;
&lt;h3&gt;The Azure AD to Microsoft Entra ID rename&lt;/h3&gt;
&lt;p&gt;In the middle of all this, on 11 July 2023, the brand changed. Microsoft renamed Azure Active Directory to Microsoft Entra ID and consolidated several adjacent products under the Microsoft Entra umbrella [@entra-rename-2023]. The article uses &quot;Microsoft Entra ID&quot; throughout; in primary sources from before July 2023, the same product is &quot;Azure AD.&quot; The rename is real, and it matters when citing older documentation, but it does not change the protocol surface.&lt;/p&gt;
&lt;h3&gt;The seam restated&lt;/h3&gt;
&lt;p&gt;With Continuous Access Evaluation, Token Protection, and Cloud Kerberos Trust in place, the picture from §1 fills out. Every cloud-mediated identity feature on a modern Windows endpoint either issues, refreshes, presents, or evaluates a PRT. The PRT itself is the asymmetric handshake that binds the device. CAE makes the time dimension elastic. Token Protection makes the access surface device-bound at the resource-request layer. Cloud Kerberos Trust makes the on-prem Kerberos surface reachable from a PRT-bearing device.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The PRT is the cryptographic seam: a single device-bound credential, issued at first sign-in, that every other identity artifact on the device references. CAE, Token Protection, and Cloud Kerberos Trust are not three different bindings; they are three different ways the same PRT contract reaches three different surfaces -- the revocation surface, the per-resource access-token surface, and the on-prem Kerberos surface.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A small comparison matrix makes the support story explicit.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource / scenario&lt;/th&gt;
&lt;th&gt;CAE-aware&lt;/th&gt;
&lt;th&gt;Token Protection (Windows GA)&lt;/th&gt;
&lt;th&gt;Cloud Kerberos Trust&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Exchange Online&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SharePoint Online&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Teams&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Graph&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Not enforced&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure Virtual Desktop&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows 365&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On-prem file share&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser (any Microsoft cloud)&lt;/td&gt;
&lt;td&gt;Indirect via resource&lt;/td&gt;
&lt;td&gt;No (native apps only)&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;That is what the PRT does. But four sibling articles in this series describe identity surfaces the PRT does &lt;em&gt;not&lt;/em&gt; cover. Before we celebrate the seam, we have to be honest about where it stops.&lt;/p&gt;
&lt;h2&gt;8. Where PRT is not the answer&lt;/h2&gt;
&lt;p&gt;The PRT carries device state, MFA state, and Conditional Access claims for the &lt;em&gt;cloud-mediated&lt;/em&gt; identity path. There is no clause in that sentence that mentions on-prem Kerberos, NTLM hashes, local admin authorization, or workload identities -- and that is the point.&lt;/p&gt;
&lt;p&gt;Five surfaces the PRT does not cover, in the order operators most often confuse them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On-prem Kerberos via the on-prem KDC.&lt;/strong&gt; A Windows user signing into a domain-joined or hybrid-joined machine still mints a Kerberos TGT against the on-prem Key Distribution Center on Windows logon. The PRT path is parallel, not replacement. The user&apos;s downstream &lt;code&gt;kerberos.dll&lt;/code&gt; ticket cache is populated by Kerberos AS_REQ/AS_REP exchanges between the workstation and the on-prem DC; the PRT lives in CloudAP&apos;s memory in &lt;code&gt;lsass&lt;/code&gt; and does not influence that flow. Cloud Kerberos Trust adds a bridge from PRT to on-prem TGT for users whose primary credential is in Entra; it does not retire the on-prem Kerberos path.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Credential Guard and LSAISO.&lt;/strong&gt; &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt;, introduced on the Enterprise SKU of the original Windows 10 release in 2015, isolates NTLM hashes and Kerberos long-term keys inside the Local Security Authority Isolated Subsystem (LSAISO), which runs in Virtual Trust Level 1 (VTL1) on top of the Hyper-V hypervisor [@credential-guard-learn] [@credential-guard-itpro-2016-wayback]. Credential Guard predates the cloud-identity model entirely; its threat model is &lt;em&gt;on-prem credential theft via long-term-key extraction from &lt;code&gt;lsass&lt;/code&gt;.&lt;/em&gt; The load-bearing distinction for the threat model is this: &lt;strong&gt;PRT material does NOT live in LSAISO&lt;/strong&gt;. It lives in normal &lt;code&gt;lsass.exe&lt;/code&gt; under CloudAP. Mollema&apos;s August 2020 extraction worked because the PRT&apos;s session-key handling is in the same address space as ordinary user processes that hold debug privilege; LSAISO did not move there. Treat &quot;I have Credential Guard enabled&quot; and &quot;my PRT is hardware-isolated&quot; as independent statements.The LSAISO isolation contract is for on-prem credentials -- NTLM hashes, Kerberos &lt;code&gt;krbtgt&lt;/code&gt; keys, the kinds of long-term secrets that the 2010s-era &quot;Pass-the-Hash&quot; tooling was designed to extract. The PRT&apos;s session key is a per-PRT artifact that lives in CloudAP&apos;s memory under normal LSASS. Credential Guard protects you against a different attack class. Get it for those reasons; do not get it expecting PRT-class mitigation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adminless and local-admin removal.&lt;/strong&gt; &quot;&lt;a href=&quot;https://paragmali.com/blog/adminless-how-windows-finally-made-elevation-a-security-boun/&quot; rel=&quot;noopener&quot;&gt;Adminless&lt;/a&gt;&quot; is an authorization pattern -- removing standing local-admin rights, requiring just-in-time elevation -- not an authentication pattern. It is orthogonal to the PRT. A device can be PRT-bound and still have a thousand local admins; a device can have zero local admins and still mint PRTs. The PRT addresses &quot;who is signing in;&quot; Adminless addresses &quot;what they can do once signed in.&quot; Conflating them is a common rhetorical move in Microsoft documentation and a common source of confusion in audits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/windows-app-identity-33-year-reinvention/&quot; rel=&quot;noopener&quot;&gt;App Identity&lt;/a&gt;, managed identities, and workload identities.&lt;/strong&gt; Workloads in Microsoft cloud environments authenticate through a separate broker path: the Azure Instance Metadata Service (IMDS) on VMs, Workload Identity Federation for cross-cloud Kubernetes flows, managed identities on Functions and App Service. None of these always involve a PRT. A managed identity is a non-human principal in Entra ID with a system-issued credential, not a device-bound JWT, and the broker path that produces its access tokens is structurally different. The App Identity sibling article addresses that surface in detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Remote Credential Guard versus Azure AD RDP sign-in.&lt;/strong&gt; These two are often introduced together because both involve credentials over RDP, and conflating them is the load-bearing threat-model error in this section. &lt;strong&gt;Remote Credential Guard&lt;/strong&gt; redirects Kerberos credentials over the RDP hop: the client&apos;s TGT is reachable to the remote &lt;code&gt;mstsc&lt;/code&gt; session via a CredSSP-mediated redirection mechanism, so that the remote session can fetch downstream service tickets without re-prompting. It does &lt;em&gt;not&lt;/em&gt; transport PRT material across the connection. &lt;strong&gt;Azure AD RDP sign-in&lt;/strong&gt; -- the separate scenario where the RDP host itself is Entra-joined and accepts an Entra sign-in at session establishment -- is the PRT-mediated path, and it happens at the &lt;em&gt;host&lt;/em&gt; side, not as a redirection from the client.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If your threat model says &quot;I am redirecting credentials over RDP, therefore my PRT is exposed,&quot; you are reading the Remote Credential Guard documentation wrong. Remote Credential Guard ferries Kerberos tickets between the client &lt;code&gt;mstsc&lt;/code&gt; and the remote session host; the PRT lives in the client&apos;s LSASS and does not cross the RDP wire under that feature. Azure AD RDP sign-in is the separate, host-side scenario where the remote session establishes its own PRT against Entra. The Stage 0a audit flagged this conflation as one of the most common errors in the wild, and the Microsoft Learn pages are not co-located.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The pattern across all five is the same. PRT is the cloud-mediated authentication path. Kerberos is the on-prem authentication path. Credential Guard is the on-prem long-term-credential isolation path. Adminless is the local-authorization pattern. App Identity is the workload-authentication path. Remote Credential Guard is an on-prem credential redirection over RDP. They run alongside each other on a modern Windows endpoint; they answer different questions. Mistaking the PRT for any of them is how good threat models go sideways.&lt;/p&gt;
&lt;h2&gt;9. Theoretical limits&lt;/h2&gt;
&lt;p&gt;The single most important sentence in the W3C Device Bound Session Credentials draft is also the single most important sentence about the PRT -- and it does not mention the PRT at all.&lt;/p&gt;

DBSC will not prevent temporary access to the browser session while the attacker is resident on the user&apos;s device. The private key should be stored as safely as modern operating systems allow, preventing exfiltration of the session private key, but the signing capability will likely still be available for any program running as the user on the user&apos;s device. -- W3C Web Application Security Working Group, Device Bound Session Credentials draft
&lt;p&gt;That paragraph is the architectural lower bound. Every device-bound session credential ever proposed inherits it. The PRT is no exception. Five bounded promises follow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. The on-device-attacker floor is architectural.&lt;/strong&gt; A hardware-bound key whose &lt;em&gt;signing surface&lt;/em&gt; is reachable by a same-privilege process can be used by that process for the lifetime of its presence. The TPM holds the key; the operating system mediates the signing operation; any process the operating system trusts to talk to CloudAP can ask for a signature. KDFv2 closed &lt;em&gt;off-device&lt;/em&gt; replay because the signing key is now uniquely bound to one cookie -- but the on-device process can simply ask for the next signature. The DBSC working draft is explicit that this is the floor for the entire class [@dbsc-w3c-draft]. The composition argument we will name in §10 is the practical response.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Non-TPM Windows reopens the pre-2021 attack class.&lt;/strong&gt; When the device key and transport key are protected by DPAPI rather than by a TPM 2.0, the key material can be unwrapped with the user&apos;s profile credentials. Pre-2021 Pass-the-PRT becomes available again because the attacker is no longer trying to extract a derived signing key from &lt;code&gt;lsass&lt;/code&gt; -- they are extracting the &lt;em&gt;root&lt;/em&gt; of the derivation from disk. Microsoft Learn names &quot;TPM 2.0 on Windows 10 1903 or higher&quot; as the supported configuration; everything else is best-effort [@prt-msft-learn]. TPM 2.0 is load-bearing, not optional, for the security claims this article makes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Phishing-resistance inheritance is one-shot.&lt;/strong&gt; The PRT records the authentication strength of the &lt;em&gt;issuing&lt;/em&gt; credential -- whether the user signed in with Hello for Business, a FIDO2 key, a password, or a password plus an MFA factor. The &lt;code&gt;mfa&lt;/code&gt; claim on the PRT carries this through to downstream tokens. If the user authenticated with a phishable factor at issuance, every downstream access token transitively trusts that weaker factor for the PRT lifetime. The PRT does &lt;em&gt;not&lt;/em&gt; upgrade. To enforce phishing-resistant authentication, the deployer must configure Conditional Access Authentication Strengths at the Entra ID side -- the PRT will record what arrived, but it will not refuse to mint downstream tokens because the issuing factor was weak.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. CAE coverage is not universal.&lt;/strong&gt; Continuous Access Evaluation is the time dimension of revocation -- but only for CAE-aware resources. Exchange Online, SharePoint Online, Teams, and Microsoft Graph honor the claim-challenge protocol; many other workloads still treat the access token as valid until its native expiry [@cae-learn]. If your tenant&apos;s risk surface is a CAE-unaware first- or third-party application, the deployment-time guarantee is the access token&apos;s natural lifetime, not 15 minutes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. The PRT lifetime is 90 days by design.&lt;/strong&gt; A device offline for more than the PRT lifetime cannot silently refresh; the user will see a re-authentication prompt the next time the device reaches Entra ID. That window is the Conditional Access trade-off: longer windows reduce friction for travelers and offline scenarios; shorter windows reduce the attacker&apos;s window after a device compromise. Microsoft chose 90 days; the deployer can tune it via Conditional Access Sign-In Frequency policies but cannot move it independently of the broader refresh-token configuration.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To approximate the ideal -- a device-bound, near-real-time-revocable, phishing-resistant cross-app SSO credential -- a deployer composes: &lt;strong&gt;PRT&lt;/strong&gt; (device binding) + &lt;strong&gt;CAE&lt;/strong&gt; (near-real-time revocation) + &lt;strong&gt;Token Protection&lt;/strong&gt; (per-resource device binding for native apps) + &lt;strong&gt;Authentication Strengths&lt;/strong&gt; (Conditional Access policy that upgrades phishing resistance at issuance) + &lt;strong&gt;DBSC&lt;/strong&gt; (per-origin web defense once it is available). No single artifact closes all five gaps; composition is the deployer&apos;s job, and the gaps in any one artifact are the joints another is supposed to cover.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Four of the five limits are bounded -- TPM rollout, claim-strength policy, CAE rollout, offline cadence. They get smaller as Microsoft ships, as administrators tighten policy, as more resources become CAE-aware. One is architectural and applies to every device-bound session credential ever proposed: same-device admin equals access while the admin has it. That is the open problem the next section traces.&lt;/p&gt;
&lt;h2&gt;10. Open problems&lt;/h2&gt;
&lt;p&gt;Five open problems sit on the PRT model right now. None of them have a &quot;just ship a patch&quot; answer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cookie-on-Demand on the live device.&lt;/strong&gt; The architectural defense is bounded by the §9 floor. Mollema&apos;s TROOPERS 22 talk makes the case that &lt;strong&gt;trustlet-level isolation&lt;/strong&gt; of the PRT signing path -- moving the CloudAP cookie-construction code from normal &lt;code&gt;lsass&lt;/code&gt; into an isolated user-mode environment in VTL1, the same security boundary that protects LSAISO -- would close the residual class [@troopers22-mollema-pdf]. Microsoft has not shipped that move. The cost is non-trivial: every downstream broker (WAM, the browser SSO surface, every native app that talks to CloudAP) would need to route through a trustlet-mediated signing API, and the trustlet itself would need to make policy decisions about which callers are entitled to a cookie. The benefit is real -- it removes the same-user-attacker class for the most powerful credential on the device -- but the engineering cost has not been deemed worth it as of 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cross-vendor near-real-time revocation.&lt;/strong&gt; CAE works inside the Microsoft Entra perimeter. If a user is compromised at Entra and Microsoft revokes the session, the signal does not automatically propagate to Okta-protected resources, Google Workspace, AWS IAM Identity Center, or any other identity provider the same user happens to have a session against. The standardization vehicle exists: the OpenID Shared Signals Framework defines a cross-IdP event-receiver protocol, and the OpenID CAEP specification provides the event taxonomy [@caep-openid-spec]. The bilateral transmit/receive deployments are sparse. Stage 3 of the research pipeline found no public production cross-vendor CAE deployment that wires Entra revocation events into a non-Microsoft IdP. The standard is ready; the deployments are not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DBSC and PRT composition for browser SSO.&lt;/strong&gt; Google&apos;s Device Bound Session Credentials began general availability for Chrome 146 on Windows in late 2025, with Microsoft co-designing the standard through the W3C process [@dbsc-google-blog] [@dbsc-w3c-draft]. The Chrome developer documentation references Chrome 145 as the rollout-start build, and the Google security blog references Chrome 146 as the GA build; the version drift reflects a phased rollout, and the article uses the later figure [@dbsc-chrome-developer]. The composition question is unresolved: when a browser on Windows visits &lt;code&gt;login.microsoftonline.com&lt;/code&gt;, the request will carry both a DBSC-bound short cookie (per-origin) and an &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; cookie from the WAM attachment path. Which binding wins, and how the two bindings are composed in the resource provider&apos;s evaluation, has not been publicly documented. The Stage 3 research found no Microsoft engineering blog explaining the contract.The Chrome developer documentation page on DBSC cites &quot;Chrome 145&quot; while the Google Security Blog post about DBSC GA cites &quot;Chrome 146.&quot; The two pages are co-published by Google; the security blog is dated later in 2025 and represents the GA figure. Stage 4 flagged this as an internal-inconsistency artifact. The article uses Chrome 146 for the GA framing and notes Chrome 145 as the rollout-start build [@dbsc-chrome-developer] [@dbsc-google-blog].&lt;/p&gt;

A modern Windows Edge session against `login.microsoftonline.com` already carries `x-ms-RefreshTokenCredential`. A modern Chrome 146 session on Windows carries a DBSC-bound short cookie for the same origin. Token Protection enforces device binding for *native-app* access-token requests, not browser ones. The three bindings are not redundant -- they cover different surfaces -- but Microsoft has not published a precedence rule or a unified &quot;this is how the browser proves device binding to Entra&quot; reference, and the open question is whether the W3C DBSC draft will be the home for that contract or whether Microsoft will document the composition independently. The composition story for browser SSO is, in 2026, the single most active open problem in this space.
&lt;p&gt;&lt;strong&gt;PRT-aware Conditional Access for AI agents and workload identities.&lt;/strong&gt; As organizations deploy autonomous AI agents that act on behalf of users -- Copilot agents, Office Studio bots, third-party LangGraph-style systems -- the identity story is genuinely unsettled. Some agents authenticate as the user via delegated permissions on a PRT-mediated path. Others authenticate as their own service principal via Workload Identity Federation. Conditional Access policies designed for human users -- &quot;require compliant device, require MFA, require sign-in frequency under four hours&quot; -- do not map cleanly to either. Microsoft Entra Agent ID entered public preview at Ignite 2025 with Conditional Access extended to agent identities via custom security attributes and agent-identity-blueprint policy targeting [@entra-agent-id-conditional-access], but the precise PRT-side claim semantics for agent-on-behalf-of-user vs autonomous-agent paths are still settling. The Conditional Access for AI Agents sibling article addresses the evolving model in detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PRT across RDP.&lt;/strong&gt; There is no clean &quot;redirect PRT&quot; primitive analogous to Remote Credential Guard&apos;s Kerberos redirection. Inside an RDP session to an Entra-joined host, a user can perform an Azure AD RDP sign-in that mints a &lt;em&gt;new&lt;/em&gt; PRT at the host -- but the client&apos;s PRT does not transit the RDP hop. Forensic and operational tooling that wants to know &quot;what PRT does this remote user have, and is it the same as the client&apos;s?&quot; has to query both endpoints separately. Active Microsoft work in this area is referenced in Mollema&apos;s TROOPERS 22 deck, but no public solution has shipped.&lt;/p&gt;
&lt;p&gt;These five problems share an architecture: they are all about composition. The PRT is one of several primitives that have to work together. The next section walks the practical guide for making them work in your environment today.&lt;/p&gt;
&lt;h2&gt;11. Practical guide&lt;/h2&gt;
&lt;p&gt;Here is what you actually do with the PRT this week.&lt;/p&gt;
&lt;h3&gt;Verifying PRT issuance&lt;/h3&gt;
&lt;p&gt;The operator-facing surface is &lt;code&gt;dsregcmd /status&lt;/code&gt;, which prints the PRT state under the &lt;code&gt;SSO State&lt;/code&gt; section. The three fields to read are &lt;code&gt;AzureAdPrt&lt;/code&gt; (Yes if a PRT is present), &lt;code&gt;AzureAdPrtUpdateTime&lt;/code&gt; (the timestamp of the last refresh), and &lt;code&gt;AzureAdPrtExpiryTime&lt;/code&gt; (the absolute expiry on the current PRT, by default 90 days after issuance) [@prt-msft-learn] [@dsregcmd-troubleshoot].&lt;/p&gt;
&lt;p&gt;{&lt;code&gt; // Models the section of dsregcmd /status output you care about. // On a real Windows host, you would run: dsregcmd /status | findstr AzureAdPrt const sampleOutput = \&lt;/code&gt;
+----------------------------------------------------------------------+
| SSO State                                                            |
+----------------------------------------------------------------------+
             AzureAdPrt : YES
       AzureAdPrtUpdateTime : 2026-05-12 09:31:14.000 UTC
       AzureAdPrtExpiryTime : 2026-08-10 09:31:14.000 UTC
        AzureAdPrtAuthority : login.microsoftonline.com/
              EnterprisePrt : NO
`;
const lines = sampleOutput.split(&apos;\n&apos;).filter(l =&amp;gt; l.match(/AzureAdPrt/));
console.log(lines.map(l =&amp;gt; l.trim()).join(&apos;\n&apos;));
// Healthy: AzureAdPrt=YES and AzureAdPrtUpdateTime within the last 4 hours.
`}&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;AzureAdPrt&lt;/code&gt; is &lt;code&gt;NO&lt;/code&gt; on a device that should have one, the most common causes are (a) the device is not actually Entra-joined, (b) the user has never signed in interactively since the last reboot, or (c) the device&apos;s TPM is malfunctioning and CloudAP could not complete the issuance handshake. &lt;code&gt;dsregcmd /status&lt;/code&gt; will print device-state diagnostics directly above the SSO State section that disambiguate these.&lt;/p&gt;
&lt;h3&gt;Forcing PRT renewal&lt;/h3&gt;
&lt;p&gt;The PRT refreshes silently every four hours, driven by CloudAP -- this is the renewal cadence Microsoft Learn documents as the device-side refresh schedule, not a Conditional Access policy [@prt-msft-learn]. To force an out-of-band renewal, the supported path is to sign the user out and back in with a Hello-for-Business gesture or a strong credential. A locked-and-unlocked session does &lt;em&gt;not&lt;/em&gt; generally force a new PRT mint; CloudAP treats unlock as a continuation event, not a fresh issuance.&lt;/p&gt;
&lt;h3&gt;Hunting PRT-mediated sign-ins in Entra logs&lt;/h3&gt;
&lt;p&gt;In the Microsoft Entra audit and sign-in logs, the load-bearing fields are &lt;code&gt;authenticationDetails&lt;/code&gt;, &lt;code&gt;authenticationProcessingDetails&lt;/code&gt;, and the &lt;code&gt;IsCompliantDevice&lt;/code&gt; and &lt;code&gt;DeviceDetail&lt;/code&gt; claims attached to the sign-in event. A sign-in that rode the PRT path will surface a &lt;code&gt;PRT&lt;/code&gt; indicator in &lt;code&gt;authenticationProcessingDetails&lt;/code&gt;. In Microsoft Defender XDR&apos;s advanced-hunting tables, the corresponding views are &lt;code&gt;IdentityLogonEvents&lt;/code&gt; (for on-prem and federated paths) and &lt;code&gt;AADSignInEventsBeta&lt;/code&gt; (for native Entra sign-in events) [@defender-xdr-schema]. The latter is the table to query when looking for unusual &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt;-driven sign-ins -- specifically, sign-ins from device-claim-bearing tokens whose &lt;code&gt;DeviceId&lt;/code&gt; does not match the device&apos;s &lt;code&gt;DeviceId&lt;/code&gt; in Intune.&lt;/p&gt;
&lt;h3&gt;Conditional Access patterns&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;What it enforces&lt;/th&gt;
&lt;th&gt;What it cannot enforce&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Require compliant device&lt;/td&gt;
&lt;td&gt;Sign-in only from devices Intune (or a partner MDM) reports as compliant&lt;/td&gt;
&lt;td&gt;Whether the compliance signal is fresh; an attacker who can spoof an Intune compliance attestation passes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Require Microsoft Entra hybrid joined device&lt;/td&gt;
&lt;td&gt;Sign-in only from hybrid-joined devices&lt;/td&gt;
&lt;td&gt;Personal Entra-registered devices that meet compliance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Require MFA at sign-in&lt;/td&gt;
&lt;td&gt;A fresh MFA factor at PRT issuance&lt;/td&gt;
&lt;td&gt;Whether the MFA factor is phishing-resistant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication Strengths (FIDO2-only)&lt;/td&gt;
&lt;td&gt;Phishing-resistant credential at issuance, propagated as a strong &lt;code&gt;mfa&lt;/code&gt; claim into the PRT&lt;/td&gt;
&lt;td&gt;Downstream phishability through cookie theft (KDFv2 fix applies; on-device residual remains)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token Protection for sign-in tokens&lt;/td&gt;
&lt;td&gt;Device-bound assertion required for app-token requests&lt;/td&gt;
&lt;td&gt;Browser sessions (DBSC is the per-origin counterpart)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sign-in Frequency = 4 hours&lt;/td&gt;
&lt;td&gt;Re-authentication every four hours&lt;/td&gt;
&lt;td&gt;The 90-day PRT lifetime independent of sign-in cadence&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The right policy stack for most enterprises is: require compliant device (or hybrid-joined), require Authentication Strengths for privileged users, require Token Protection where the resource supports it, and set a Sign-In Frequency policy that matches your risk appetite. CAE is on by default on modern tenants and does not need explicit opt-in.&lt;/p&gt;
&lt;h3&gt;CAE enablement and tenant configuration&lt;/h3&gt;
&lt;p&gt;CAE was made the default for all Entra tenants at GA on 10 January 2022; the announcement explicitly noted that Microsoft &quot;auto-enabled it for all tenants&quot; [@twu-cae-ga-mirror]. Microsoft Outlook, Microsoft Teams, and Office on Windows are CAE-aware clients [@cae-learn]; third-party apps that want to participate need to implement the claim-challenge protocol. Microsoft Graph clients gain CAE participation by including &lt;code&gt;cp1&lt;/code&gt; in the requested client capabilities [@cae-client-capabilities]. If your tenant is a CAE outlier, the cause is almost always a custom OIDC application that has not implemented the claim challenge.&lt;/p&gt;
&lt;h3&gt;Forensic indicators&lt;/h3&gt;
&lt;p&gt;Three signals deserve hunting attention:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Anomalous &lt;code&gt;x-ms-RefreshTokenCredential&lt;/code&gt; cookie origins.&lt;/strong&gt; A sign-in where the cookie&apos;s IP geolocation does not match the device&apos;s last known location -- particularly across time zones -- is a candidate Pass-the-PRT-Cookie signal even after KDFv2, because the on-device class survives.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Device-claim-bearing tokens whose &lt;code&gt;DeviceId&lt;/code&gt; does not match Intune state.&lt;/strong&gt; An attacker who lifted a PRT off-device cannot mint cookies post-KDFv2, but a cloned &lt;code&gt;DeviceId&lt;/code&gt; claim in a token request is a strong off-the-rails signal in older logs and a useful retrospective hunt for July 2021 and earlier.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;lsass&lt;/code&gt; broker-process anomalies.&lt;/strong&gt; Mimikatz-class memory-reading tools typically attach to &lt;code&gt;lsass&lt;/code&gt; with debug privileges. The current EDR generation (Microsoft Defender for Endpoint, CrowdStrike Falcon, SentinelOne) detects the canonical access patterns; deploy that telemetry, then validate the alert-rule coverage with &lt;code&gt;Get-MpComputerStatus&lt;/code&gt; and the EDR-specific equivalents.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;What NOT to do&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The single biggest operational mistake is to disable the broker because something else is broken. WAM, CloudAP, and the browser SSO surface are not optional add-ons; they are the cryptographic floor your Conditional Access policies are built on. If a particular app is breaking on PRT-mediated sign-in, the right move is to diagnose the broker integration, not to suppress it. Likewise, do not suppress Conditional Access in lieu of trusting the PRT -- the PRT carries claims that Conditional Access evaluates; disabling Conditional Access keeps the claims but throws away the policy engine.&lt;/p&gt;
&lt;/blockquote&gt;

Open an elevated command prompt. Run `dsregcmd /status`. Confirm `AzureAdJoined : YES`, `DeviceId` is populated, and `AzureAdPrt : YES` with a recent `AzureAdPrtUpdateTime`. Then in PowerShell, run `Get-CimInstance -ClassName Win32_Tpm` and confirm the TPM is present, ready, and at spec version 2.0. Finally, in the Entra ID portal, search for the device by `DeviceId` and confirm the registration state, the OS version, and the compliance posture. Those three checks rule out 90% of &quot;is my PRT working?&quot; questions.
&lt;p&gt;That is the PRT -- what it is, how it broke, how Microsoft fixed it, where it stops. Now the FAQ.&lt;/p&gt;
&lt;h2&gt;12. FAQ and closing&lt;/h2&gt;

No. They are different protocols, issued by different authorities, with different lifetimes. A Kerberos TGT is issued by an on-prem Key Distribution Center, lives 10 hours by default, and rides the AS_REQ/AS_REP protocol. A PRT is issued by Microsoft Entra ID, lives 90 days by default, and rides the MS-OAPXBC protocol over HTTPS. Cloud Kerberos Trust *issues a TGT to a PRT holder* via the Microsoft Entra Kerberos partial-TGT mechanism [@cloud-kerberos-trust-learn], but the two artifacts are distinct and serve different protocol clients.

No. The PRT is the cloud-mediated authentication path. On-prem Kerberos still flows through the on-prem KDC for resources protected by the on-prem Active Directory domain. NTLM remains in use for legacy applications until those applications migrate. The PRT, Cloud Kerberos Trust, and the in-progress &quot;NTLM-less&quot; effort together describe a path that *reduces* reliance on NTLM, but they do not delete the on-prem authentication surface on day one.

Not since July 2021. The asymmetric device key (`dkpriv`) signs the PRT *issuance* request -- a single asymmetric signature per PRT mint. The `x-ms-RefreshTokenCredential` cookie, by contrast, is HMAC-signed with `alg: HS256` using a symmetric key derived from the PRT *session key* via the SP800-108 KDF. Under KDFv2, the derivation context binds the cookie&apos;s full payload via `SHA256(ctx || assertion_payload)` [@ms-oapxbc-jwt] [@dimi-3or-de-kdfv2].

No. Dirk-jan Mollema&apos;s seminal PRT-cookie extraction work appeared in two blog posts on `dirkjanm.io` -- 21 July 2020 and 5 August 2020 [@mollema-prt-2020-07] [@mollema-prt-2020-08]. His 2022 conference talk on the same body of research was at TROOPERS 22 in Heidelberg in June 2022, not at DEF CON 30 [@troopers22-abstract]. Mollema&apos;s DEF CON history covers DC 27 (2019), DC 32 (2024), and DC 33 (2025); he did not present at DC 30 (2022) [@dirkjanm-talks-index]. The &quot;DEF CON 2022&quot; anchor that occasionally appears in summaries of the PRT-attack story is a memory error.

Yes. Conditional Access evaluates each *token request*, including app-token requests via the Web Account Manager and `x-ms-RefreshTokenCredential` cookie redemptions at `login.microsoftonline.com`. The PRT carries device-state, MFA, and risk claims; Conditional Access uses those claims plus the resource and request context to allow or deny each request. CAE additionally revokes already-issued long-lived access tokens in near real time when critical events fire [@cae-learn].

No. Microsoft Pluton *is* a TPM 2.0 implementation -- the same TPM 2.0 contract, embedded in the SoC rather than as a discrete chip. The PRT two-key model is unchanged. `dkpriv` and `tkpriv` are TPM 2.0 keys on Pluton just as they are on a discrete TPM 2.0; CloudAP does not branch on TPM provenance in its issuance path.

All three device states issue PRTs at first interactive sign-in. The differences are about device-management posture and which Conditional Access claims attach. **Microsoft Entra registered** is the personal-device / BYOD state -- the device has a cloud identity but is not the primary management surface; the PRT exists but the device is not necessarily compliant in the management sense. **Microsoft Entra joined** is the cloud-primary state -- the device&apos;s primary identity authority is Entra ID. **Microsoft Entra hybrid joined** is the dual state -- the device has both an on-prem AD computer object and an Entra ID device object; both authentication paths are active in parallel. Microsoft documents hybrid join as &quot;an interim step on the road to Microsoft Entra join&quot; for organizations migrating away from on-prem AD [@entra-devices-overview].
&lt;p&gt;The PRT is not a replacement for Kerberos, NTLM, or Credential Guard. It is the cryptographic seam where Windows logon becomes a Microsoft Entra ID transaction -- and the rest of this series is about what runs alongside it: Hello for Business as the issuing credential, WebAuthn and FIDO2 as the per-relying-party authenticator class, Cloud Kerberos Trust as the on-prem bridge, Credential Guard as the on-prem-credential isolation path, Adminless as the local-authorization pattern, App Identity as the workload broker. Each of those articles starts from a question this one raises, and each closes on a question that connects back. The seam is the part you can name when somebody asks how the three sign-ins from §1 are secretly one event.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;entra-id-and-the-primary-refresh-token-how-azure-ad-sign-on-bridges-windows-logo&quot; keyTerms={[
  { term: &quot;Primary Refresh Token (PRT)&quot;, definition: &quot;Device-bound JWT issued by Microsoft Entra ID to CloudAP at first interactive sign-in; cryptographic seam between Windows logon and Entra-mediated SSO.&quot; },
  { term: &quot;CloudAP&quot;, definition: &quot;Cloud Authentication Provider plugin framework in lsass.exe; the Entra ID plugin owns the device-side PRT lifecycle.&quot; },
  { term: &quot;Device key (dkpub/dkpriv)&quot;, definition: &quot;TPM-bound key pair that signs PRT issuance requests; registered with Entra ID at join time.&quot; },
  { term: &quot;Transport key (tkpub/tkpriv)&quot;, definition: &quot;TPM-bound key pair Entra ID uses to wrap session keys; only tkpriv can unwrap them on-device.&quot; },
  { term: &quot;Session key&quot;, definition: &quot;Symmetric proof-of-possession key for the PRT lifetime; signs cookies and app-token requests via SP800-108 KDF derivation.&quot; },
  { term: &quot;x-ms-RefreshTokenCredential&quot;, definition: &quot;HMAC-signed JWT cookie that carries PRT-derived authentication to login.microsoftonline.com from supported browsers.&quot; },
  { term: &quot;KDFv2&quot;, definition: &quot;Post-CVE-2021-33779 derivation rule that mixes SHA256(ctx || payload) into the cookie&apos;s signing-key derivation, closing off-device replay.&quot; },
  { term: &quot;Continuous Access Evaluation (CAE)&quot;, definition: &quot;Near-real-time revocation channel for OAuth access tokens; 15-minute event-propagation upper bound; CAEP-anchored claim-challenge protocol.&quot; },
  { term: &quot;Token Protection&quot;, definition: &quot;Conditional Access session control that requires device-bound assertions for app-token requests; the per-app analogue of PRT device binding.&quot; },
  { term: &quot;Cloud Kerberos Trust&quot;, definition: &quot;Bridge that lets a PRT-bearing device receive on-prem Kerberos TGTs from Entra ID via the AzureADKerberos virtual RODC object.&quot; }
]} questions={[
  { q: &quot;Why is &apos;the PRT cookie is DKey-signed&apos; wrong?&quot;, a: &quot;The device key signs the asymmetric PRT issuance request once per PRT mint. Cookies are HMAC-signed with a symmetric key derived from the session key via SP800-108 KDF; under KDFv2 the derivation context is SHA256(ctx || assertion_payload).&quot; },
  { q: &quot;What did CVE-2021-33779 fix, in one sentence?&quot;, a: &quot;It introduced KDFv2, which binds the cookie&apos;s full payload into the SP800-108 derivation context, so a key derived for one cookie cannot sign another -- killing off-device Pass-the-PRT.&quot; },
  { q: &quot;What does the on-device-attacker floor mean for the PRT?&quot;, a: &quot;A same-privilege attacker on the live device can ask CloudAP to mint a fresh cookie; the TPM signs it, because that is its job. Off-device replay is closed; on-device Cookie-on-Demand is the architectural residual.&quot; },
  { q: &quot;Where does the PRT NOT apply?&quot;, a: &quot;On-prem Kerberos via the on-prem KDC, Credential Guard / LSAISO (NTLM/Kerberos long-term keys), Adminless (authorization), App Identity / workload identities, and Remote Credential Guard (which redirects Kerberos, not PRT).&quot; },
  { q: &quot;How does CAE revoke an in-flight access token?&quot;, a: &quot;Entra fires a CAEP event on a critical change (user deletion, password reset, MFA enable, admin revocation, high user risk). The CAE-aware resource provider issues an HTTP 401 with a claim challenge on the next request; the client re-presents the PRT and Entra evaluates Conditional Access fresh, issuing a new token or denying.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>entra-id</category><category>azure-ad</category><category>windows-authentication</category><category>primary-refresh-token</category><category>tpm</category><category>conditional-access</category><category>identity</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>