In this section

Containment Decisions: Token and Session Revocation as First-Class Containment

5-6 hours · Module 9

The action reached for last that should be first

For the attacks that now dominate, the containment most analysts reach for last is the only one that works. Token theft and adversary-in-the-middle replay are the leading way attackers bypass MFA, and the access they give rides entirely on a stolen session token. Against that, the habitual first moves, disable the account, reset the password, do nothing, because the token is independent of both once issued. The action that severs it, session revocation, is the one analysts reach for last, treated as a follow-up step rather than the containment. This sub inverts that: for token-based attacks, session revocation is first-class containment, the first move, not an afterthought to an account action that never touched the access.

TR2 established the mechanics you need here: revoking the session invalidates the token the replay depends on, while a password reset leaves it untouched. This sub takes that from a fact about token theft to a containment discipline. The point is not only that revocation works where reset fails, it is that revocation should be the action you reach for first when the triage names a token, with the same reflex speed you currently reach for account-disable. Making it first-class means changing the order of your instincts: token named, session revoked, then everything else.

Why revocation is the containment and the others are not

The reason comes down to what each action touches and when the token was issued. A session token is minted once, at authentication, and then it is a self-contained bearer artifact: presenting it is sufficient to act as the user, and it stays valid until it expires or is explicitly revoked. Disabling the account changes the account's state going forward, blocking new interactive authentications, but it does not reach back to invalidate a token already issued, so the attacker replaying that token is unaffected. Resetting the password invalidates the credential, which matters for stopping new authentications with that secret, but the live session is not holding the password, it is holding the token, so the reset changes nothing about the active replay. Both actions operate on the wrong layer for a token already in the attacker's hands.

Session revocation operates on the right layer: it invalidates the issued tokens themselves, so the next time the attacker replays, the token is rejected and the session dies. That is why it is the containment and the others are not: against a token, the only action that severs the access is the one that invalidates the token. The practical form is revoking the user's sign-in sessions, which marks the issued refresh and session tokens invalid and forces re-authentication. Done first, it stops the replay; done after a reset and a disable that already failed to touch it, it still works but you have spent the dangerous minutes letting the session run. First-class means first in time, because every minute the revocation waits is a minute the replay continues.

Three actions, three layers, one already-issued token disable accountacts on account state going forward ✗ does not reach a token already issued reset passwordinvalidates the credential ✗ session holds the token, not the password revoke the sessioninvalidates the issued tokens themselves ✓ next replay is rejected: the session dies

Disable and reset act on the account and the credential; the live access rides on the token. Only revocation invalidates the token, which is why it is the containment.

Revoke first, verify, then complete

First-class containment is an order of operations, more than a preferred action. The discipline is three steps. Revoke first: the moment the triage names a token compromise, revoke the user's sign-in sessions, before the account action, before the reset, because that is the step that stops the live harm and every other step can wait the seconds it takes. Verify second: read the evidence to confirm the replay actually stopped, because revocation that did not take, or a second session you missed, leaves the attacker live while you believe you contained them. The non-interactive sign-ins are the verification, if they stop advancing after you revoke, the containment worked; if they continue, you have another session or the revocation failed.

Complete third: now do the reset and any account action, for the credential path and for completeness, because a token theft often rides on a credential compromise too, and a full response addresses both. The order matters because the steps have different urgencies, the revocation is the only time-critical one, the rest can follow once the bleeding stops. This inverts the habitual order, where the reset and disable come first and the revocation, if it happens, comes last, which spends the urgent minutes on the non-urgent actions while the replay runs. Revoke first, verify it took, then complete: that is what making revocation first-class looks like in practice, and it is the difference between stopping the attack in the first minute and stopping it in the tenth.

The only urgent step is the revocation; put it first HABITUAL: revoke last disable account reset password revoke session replay runs through both ✗ FIRST-CLASS: revoke first revoke session verify stopped complete: reset + account replay stopped, minute one ✓

Same actions, opposite order. Revoke-last lets the replay run; revoke-first stops it before the non-urgent steps.

The common mistake

Treating session revocation as the cleanup step after the "real" containment, so the account disable and password reset come first and the revocation, the only action that touches the token, comes last or not at all. The analyst follows the familiar order, disable, reset, and only then thinks about sessions, spending the urgent opening minutes on two actions that do nothing to a live token while the replay keeps running.

The deeper version is skipping the verify step: the analyst revokes but does not confirm the replay stopped, so a second live session or a revocation that did not take leaves the attacker active while the ticket says contained. Both come from not treating revocation as the first-class, time-critical action it is for token-based attacks.

The fix is the order of operations: the moment the triage names a token, revoke the sessions first, verify the replay stopped in the evidence, then complete with the reset and account action. Revocation is first in time because it is the only step that stops the live harm; everything else can wait the seconds it takes, and nothing else substitutes for it.

Seeing it in the evidence

The verify step made concrete: the non-interactive replay you watch to confirm the revocation actually stopped the session.

Where to find it

The replay you are containing, and the test of whether you contained it, both live in the non-interactive sign-in log (Entra AADNonInteractiveUserSignInLogs / Splunk azure:aad:signin:noninteractive). The token presenting itself to act shows here as non-interactive sign-ins, and the last-seen timestamp is your verification: after you revoke, it should stop advancing. If new non-interactive sign-ins keep appearing past the revocation time, either the revocation did not take or there is a second session you have not revoked, and the containment is not yet complete.

SIEM Console

Revoke first, then read this log to verify the replay stopped.
Before revocation, the non-interactive sign-ins advance to the present, the live replay. After you revoke the user's sessions, the last-seen timestamp should freeze. A frozen timestamp is the containment confirmed; sign-ins continuing past the revocation time mean a missed session or a revocation that failed, and you are not done.
azure-aad-signin-noninteractive
| stats count as replays, max(_time) as last_seen by user
AADNonInteractiveUserSignInLogs
| summarize replays = count(), last_seen = max(TimeGenerated) by UserPrincipalName
# Step 1 revoke first; step 3 reset follows once the replay is verified stopped
Revoke-MgUserSignInSession -UserId $userId
Reset-MgUserAuthenticationMethodPassword -UserId $userId

Read the output

Predict before running. The panel returns, per user, the replay count and the last-seen timestamp. Read the last-seen as the verification instrument. Before you revoke, it advances to the present: the session is live and replaying.

After you revoke the user's sessions, you run the same panel again and watch the timestamp. If it has frozen, the last non-interactive sign-in predates your revocation, the token is rejected, the session is dead, and the containment took. If it is still advancing past the revocation time, the revocation did not reach the session the attacker is using, either it failed or there is a second session, and you are not contained despite having acted.

Run the panel and read it as the verify step of the revoke-first discipline: the action is only confirmed when the evidence shows the replay stopped, not when the console reports the revocation submitted.

After revocation, read the last-seen timestamp revocation time Frozen last sign-in predates revocation token rejected: contained ✓ Still advancing new sign-ins past revocation time missed session or failed revoke ✗

Confirmed when the evidence shows the replay stopped, not when the console says the revocation was submitted.

Session revocation as first-class containment

For token-based attacks, revocation is the first move, not the cleanup. Revoke first, verify the replay stopped, then complete with the reset and account action.

1. Revoke first

The moment the triage names a token compromise, revoke the user's sign-in sessions, before the account disable, before the reset. It is the only step that stops the live replay, and every other step can wait the seconds it takes.

2. Verify the replay stopped

Read the non-interactive sign-ins. A frozen last-seen timestamp confirms the token is rejected and the session is dead. Sign-ins continuing past the revocation time mean a missed session or a failed revocation, and you are not done.

3. Complete with reset and account action

A token theft often rides on a credential compromise, so a full response resets the credential and addresses the account. These follow the revocation, because they are not the time-critical step and do not substitute for it.

Disable and reset do not touch an issued token

Account disable acts on account state going forward; reset invalidates the credential. Neither reaches a token already in the attacker's hands. Reaching for them first spends the urgent minutes on actions that do nothing while the replay runs.

Your turn

A token-theft alert fires on a finance user: an AiTM proxy stole the session token and it is being replayed now. You have the containment console open. List the order of actions and, for each, what you would check before moving to the next.

Reveal

You revoke the session first, verify the replay stopped, then complete with the reset and account action, because only the first step stops the live harm and the rest can wait the seconds it takes. Step one is revoke the user's sign-in sessions, immediately, before touching the account or the password. The triage has named a token compromise, the token is the capability the access rides on, and revocation is the action that severs it: invalidating the issued sessions means the next replay is rejected. You do this first because every minute it waits is a minute the attacker keeps acting, and because disabling the account or resetting the password does nothing to a token already issued, so spending the opening minutes on them lets the replay run while you achieve nothing. Step two is the verification, and it is not optional: you read the non-interactive sign-in log and watch the last-seen timestamp, because a revocation that did not take or a second session you missed leaves the attacker active while you believe you are contained. If the timestamp has frozen before your revocation, the session is dead and you can move on; if sign-ins keep appearing after the revocation time, you are not contained, and you revoke again or hunt the missed session before treating the token as handled. Step three is to complete the response: reset the credential and address the account. A token stolen via an AiTM proxy often means the credential path is also compromised, so a full response resets the password and forces re-authentication on a clean factor. But these follow the revocation and its verification, because they are not the time-critical step and do not substitute for it: a reset with the session still live contains nothing. The lesson is the sub's core: for token-based attacks, session revocation is first-class containment, first in time because it is the only action that stops the live access, verified in the evidence before you trust it, and completed by the reset and account action that follow rather than replace it.

Where this leads: you can make revocation the first-class containment it should be for token attacks, and verify it took. The next sub steps back to the decision that sits over all containment under the triage clock, the trade-off between the narrowest action that stops the harm now and the complete action that takes longer, and when the gap between them costs you.