Safeguard
Supply Chain Security•

M365 Token Replay Campaign: 79 Organisations Lost Mailboxes Past MFA

A 10 week campaign replayed stolen Microsoft 365 sessions to take over mail at 79 organisations without a password. IOCs, KQL and a cleanup plan.

Safeguard Security Team
41 min read

From 14 July to 22 September 2026, an attacker took over Microsoft 365 mailboxes at 79 organisations by stealing sessions after users passed MFA, then replaying the tokens in bulk. A security vendor's report published 22 October lists the indicators. Microsoft 365 admins should hunt for them, revoke sessions and audit devices, MFA methods and inbox rules.

The striking part is not the number of victims. It is that no password was needed. Victims typed their credentials and approved MFA on what looked like a normal sign in, and a relay in the middle kept the resulting session. Minutes later the same session appeared from a server in Hamburg. The researchers describe replaying many stolen tokens at volume across many tenants, and they call it "token spraying".

This post sets out what the report and the follow up coverage say, lists every indicator the report publishes, and gives a cleanup plan with commands you can run today. The hunting queries are ours, written for this post. The report itself does not include any.

The short version

ItemWhat the report says
Campaign window14 July to 22 September 2026, about ten weeks
Public disclosure22 October 2026 (security vendor report); 23 October (Help Net Security)
Organisations with compromised accounts79
Successful attacker sign insat least 497
Failed sign in attemptsmore than 200,000
Rogue devices registered in Entra IDat least 48
Organisations where MFA was wiped and replaced19, each within three hours of the first campaign sign in
Main replay infrastructure193.26.115[.]0/24, 1337 Services GmbH, AS210558, Hamburg
How sessions were stolenadversary in the middle (AiTM) relays, device code phishing, social engineering
What the attacker did nextregistered devices, replaced MFA methods, hid mail with inbox rules, sent payroll related mail

All numbers in this post come from the report unless another source is named. Some of the report's own figures do not agree with each other, and we flag those where they appear.

What happened

The report splits the campaign into four phases. The phases overlap in time, and the numbering follows the report rather than strict date order. All times are UTC.

Date and time (UTC)EventSource
14 Jul 2026Stolen tokens used against more than a dozen organisations; in 13 of the 14 incidents handled that day, the attacker had registered a rogue deviceVendor report
21 Jul, 17:18:20AiTM relay at 185.238.2[.]195 catches a victim at the MFA promptVendor report
21 Jul, 17:30:21Session hijacked from 193.26.115[.]199, 12 minutes after the relay captureVendor report
21 Jul, 17:43:15Same session used from 124.198.132[.]33, another 1337 Services addressVendor report
21 Jul, 18:08:50Authenticator app labelled "iPhone 13" activated on the accountVendor report
3 AugLast activity from 193.26.115[.]221; by this date 37 organisations had attacker sign ins and 37 rogue devicesVendor report
AugustThree more attempts to reuse one stolen session, from 193.26.115[.]199, 45.83.31[.]44 and 192.159.99[.]172, all fail with AADSTS50133Vendor report
17 AugPhase 2 begins after a two week gap, from .16 and .21; device code phishing appearsVendor report
2 SepPhase 4 begins: relay on Evoxt (2400:8d60:2::1:841d:5dd), replay from 193.26.115[.]210Vendor report
3 SepReplay of a session stolen the day before fails with AADSTS50133Vendor report
11 SepPhase 3 burst from 193.26.115[.]72; 1,052 sign ins blocked by Conditional Access at four organisations; reports sent to 22 customers within two hoursVendor report
11 to 15 SepBurst continues for four days; 303 successful sign ins at 29 organisations (a later section says 232 at 28)Vendor report
22 Sep, 20:46Victim reaches the MFA prompt through the Evoxt relay and completes it a minute later, from a macOS browser using OfficeHomeVendor report
22 Sep, 20:50Session replayed from 193.26.115[.]210, four minutes after capture; the last takeover in the reportVendor report
22 OctReport publishedVendor report
23 OctHelp Net Security coverageHelp Net Security

Two details in that table matter for defenders. First, the gap between capture and replay shrank from 12 minutes in July to four minutes in September. Whatever your response time to a risky sign in alert is, it now has to beat four minutes to stop the first replay. Second, the failed replays in August and on 3 September show that revocation worked where someone did it. Sessions that had been invalidated could not be reused.

How token spraying works

Most people think of MFA as the final gate. Pass it and you are in; fail it and you are out. That model leaves out what happens after the gate opens.

When you sign in to Microsoft 365, Entra ID checks your password and your second factor and then issues tokens. A session cookie in the browser, a refresh token for native apps, and short lived access tokens for each service such as Exchange Online or Microsoft Graph. From that moment the tokens are the proof of who you are. Services do not ask for your MFA again for every request. They look at the token.

An AiTM relay sits between the victim and the real Microsoft sign in page. The victim sees the genuine page content, passed through the relay, and completes the genuine MFA challenge. Microsoft issues genuine tokens. The relay keeps a copy. The attacker never needs the password, because the password and the second factor have already done their job. Our explainer on AiTM phishing and how sessions are stolen despite MFA covers the mechanics in more depth.

Device code phishing reaches the same place by another route. The device code flow exists for devices without a keyboard, such as conference room displays. A device shows a short code, and the user enters it on Microsoft's real sign in page from another device. In this campaign, according to the report, the attacker started that flow and persuaded victims to enter the code. The victims signed in on the genuine Microsoft page, which then handed valid tokens to the attacker's session.

Then comes the "spray". Instead of using each stolen session quietly, one at a time, the operator replayed many of them from the same small set of servers, at volume, against many tenants. That gave the campaign scale. It also left a very concentrated footprint: six addresses in one /24 carried most of the replay traffic.

Relay and replay are separate

The report makes a point that is easy to miss. The infrastructure that captured sessions (the relays) was different from the infrastructure that used them (the 1337 Services range). Blocking the replay range does not stop new captures. Blocking a relay does not stop replay of tokens that were already stolen. You need controls on both sides, and you need to clean up sessions that were captured before any block went in.

Two builds, two footprints

The report describes two distinct replay tools, which it calls Build A and Build B.

Build A was a scripted client. It sent OAuth2:Token requests with a node user agent (and, from one host, a bare Mozilla/5.0), posing as the Microsoft Office client or the Microsoft Authentication Broker. It went after Graph, Exchange Online, SharePoint Online and the Device Registration Service, and it joined rogue devices to Entra ID. That footprint is unusual and huntable.

Build B replayed browser sessions. It used a current Chrome or Edge user agent on Windows, the OfficeHome application, and Login:reprocess and OAuth2:Authorize requests. To a log reviewer it looks like someone opening Outlook on the web. In the 22 September case, the report says a Remote Desktop Protocol tunnel into a virtual desktop changed the session's operating system to Windows, even though the victim had signed in from macOS. Build B registered no devices.

Technical details

Everything in this section comes from the security vendor's report unless marked otherwise. Addresses are defanged with [.] as the report prints them. Restore the dots only inside your own hunting tools.

Token replay hosts (1337 Services GmbH, AS210558)

AddressRole in the reportPhase
193.26.115[.]221Build A replay and rogue device joinPhase 1, 14 Jul to 3 Aug
193.26.115[.]199Build B session replayPhase 1
193.26.115[.]16Build A replay; device code phishingPhase 2
193.26.115[.]21Build A replay with bare Mozilla/5.0 user agent, against SharePoint OnlinePhase 2
193.26.115[.]72Build A replay, the September burstPhase 3, 11 to 15 Sep
193.26.115[.]210Build B session replayPhase 4, 2 to 22 Sep
124.198.132[.]33Continued a hijacked sessionPhase 1
45.83.31[.]44Failed replay attemptAugust
192.159.99[.]172Failed replay attemptAugust

The report notes that a single /24 block would have covered all six main replay hosts, but that a few other addresses it attributes to the same provider sit outside that range. Help Net Security adds that blocking any one address would have stopped one phase at most, because the operator moved to a new address between phases.

Relays and mailbox action infrastructure

AddressRole
185.238.2[.]195AiTM relay used for the 21 July session
2400:8d60:2::1:841d:5ddAiTM relay on Evoxt Sdn. Bhd., Phase 4
167.148.41[.]96Interserver address that created the payroll hiding rule, Phase 3

The report says every suspicious inbox rule it found was created from consumer VPNs or rented hosting (it lists ExpressVPN, NordVPN, CrownCloud, DataWagon, GLOBALTELEHOST, LeaseWeb, Dynu and Interserver), never from the 1337 Services range. So a hunt that only looks at the replay range will find the sign ins and miss the rule changes.

Application and resource identifiers

These are standard Microsoft first party IDs. Seeing them is normal. Seeing them with the user agents and addresses above is not.

IdentifierNameUsed by
d3590ed6-52b3-4102-aeff-aad2292ab01cMicrosoft Office (client)Build A
29d9ed98-a469-4536-ade2-f981bc1d605eMicrosoft Authentication Broker (client)Build A
4765445b-32c6-49b0-83e6-1d93765276caOfficeHome (client)Build B
00000003-0000-0000-c000-000000000000Microsoft Graph (resource)Build A
00000002-0000-0ff1-ce00-000000000000Exchange Online (resource)Builds A and B
00000003-0000-0ff1-ce00-000000000000SharePoint Online (resource).21
01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9Device Registration Service (resource)Build A

Microsoft's own documentation on authentication flows uses the same Device Registration Service client ID, 01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9, when it explains how to exclude that resource from a device code flow policy.

User agents, request types and error codes

ValueMeaning in this campaign
nodeBuild A scripted client
Mozilla/5.0 (bare, nothing after it)Build A on 193.26.115[.]21
Current Chrome or Edge on WindowsBuild B
OAuth2:TokenBuild A token redemption
Login:reprocess, OAuth2:AuthorizeBuild B browser replay
Cmsi:CmsiListed by the report as a hunting signal alongside OAuth2:Token
AADSTS53003Blocked by Conditional Access; the report treats it as proof the credential was valid
AADSTS50133Replay of a session that had been invalidated

Microsoft's error reference describes AADSTS53003 as BlockedByConditionalAccess: the access policy does not allow token issuance. It describes AADSTS50133 as SsoArtifactRevoked, where the session is not valid because of password expiration or a recent password change. In the report's examples, 50133 marks a replay that failed because someone had already invalidated the session.

Host and mailbox artifacts

ArtifactValue
Rogue device namesDESKTOP-54521F46, DESKTOP-BAF88EF4, DESKTOP-CA85907C
Device name patternDESKTOP- followed by exactly eight uppercase hexadecimal characters
Attacker authenticator labeliPhone 13
Device tokenapns2-d8a3fedb1a3cd1287ca47c6851a49e6052ab6116b43666e674765ca892d798ce
Inbox rule names., sss, ss, iT, ,., ........, s, d
Destination foldersRSS Feeds, RSS Subscriptions, Conversation History

The report says Windows' default naming uses DESKTOP- plus seven characters, so eight hex characters stands out. It also warns that the pattern is not unique to this campaign, and its mitigation section broadens the check to names that start with Device- or Work Pc followed by eight hex characters. Confirm before deleting anything.

Inbox rules in detail

Rule nameActionTrigger
.Mark as read, deleteAll mail
sssMark as read, deleteAll mail
ssMove to RSS Feeds, mark as readMail mentioning a business partner's domain
iTMove to Conversation History, mark as readAll mail
,.Move to Conversation History, mark as readAll mail
........Move to RSS Subscriptions, mark as readAll mail
sHidePayroll, direct deposit, bank or bonus terms
dMove to Conversation History, mark as readOne external accountant's address

In four mailboxes, according to the report, the rules were created through the Outlook REST API, two of them within minutes of the first campaign sign in. In one case the attacker changed rule s to catch payroll, direct deposit, bank and bonus messages, then five minutes later created rule d from the Interserver address to hide replies from an outside accountant who had been sent a payroll related message. In another case the attacker registered a lookalike of a business partner's web address. Both patterns point to payment fraud: redirecting salary or invoice payments while the real owner cannot see the conversation.

ATT&CK mapping from the report

TechniqueUse in this campaign
T1557 Adversary in the MiddleAiTM relays captured post MFA sessions
T1566.002 Spearphishing LinkFake sign in pages and device code phishing
T1550.001 Application Access TokenOAuth2:Token replay from the 1337 Services range
T1098.005 Device Registration48 rogue devices
T1556.006 Multi Factor AuthenticationMFA methods wiped and replaced
T1564.008 Email Hiding RulesHidden rules through REST APIs and Exchange features
T1090.003 Multi hop ProxyRented virtual desktop tunnels and consumer VPNs

MITRE's page for T1550.001 makes the general point directly: direct API access through a token "negates the effectiveness of a second authentication factor." It lists token binding (it names Entra token protection and OAuth DPoP) and blocking end user consent to OAuth apps among the mitigations.

Token lifetimes: what the numbers actually are

The report says the access token has "about" a 90 minute lifetime and stays valid after a password reset until it expires or the sessions are revoked. Microsoft's documentation gives more detail. By default an access token gets a random lifetime between 60 and 90 minutes, 75 on average. Tenants that do not use Conditional Access get a default of two hours for clients such as Teams and Microsoft 365. With continuous access evaluation (CAE), access tokens become long lived, 20 to 28 hours, but services that support CAE (Exchange Online, SharePoint Online and Teams) subscribe to critical events such as a password reset, an admin session revocation or high user risk, and reject the token within minutes. Microsoft says propagation can take up to 15 minutes.

Put together: a password reset on its own is not enough. Revoke sessions, and expect a short tail of access to services that do not support CAE until their tokens expire.

Who is affected

GroupExposure
The 79 organisations in the reportConfirmed compromised accounts, per the report; not named
Other Microsoft 365 tenantsUnknown. The report covers what one vendor saw in its own customer base. The relays and the replay range were not exclusive to those customers
Tenants without Conditional Access covering all users, all cloud apps and all client app typesHigher. The September burst got in at 29 (or 28) organisations where nothing stopped it
Tenants that allow the device code flow broadlyHigher for the device code phishing route
Tenants that allow end users to consent to appsThe report recommends hunting for new app grants; exposure depends on settings
Finance, payroll and accounts payable staffTargeted by the payroll and bank change rules

The report does not name any victim organisation, and nor do we. It also does not say how the 79 break down by sector, size or region.

What to do now

The steps below run from fastest to slowest. Do them in order. The KQL queries are ours, not the report's. They assume the Microsoft Sentinel or Log Analytics tables SigninLogs, AADNonInteractiveUserSignInLogs, AuditLogs and OfficeActivity. Column names and operation names vary by connector and workspace, so run each one with a short time range first and adjust.

One warning before you start. The campaign ended on 22 September. If you only keep sign in logs in the Entra portal, check how far back they go before you rely on a clean result. If they do not reach July, export what you have now and hunt in whatever longer term store you use.

1. Hunt for the replay infrastructure

// Ours: sign ins from the replay range and related hosts named in the report
let replayRanges = dynamic(["193.26.115.0/24"]);
let relatedHosts = dynamic(["124.198.132.33", "45.83.31.44", "192.159.99.172",
                            "185.238.2.195", "167.148.41.96"]);
union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > datetime(2026-07-01)
| where ipv4_is_in_any_range(IPAddress, replayRanges) or IPAddress in (relatedHosts)
     or IPAddress == "2400:8d60:2::1:841d:5dd"
| project TimeGenerated, UserPrincipalName, IPAddress, AppId, AppDisplayName,
          ResourceDisplayName, UserAgent, ResultType, ResultDescription
| order by TimeGenerated asc

Any row with ResultType of 0 is a successful sign in and should be treated as a compromise. Rows with 53003 mean the credential or session was valid and a policy stopped it, which still means the account needs cleanup. Rows with 50133 show a replay that failed because the session had already been invalidated.

2. Hunt for the Build A pattern without relying on addresses

Addresses change. The combination of first party Office client IDs and a scripted user agent is a better long term signal.

// Ours: Office or Broker client with a scripted user agent
let officeClients = dynamic(["d3590ed6-52b3-4102-aeff-aad2292ab01c",
                             "29d9ed98-a469-4536-ade2-f981bc1d605e"]);
union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(120d)
| where AppId in (officeClients)
| where UserAgent =~ "node" or UserAgent == "Mozilla/5.0"
| summarize SignIns = count(), Users = dcount(UserPrincipalName),
            Results = make_set(ResultType), Resources = make_set(ResourceDisplayName)
          by IPAddress, UserAgent, AppId
| order by SignIns desc

Then look specifically at sign ins to the Device Registration Service from anywhere unusual.

// Ours: who is signing in to the Device Registration Service, and from where
union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(120d)
| where ResourceIdentity == "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9"
| summarize SignIns = count(), Users = make_set(UserPrincipalName, 50),
            Agents = make_set(UserAgent, 10)
          by IPAddress, AutonomousSystemNumber
| order by SignIns desc

If your workspace does not have ResourceIdentity or AutonomousSystemNumber, filter on ResourceDisplayName and drop the ASN column. AS210558 is the ASN the report gives for the replay range.

3. Rank accounts by credential validity, not by noise

The report's most useful lesson is about triage. The most sprayed tenants were not the most compromised ones. A wall of failures from one address looks alarming, but the accounts that matter are the ones where the attacker got a success or a Conditional Access block.

// Ours: accounts where the attacker's session was valid
union isfuzzy=true SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > datetime(2026-07-01)
| where ipv4_is_in_range(IPAddress, "193.26.115.0/24")
| summarize Successes = countif(ResultType == "0"),
            CABlocks  = countif(ResultType == "53003"),
            Revoked   = countif(ResultType == "50133"),
            Other     = countif(ResultType !in ("0", "53003", "50133"))
          by UserPrincipalName
| extend Priority = case(Successes > 0, "1 compromised",
                         CABlocks > 0,  "2 valid session, blocked",
                         Revoked > 0,   "3 revoked session reused",
                                        "4 noise")
| order by Priority asc, Successes desc

4. Contain every account in priority 1 and 2

Microsoft's emergency revocation guide gives the sequence. In Microsoft Graph PowerShell:

Connect-MgGraph -Scopes "User.ReadWrite.All","Directory.AccessAsUser.All"

$upn  = "user@example.com"
$user = Get-MgUser -UserId $upn

# Block new sign ins while you clean up
Update-MgUser -UserId $user.Id -AccountEnabled:$false

# Revoke refresh tokens and session cookies
Revoke-MgUserSignInSession -UserId $user.Id

# Disable every device registered to the user, then review them one by one
Get-MgUserRegisteredDevice -UserId $user.Id -All | ForEach-Object {
    Update-MgDevice -DeviceId $_.Id -AccountEnabled:$false
}

Reset the password as well, but do not treat the reset as the containment step. The report is explicit that a reset alone leaves the current access token valid and leaves the attacker's devices and MFA methods in place. Re-enable the account only after steps 5 to 7 are done for that user.

5. Find rogue devices

# Devices named DESKTOP- plus exactly eight uppercase hex characters
Get-MgDevice -All -Property "id,deviceId,displayName,registrationDateTime,approximateLastSignInDateTime,operatingSystem,trustType" |
    Where-Object { $_.DisplayName -cmatch '^DESKTOP-[0-9A-F]{8}$' } |
    Select-Object DisplayName, Id, DeviceId, RegistrationDateTime,
                  ApproximateLastSignInDateTime, OperatingSystem, TrustType |
    Sort-Object RegistrationDateTime

For each hit, check who registered it (Get-MgDeviceRegisteredOwner -DeviceId $deviceObjectId), when, and from which address in the audit log. A device registered by a user who does not use Windows, or registered in the minutes after a sign in from the replay range, is the strong signal. Disable first, delete later, once you are sure. Repeat the search with ^Device- and ^Work Pc prefixes if you want the broader pattern from the report's mitigation section.

6. Find MFA methods that were wiped and replaced

The report saw existing methods cleared and a new authenticator registered within minutes, at 19 organisations within three hours of the first campaign sign in.

// Ours: security info deleted then registered for the same user within 3 hours
let window = 3h;
let deleted = AuditLogs
    | where TimeGenerated > datetime(2026-07-01)
    | where OperationName has "deleted security info"
    | extend Target = tostring(TargetResources[0].userPrincipalName)
    | project DeletedAt = TimeGenerated, Target;
AuditLogs
| where TimeGenerated > datetime(2026-07-01)
| where OperationName has "registered security info"
| extend Target = tostring(TargetResources[0].userPrincipalName),
         IP = tostring(InitiatedBy.user.ipAddress)
| join kind=inner deleted on Target
| where TimeGenerated between (DeletedAt .. DeletedAt + window)
| project Target, DeletedAt, RegisteredAt = TimeGenerated, IP, OperationName

Then list each affected user's authenticator registrations and look for the iPhone 13 label or anything the user does not recognise:

Get-MgUserAuthenticationMicrosoftAuthenticatorMethod -UserId $upn |
    Select-Object Id, DisplayName, DeviceTag, PhoneAppVersion, CreatedDateTime

Remove what the user cannot account for, and have them re-register in person or through a verified help desk process.

7. Find hidden inbox rules in every mailbox

Connect-ExchangeOnline

$suspicious = 'RSS Feeds|RSS Subscriptions|Conversation History'
$keywords   = 'payroll|direct deposit|bank|bonus'

Get-Mailbox -ResultSize Unlimited | ForEach-Object {
    Get-InboxRule -Mailbox $_.UserPrincipalName -IncludeHidden -ErrorAction SilentlyContinue
} | Where-Object {
    ($_.Name.Trim().Length -le 3) -or
    ($_.Name -match '^[\W_]+$') -or
    ("$($_.MoveToFolder)" -match $suspicious) -or
    ("$($_.SubjectOrBodyContainsWords)" -match $keywords)
} | Select-Object MailboxOwnerId, Name, Enabled, MoveToFolder, MarkAsRead,
                  DeleteMessage, From, SubjectOrBodyContainsWords

-IncludeHidden is a documented switch on Get-InboxRule in Exchange Online and returns hidden rules alongside normal ones. Expect some false positives from short rule names that users made themselves. In the unified audit log, rule creation shows up as New-InboxRule, Set-InboxRule or UpdateInboxRules operations:

// Ours: inbox rule changes that move mail to the folders used in this campaign
OfficeActivity
| where TimeGenerated > datetime(2026-07-01)
| where Operation in ("New-InboxRule", "Set-InboxRule", "UpdateInboxRules")
| extend P = tostring(Parameters)
| where P has_any ("RSS Feeds", "RSS Subscriptions", "Conversation History",
                   "payroll", "direct deposit", "bonus")
| project TimeGenerated, UserId, ClientIP, Operation, P
| order by TimeGenerated asc

8. Check for payment fraud, not only for intrusion

For every compromised mailbox, ask finance and HR whether bank details, payroll destinations or supplier remittance details changed during the window. The report's payroll example involved mail to an outside accountant. Search sent items for messages to external recipients that the user did not write, and check for lookalike domains of your partners. Call the counterparty on a known number before you accept any change to payment details.

9. Hunt for new app consents

// Ours: consent grants and new service principals since the campaign began
AuditLogs
| where TimeGenerated > datetime(2026-07-01)
| where OperationName in ("Consent to application", "Add service principal",
                          "Add delegated permission grant")
| project TimeGenerated, OperationName,
          Actor = tostring(InitiatedBy.user.userPrincipalName),
          IP = tostring(InitiatedBy.user.ipAddress),
          App = tostring(TargetResources[0].displayName)
| order by TimeGenerated asc

The report recommends hunting for new grants even though its main narrative is about token replay, because a consented app keeps access after every session is revoked.

Hardening that changes the outcome next time

Cleanup removes this attacker. These settings make the next campaign of this kind fail earlier. Test each in report only mode first.

Close the Conditional Access gaps

The September burst is the clearest evidence in the report. The same address was blocked 1,052 times at four organisations whose policies required MFA or blocked access for all users, all cloud apps and all client app types with no exceptions. It got in at 29 others where nothing stopped it. Review every exclusion in your policies. Legacy client apps, service accounts and "temporary" exclusions are where token replay finds room.

Restrict the device code flow

Microsoft's guidance is blunt: it calls device code flow a high risk method and recommends blocking it wherever possible. Conditional Access has an authentication flows condition for this. A policy that blocks device code flow for all users and all resources, with a named exception group for the few devices that genuinely need it, removes the route used from 193.26.115[.]16.

Two caveats from Microsoft's documentation. Since September 2024, authentication flow policies that target all resources are also enforced on the Device Registration Service, so if you use device code flow to register devices you must exclude that resource (client ID 01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9). And sessions that began with device code flow are "protocol tracked", so the block can apply to later refreshes from the same session. Use the authentication protocol filter in sign in logs, or a report only policy, to see who uses the flow before you enforce. Our earlier post on device code phishing walks through the policy.

Bind tokens to devices where you can

Token protection is a Conditional Access session control that accepts only device bound sign in session tokens, such as a Primary Refresh Token, for supported apps. Microsoft lists it as generally available for native apps on Windows, iOS and iPadOS, and macOS, enforced on Exchange Online, SharePoint Online and Teams, with browser support still in preview and limited to selected apps that access Azure Resource Manager. That means it would not have covered Build B's browser replay against OfficeHome. It would have made a stolen native app token much harder to reuse from a server in Hamburg. Roll it out to a pilot group first, as Microsoft recommends.

Keep continuous access evaluation on

CAE lets Exchange Online, SharePoint Online and Teams reject a token within minutes of a revocation, password reset or high user risk event. It is on by default for new tenants. Check that nobody has created a policy that disables it, and that Office clients are on a channel and Web Account Manager configuration that supports it.

Move high value users to phishing resistant MFA

CISA's fact sheet on phishing resistant MFA ranks FIDO and WebAuthn authenticators and PKI based methods as the strongest forms, because they are bound to the real site and cannot be relayed through a lookalike page. App push, codes and SMS can all be phished through an AiTM relay. Start with finance, payroll, executives and administrators, then expand.

Turn off user consent, or narrow it

Microsoft's consent settings let you disable user consent or allow it only for verified publishers and low impact permissions, with an admin consent workflow for everything else. Existing grants are not affected by the change, so review them separately.

What changed since the first reports

The campaign is over, per the report: the last takeover it describes was on 22 September. What changed is visibility. Before 22 October, the replay addresses appeared individually in some tenants' risk detections. Help Net Security notes that Entra ID Protection flagged several of them on its own. But nobody had published the full set, the client ID combination or the inbox rule names. The report is the first public account that ties the four phases together.

Help Net Security's coverage on 23 October repeats the main figures and adds framing (for example "nearly 30 organisations" for the September burst) but no new indicators.

There is no CVE here. Nothing in Microsoft 365 or Entra ID was broken. The campaign used features exactly as designed: sessions, device code sign in, device registration, MFA method management and inbox rules.

Open questions

  • Which September numbers are right? The report gives 303 successful sign ins at 29 organisations in one section and 232 at 28 in another, for the same address and period. We cannot tell which is correct.
  • How big is the real campaign? The 79 organisations are the ones a single vendor saw among its own customers. The 200,000 failed attempts are described in one place as seen across that vendor's customers and in another as traced back to the /24. The total across all Microsoft 365 tenants is unknown.
  • Who ran it? The report attributes infrastructure, not an actor. It does not name a group.
  • How were victims lured? The report describes the relays and the device code phishing, but not the lures, sender domains or relay page addresses beyond the two relay IPs.
  • What happened to the money? The payroll and bank change rules point to fraud, but the report does not say whether any payment was diverted.
  • Is the device naming pattern reliable? The report itself says the eight hex character pattern is not unique and then broadens it. Treat it as a lead, not as proof.

What would have helped

Practices any team can use

  1. Conditional Access with no gaps. All users, all cloud apps, all client app types, MFA or block, with exclusions reviewed monthly. The September burst numbers show this was the single biggest difference between tenants that were hit and tenants that were not.
  2. Phishing resistant MFA for the people who move money. Passkeys and security keys defeat AiTM relays because the authenticator checks the site it is talking to. Start with finance, payroll and administrators.
  3. Device code flow blocked by default. Allow it only for named devices that need it, with the Device Registration Service exclusion handled deliberately.
  4. Token protection and CAE where supported. Device bound tokens for native apps, near real time revocation for Exchange, SharePoint and Teams.
  5. A containment runbook that revokes, not only resets. Disable the account, revoke sessions, disable registered devices, remove unknown MFA methods, delete hidden inbox rules, then reset and re-enable. Practise it on a test account so it takes minutes.
  6. Triage by credential validity. Successes and 53003 blocks first, volume last.
  7. Log retention that outlasts a campaign. This one ran ten weeks and was published a month after it ended. Keep sign in and audit logs long enough to hunt back across that span.
  8. Out of band verification for payment changes. No bank detail change accepted by email alone, whoever sends it.
  9. User consent off, admin consent workflow on. So that a stolen session cannot turn into a long lived app grant.
  10. Alerts on behaviour, not addresses. Scripted user agents on Office or Broker clients from hosting providers, device registrations followed within the hour by MFA method changes, and rules that move mail to RSS or Conversation History folders. None of these depends on an IP address, which matters because the operator rotated addresses between phases.

Zero-Day Discovery and Gold

Safeguard's Zero-Day Discovery looks for previously unknown flaws in open source packages before a CVE exists. It runs in an agentic mode and a deterministic scanner mode, issues findings as SGZ advisories before they reach public CVE databases, and covers seven package ecosystems. This campaign did not exploit a software flaw, and Microsoft 365 and Entra ID are hosted services outside the package ecosystems Zero-Day Discovery examines. It has nothing to say about this incident.

Gold Open Source at gold.safeguard.sh is free and needs no login: searchable CVE intelligence with CVSS, EPSS, CISA KEV status, affected and fixed versions and a recommended safe version, a free read API and a CI gate GitHub Action. Gold Registry at registry.safeguard.sh is a paid service providing hardened drop in components and container images held to zero exploitable critical or high CVEs, with SLSA L3 or higher provenance, Sigstore signatures and evidence pages; an artifact loses its badge if it regresses. There is no CVE for this campaign, so there is nothing to look up in Gold, and no Gold component would have stopped a stolen Microsoft 365 session from being replayed. The habit Gold supports, pulling known good components from a curated source and rebuilding quickly, matters for the software you build. It is not an identity control.

Where Safeguard fits

Safeguard is not an identity security product. It does not read Entra ID sign in logs, detect AiTM relays, inspect mailboxes, manage Conditional Access or revoke sessions. For this incident, the tools that matter most are your identity provider's own controls, your log store and your response runbook.

Where Safeguard can help is with the code and scripts around your Microsoft 365 tenant:

  • Know who breaks when you block device code flow. Internal tools, scripts and kiosk apps sometimes sign in with device code flow. The Safeguard CLI's assistant edits code and runs commands with your approval, under /permissions modes Ask, Accept edits, Plan, Auto (the default) and Strict. You could ask it to search your repositories for device code sign in calls in MSAL based code or scripts, list them with owners, and draft the change to a supported flow, approving each edit and command. safeguard exec runs the same kind of task in CI.
  • Build the response scripts with a reviewer in the loop. The PowerShell and KQL in this post need adapting to your tenant. The assistant can help write and test a containment script in a repository, asking before each command it runs.
  • Inventory the identity libraries you ship. SBOM and dependency scanning of repositories, container images and SBOM files (safeguard scan --dir ., safeguard scan --image internal-tools:latest, safeguard scan --sbom sbom.json, with JSON results under ./output), plus a platform view of which projects contain a given component and version. That tells you which of your services embed authentication libraries and at what versions, and vulnerability matching and reachability analysis rank any known issues in them.
  • Approve from wherever you are. Desktop and phone apps can send work to a computer running the CLI and approve each command. When the capture to replay gap is four minutes, the person who can approve a containment script from a phone matters.

None of this would have prevented the campaign, detected the replay or cleaned a mailbox, and we do not claim it would have.

Common mistakes and troubleshooting

Resetting the password and closing the ticket. The report's containment advice exists because this is the usual response. The access token survives, and so do the attacker's device and authenticator. Revoke sessions and remove persistence.

Blocking the /24 and stopping there. The relays were elsewhere, the inbox rules were created from VPNs and other hosting, and some replay addresses sat outside the range. A block helps against this operator. It does nothing for tokens captured through a different replay host next month.

Reading a 53003 as a win. A Conditional Access block on a sign in from a hosting range means someone held a valid credential or session for that account. Treat the account as compromised.

Searching only visible inbox rules. Use -IncludeHidden. Rules created through APIs may not appear in the Outlook client in the usual way.

Deleting every DESKTOP- device. The report warns the pattern is not unique. Disable, investigate the registration event, then delete.

Enforcing a device code block on all resources without checking device registration. Microsoft documents that this can break device registration that relies on device code flow. Exclude the Device Registration Service if you need it, and start in report only mode.

Expecting token protection to cover browser sessions. For Microsoft 365 web apps it does not today. Build B used exactly that path.

Hunting with logs that have already aged out. If your sign in logs only cover the last few weeks, a clean result for July and August means nothing.

Query returns nothing at all. Check table names (AADNonInteractiveUserSignInLogs needs its own diagnostic setting), the time filter, and whether IPAddress holds IPv6 for some rows. Run the query without filters for one hour to confirm data is arriving.

FAQ

What is token spraying?

It is the term the researchers used for replaying many stolen session tokens, at volume, from the same infrastructure against many organisations. It borrows from password spraying, but the attacker never tries a password. Each token was captured after a real user had completed MFA.

Did the attacker break Microsoft MFA?

No. MFA worked and the users passed it. The attacker stole the session that MFA produced, through an AiTM relay or by getting the user to approve a device code sign in. That is why phishing resistant methods matter: they will not complete through a relay.

How do I know if my tenant was hit?

Run the hunts in steps 1 to 3. A successful sign in from 193.26.115.0/24 or the related hosts, a scripted node user agent on the Office or Broker client, a DESKTOP- device with eight hex characters, an iPhone 13 authenticator nobody recognises, or a short or punctuation named inbox rule moving mail to RSS or Conversation History folders are all strong leads.

Is a password reset enough?

No. Disable the account, revoke sessions, disable registered devices, remove unknown MFA methods and delete hidden rules, then reset the password. With CAE, supported services drop the session within minutes of the revocation; others keep accepting the current access token until it expires, which Microsoft puts at 60 to 90 minutes by default.

Which error codes should I look for?

AADSTS53003 means Conditional Access blocked the sign in, which also tells you the credential was valid. AADSTS50133 means a session that had been invalidated was presented again. In this campaign, 50133 marked failed replays after cleanup.

Should I block the 1337 Services range?

Blocking it with a Conditional Access named location costs little and stops this operator's known replay hosts. Do not rely on it. The operator moved between addresses, used other providers for some actions, and can rent new space.

Will token protection stop this?

It would have made native app tokens much harder to replay from another machine, for Exchange Online, SharePoint Online and Teams. Browser session replay, which Build B used, is not covered for Microsoft 365 web apps today.

Do I need to block device code flow entirely?

Microsoft recommends blocking it wherever possible. Most organisations need it for a handful of devices at most. Block it for everyone else, handle the Device Registration Service exclusion, and use report only mode first to find real users.

Is this related to earlier password spraying campaigns against Microsoft 365?

Not on the evidence published. This campaign did not guess passwords. It reused sessions captured after MFA. Keep the two kinds of attack separate in your response: password spraying is about weak credentials and legacy protocols, and token replay is about what happens after a successful sign in.

Can Safeguard detect this?

No. Safeguard does not monitor Entra ID, mailboxes or sign in traffic. It can help with the code around your tenant, such as finding internal tools that use device code flow and writing response scripts with your approval, as described above.

Fix it without waiting for upstream

This campaign abused identity features rather than a vulnerable package, so the fix for the incident itself comes from Microsoft's controls and your runbook. The block below applies to the open source dependencies and images in the services you build around your tenant, which is where Safeguard works.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would have helped

None of these demos shows Microsoft 365, Entra ID or this campaign. Each is a real Safeguard session, and each intro says how the same flow applies to the response work above.

This real CLI session fixes a lodash CVE in a sample repository: the assistant reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, and pushes nothing. For this incident, you would open the CLI in the repository that holds your internal tools and ask it to find every device code sign in before you switch on the Conditional Access block, then draft the change to a supported flow and run the tests, approving each edit and command.

Click through it at your own pace, or open it full screen.

This real desktop app session shows the CLI session in the conversation list, a request for work on your computer, a folder pick, and Approve or Deny on each command and file edit, ending with an upgrade done and tests passing. Here you would pick the folder that holds your incident response scripts, ask for the containment script from step 4 to be adapted to a list of affected users, and approve or deny each change before anything runs against your tenant.

Click through it at your own pace, or open it full screen.

This real Android session sends work to a computer running the CLI and approves the command on the phone with Allow once, Allow for turn or Deny. In this campaign the attacker's session appeared four minutes after capture. With this flow, the on call engineer who gets the risky sign in alert could approve a prepared revocation script from a phone instead of waiting to reach a laptop.

Click through it at your own pace, or open it full screen.

To try it on your own repositories, download Safeguard and follow the CLI docs. For background, read access tokens, ID tokens and refresh tokens explained, and for the rest of the month, October 2026 security incidents and what would have helped.

Quick check

Why did MFA not stop the 79 organisation token replay campaign?

Users completed MFA, and the attacker stole the session it produced through an AiTM relay or a device code sign in. The stolen tokens were then replayed from hosting infrastructure. Phishing resistant MFA, token protection and Conditional Access without gaps address that; a password reset alone does not.

What does an AADSTS53003 result from the replay range tell you?

That Conditional Access blocked the sign in, and that the attacker held a valid credential or session for that account. Treat the account as compromised: revoke sessions, remove unknown devices and MFA methods, and check inbox rules.

Sources

Last reviewed: 24 October 2026. This is a developing story; check the linked advisories for the latest status.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.