Est.

Attestation Token Replay and Freshness Attacks

Attackers replay valid tokens to bypass security checks that depend on current device state.

Editor at Large · · 15 min read
Cover illustration for “Attestation Token Replay and Freshness Attacks”
Attestation and Verifiable Computing · August 28, 2026 · 15 min read · 3,364 words

Attestation token replay and freshness attacks exploit a simple structural weakness: the gap between when a token gets issued and when it actually gets checked. An attacker doesn't need to break the signature; they just need to catch a valid, signed statement and use it somewhere it no longer applies.

Attestation tokens are cryptographically signed statements about what a device, chip, or software component looks like right now: its identity, its patch level, whether its boot chain is intact. The IETF's RATS model breaks this into three roles. An Attester produces Evidence about its own state, a Verifier appraises that Evidence and decides whether to trust it, and a Relying Party takes the Verifier's word and acts on it, granting access, issuing a certificate, letting a transaction through. The Entity Attestation Token, or EAT, is the standard container for this: a signed bundle of claims that says, in effect, "here is what I am and here is what condition I'm in."

The Relying Party never gets to look at the Attester directly. It has no window into the actual device, no way to peek at the TPM or the enclave itself. The token is the only evidence it gets, and everything downstream rests on one assumption baked quietly into that arrangement: the token describes the Attester's state now, not five minutes ago, not five days ago. That assumption is where this entire piece lives, and once you start pulling on it, the whole freshness problem unspools pretty fast.

The gap between issuance and consumption (where the attack lives)

Every token has a lifecycle. It gets issued at one moment, and it gets consumed at another, and that interval, however short, is the entire attack surface this article is about.

Two distinct failure modes live in that gap. The first is replay: an attacker captures a token that was valid once and resubmits it later, hoping the Verifier treats it as current. The second is subtler and, in some ways, more dangerous: a freshness attack, where the token itself hasn't expired, but the claims sealed inside it describe a state that's no longer true. RFC 9334 places the burden here squarely on the signer: it's the signer's job to make sure claim values are still fresh at the moment of signing, not the Verifier's job to guess.

Take the classic stale-quote scenario in hardware attestation. A platform gets compromised, malware lands, firmware gets tampered with, whatever the mechanism. But the attacker, or the compromised software itself, still holds onto an old TPM quote, cryptographically valid, signed back when the platform was in a known-good state. That quote gets presented to a Verifier as proof of health. The signature checks out perfectly, and the platform, meanwhile, is not remotely what it claims to be.

This is why these attacks sit in a different category from forgery. Nobody broke the crypto, and nobody forged a signature or guessed a private key. The adversary just took something real and used it at the wrong time; standard signature verification sails through without complaint, because cryptographically, nothing is wrong. The Verifier has to do work beyond checking the signature to catch this, and that extra work (or the absence of it) is what separates a well-defended attestation system from one that only looks defended. Freshness is not the same problem as authenticity, and the rest of this piece is really an extended argument for why that distinction deserves more attention than it usually gets.

How the same exploit plays out across identity and hardware attestation ecosystems

This isn't a theoretical concern confined to whitepapers. Microsoft's 2024 telemetry flagged a large volume of token replay attacks, a sharp jump year over year, and adversary-in-the-middle phishing, one of the primary ways attackers get their hands on tokens in transit, grew even faster over that same stretch. By 2025, token theft accounted for a meaningful share of Microsoft 365 breaches, with detections happening tens of thousands of times a day across Microsoft's own environments.

Here's the part that should give anyone pause: multi-factor authentication does essentially nothing against this. MFA protects the login event. A replay attack skips the login event entirely, because the attacker already has a token issued after a legitimate, successful authentication. There's no second factor to bypass, because there's no authentication attempt happening at all; the attacker is just handing over something that was already stamped as good. Microsoft's own 2025 Digital Defense Report attributes the large majority of MFA-bypass breaches to session token theft specifically, which is worth sitting with for a second, because it cuts against a pretty widely held assumption that MFA is the backstop against credential misuse. It backstops one thing. It does not backstop this.

The hardware world has its exact mirror image. The stale TPM quote from the previous section is mechanically identical to a stolen session token: a legitimate credential, captured or retained, presented outside the context it was meant for. Different domain, same exploit shape, and honestly, once you've seen it in one context it's hard not to see it everywhere.

The blast radius compounds further once federation enters the picture. One of the larger SaaS breaches of 2025 traced back to compromised OAuth tokens from a marketing-and-sales integration, which gave attackers access to hundreds of downstream environments through federated trust relationships. One replayed credential, multiplied by however many systems trusted the token's origin without re-checking its freshness. Industry breach-cost research consistently puts compromised-credential incidents among the most expensive categories to detect and contain, often taking well over half a year from first compromise to containment. That's the financial argument for treating freshness as an architectural problem rather than something bolted onto authentication as an afterthought.

Why a timestamp alone does not solve the freshness problem

The obvious fix, the one that occurs to almost everyone the first time they hear about this problem, is to just stamp the Evidence with a timestamp and reject anything older than some cutoff window. RFC 9334 actually formalizes this as one legitimate model: timestamps in Evidence get compared against the Verifier's own clock. EPID-based attestation already uses a timestamp inside the verification report, and ECDSA-based schemes lean on validity periods attached to TCB info and certificate revocation lists. So timestamp-based rejection isn't hypothetical; it's already running in production systems today.

But it has real limits, and they show up fast once you scale past a tightly controlled environment. Clock synchronization is a nontrivial prerequisite, especially for constrained IoT devices and embedded systems that may not have reliable network time sync at all. Clock skew between a client and server can be substantial in practice; OAuth's own draft specifications acknowledge this by noting that servers may need to limit proof-of-possession lifetimes using server-provided challenge values containing server time, rather than trusting whatever iat claim the client hands over. If an attacker can manipulate the Attester's clock, even slightly, they can stretch the apparent freshness of stale Evidence more or less indefinitely.

There's a tension baked into the window size itself, too. Widen the tolerance to accommodate clock drift, and you widen the replay opportunity right along with it. Narrow it too aggressively, and legitimate requests start failing because two clocks disagree by a few seconds. Neither direction is free.

RFC 9334 raises one more wrinkle that's easy to overlook: the actual claim values inside a token may have been generated well before the token was signed. A fresh signature timestamp says nothing about how old the underlying claims are. So timestamps are a real signal, worth having, worth checking. They're just not proof.

Nonces as the dominant freshness mechanism and their requirements

If timestamps rely on trusting clocks, nonces sidestep the clock problem entirely by relying on construction instead. The Verifier generates a random value, the nonce, and sends it along with the attestation request. The Attester has to cryptographically bind that nonce into its Evidence. When the response comes back, the Verifier checks that the nonce inside matches the one it just issued.

Why does this actually work? Because a quote containing a nonce the Verifier only just generated cannot possibly have been produced before that nonce existed. Freshness stops being a matter of trusting a clock and becomes a matter of simple logic: either the Attester generated this Evidence after receiving the nonce, or the math doesn't work at all.

RFC 9683 describes exactly this pattern for TPM quotes: each Verifier request carries a fresh random number, and the resulting quote embeds that same number, letting the Verifier confirm the quote was generated specifically in response to its request and nothing earlier. The EAT specification is explicit about entropy requirements here too, tokens using nonce-based freshness need a nonce with at least 64 bits of entropy, because anything less starts becoming guessable at meaningful scale. Within the RATS reference interaction models, the nonce is formally classified as a "freshness handle," and it can double as a signal that invalidates cached claims, forcing fresh collection rather than reuse of something sitting around from an earlier check.

None of this comes free, though. Nonces cost an extra round-trip, every single session, and in high-frequency or latency-sensitive deployments that overhead adds up in ways that matter operationally. There's also a state-management burden on the Verifier side: it has to track every nonce it has ever issued and mark each one consumed once used, so a captured nonce can't get replayed a second time. The OAuth attestation-based client authentication draft acknowledges this directly, noting that managing large volumes of challenge values or jti identifiers at scale takes genuinely efficient data structures, not just a database table someone throws together over a weekend.

OAuth's ecosystem has settled on two tracks here, and they trade off against each other cleanly. Challenge-based freshness, where the server issues the challenge itself, gives strong replay protection at the cost of that extra round-trip. Self-contained freshness, where the client supplies its own iat timestamp, scales better because there's no round-trip required, but it only guarantees the token is recent. It doesn't guarantee the token hasn't been replayed within that recency window.

Epoch IDs as an alternative when per-session nonces are too costly

So what happens when a deployment has too many attesters for per-session nonce tracking to be practical? This is where epoch IDs come in. The shift in thinking matters here: instead of a unique, one-time value per session, an epoch ID is a shared marker dividing time into named intervals. It doesn't convey a precise point in time the way a timestamp does, and it doesn't need to be a monotonically increasing integer either.

The appeal is mostly about state. A Verifier using epoch IDs tracks the current epoch, one value, rather than a distinct nonce for every single Attester it talks to. State scales with the number of epochs in play, not the number of devices being verified, which matters enormously once you're talking about deployments with thousands or millions of endpoints.

The mechanism proposed for this, sometimes called the Epoch Bell model, works through a dedicated broadcasting system that pushes out Epoch Markers to everyone listening. Any participant that receives the same marker shares a common notion of "now" with every other participant, without anyone needing a synchronized clock of their own. The IETF's Epoch Markers draft operationalizes this concept, and it's telling that Appendix A of RFC 9334 is dedicated entirely to the freshness problem. That's a quiet signal of how genuinely hard this has proven across the standards community.

But epoch IDs trade one attack surface for another. RFC 9334 spells this out plainly: epoch IDs can be tampered with, replayed, dropped, delayed, or reordered by an attacker sitting in the delivery path. There's a more unsettling variant too: an attacker who controls how epoch markers get delivered can effectively freeze every participant in a single chosen epoch, indefinitely. Time, from the system's perspective, simply stops advancing. That turns the integrity and availability of the Epoch Bell itself into a critical dependency, arguably as important as the freshness guarantee it was meant to provide in the first place.

Nonces and epoch IDs aren't really competitors so much as different tools for different constraints. Nonces give strong, per-session guarantees at higher overhead, while epoch IDs trade some of that precision for scalability, at the cost of a new piece of infrastructure that itself needs defending. RFC 9334 even describes a hybrid: run a nonce-based exchange once to calibrate a relative time offset, then fall back to timestamp-based exchanges afterward. Useful in environments where clocks exist but aren't tightly synchronized.

Eliminating the round-trip: TUDA and TSA-based freshness

Nonces assume something that doesn't always hold: an interactive Verifier, present and available, ready to issue a challenge and wait for a response. Push attestation, multicast attestation, broadcast scenarios where data flows one direction only: none of these can tolerate that round-trip. So what do you do when the Verifier simply isn't there to ask a question in real time?

This is the gap TUDA, Time-Based Uni-directional Attestation, is built to close. It's an IETF RATS draft that removes the challenge-response requirement altogether. The mechanism leans on a hardware Root of Trust clock built into the Attester, combined with Time Stamp Tokens issued by a trusted Time Stamp Authority under RFC 3161. Both the Attester and the Verifier receive tokens from this same TSA, and that shared reference lets the Verifier bound how fresh the Evidence is without ever sending a nonce in the first place. RFC 9683, published in December 2024, references TUDA specifically as an alternate path to freshness that skips the request-response cycle.

There's a related TPM-based approach worth a quick mention too: tokens generated from the state of internal TPM counters, which let an external party validate freshness even in asynchronous settings where a live challenge-response exchange isn't feasible.

What TUDA opens up that nonces structurally cannot is the idea of a Secure Audit Log, Evidence that speaks credibly not just to the Attester's current state but to its state at various points in the past. A Verifier can check historical compliance this way, not merely "are you healthy right now" but "were you healthy an hour ago, and did anything change since."

That capability comes with a new dependency, though, and it's not a small one. The entire freshness guarantee now rests on the correctness of the Time Stamp Authority. If the TSA is compromised, or simply unavailable, the whole freshness proof collapses along with it. TUDA trades the availability requirement on the Verifier for an availability requirement on the TSA. It's not obvious that's a strictly better trade in every deployment. It's a different trade, suited to different constraints.

Freshness in certificate enrollment and how nonces propagate into PKI workflows

Freshness isn't only a runtime concern that shows up during ongoing operation. It matters just as much, arguably more, at the moment a device first enrolls into a PKI and requests a certificate.

Picture a device including attestation Evidence inside a Certificate Signing Request. The Registration Authority or Certificate Authority reviewing that request needs the same assurance any Verifier needs: that the Evidence reflects the device's actual state right now, not some earlier snapshot. A stale quote embedded in a CSR could conceal a compromised device at the exact moment it's handed a long-lived credential, arguably worse than a stale quote presented in an ordinary runtime check, because a certificate's validity period can stretch for months or years.

The IETF's LAMPS working group addresses this directly in draft-ietf-lamps-attestation-freshness, which defines how nonces get supplied by the RA or CA to the end entity for inclusion in its Evidence, using CMP and EST as the delivery channels for that exchange. Structurally, nothing new is happening here. The CA is just playing the Verifier role, and the enrolling device is playing the Attester role, mapped onto a PKI issuance workflow rather than a runtime attestation check.

Why does this deserve its own section rather than folding into the nonce discussion above? Because the stakes of getting it wrong differ in kind. A certificate issued on the basis of stale Evidence binds trust to a moment in time that may no longer be true, and that error doesn't just affect one transaction. It propagates across the certificate's entire validity period, silently, until someone catches it or the certificate expires.

Multi-verifier topologies and how replay can propagate through a cascade

Real deployments rarely involve a single Verifier making a single decision in isolation. Cloud-to-edge architectures, supply chain integrity checks, federated identity systems: all of these involve multiple Verifiers coordinating appraisal in cascade or hierarchical arrangements, where one Verifier's output feeds directly into the next one's input.

That raises an important question: what happens if an attacker replays old Evidence, or an old Attestation Result, at some node partway through that chain? A downstream Verifier that assumes freshness was already validated upstream, and simply trusts the result it's handed, has no independent way to catch a forgery it never checked for itself.

The draft-ietf-rats-multi-verifier specification, expected in mid-2026, addresses this by placing the burden squarely on the first Verifier in the chain. It's responsible for enforcing freshness, whether through nonces, epoch IDs, or timestamps, for the entire cascade that follows. Critically, that freshness value has to travel with the Evidence and Results through every single hop, so the final Attestation Result at the end of the chain can still be checked against the original challenge that started the whole process.

The OAuth token cascade mentioned earlier is really the identity-layer version of exactly this failure mode. Replayed tokens moved through federated trust relationships and reached hundreds of downstream environments, none of which independently re-verified the freshness of what they'd been handed. The blast radius of a single replayed credential scales with the depth of the trust chain it's allowed to travel through.

For anyone designing these systems, the implication is uncomfortable but straightforward: freshness cannot be a property the first Verifier declares once, with everyone downstream simply inheriting it. It has to be an end-to-end invariant, something re-checkable at every node that touches the Evidence or the Result. And that leaves an open governance question the technical standards alone can't fully answer: in a multi-party chain where no single organization controls every node, who actually owns the responsibility when freshness fails somewhere in the middle?

What a well-defended attestation system actually requires

Table: Freshness Mechanisms: Trade-offs at a Glance. Compares Core Mechanism, Replay Protection, Key Dependency, Scales to Many Devices, and 2 more by Nonces, Timestamps, Epoch IDs and TUDA / TSA.

Pull back from the individual mechanisms, and the core insight running through this entire piece is simple to state, even if it's hard to fully act on: freshness is architecturally separate from authenticity. A system that verifies signatures carefully but never checks freshness independently is, at best, half-defended. It will catch forgery. It will not catch replay.

Mechanism choice is genuinely deployment-specific, and there's no single answer that fits every context. Interactive, low-latency environments are well served by nonces, at least 64 bits of entropy per the EAT specification, with the Verifier carrying the burden of tracking issued and consumed values. Clock-synchronized environments can lean on timestamps with explicit, carefully chosen skew tolerance, ideally paired with nonces rather than used alone. Large-scale or broadcast environments, where per-session nonce tracking doesn't scale, are better suited to epoch IDs, provided the integrity of the Epoch Bell itself gets taken as seriously as the freshness guarantee it enables. Asynchronous or push-based environments, where no interactive Verifier is available to issue a challenge, point toward TUDA, with a trusted Time Stamp Authority standing in as the freshness anchor.

One thing holds across every one of these approaches, and it's the detail most likely to get skipped in a real implementation: the freshness handle, whatever form it takes, has to be cryptographically bound into the Evidence itself. A nonce sitting alongside the Evidence as loose metadata, rather than sealed inside the signed structure, protects nothing, since it's a value an attacker can swap out just as easily as the Evidence it was meant to anchor. Freshness only means something when it's inseparable, cryptographically, from the claim it's supposed to be freshening. Everything else in this piece (the nonces, the epochs, the timestamps, the TSAs) is just different engineering answers to that one non-negotiable requirement.

Sources

  1. workos.com
  2. datatracker.ietf.org
  3. datatracker.ietf.org
  4. datatracker.ietf.org
  5. rfc-editor.org

More in Attestation and Verifiable Computing