Observations

What went wrong, and what to do about it

Real breaches, each put through the same four questions: one control that worked, one that did not, one number worth watching, and what should have been done instead. Every entry cites a primary source, because the point of this section is that you can take it to a meeting.

NO. 15/Hospitality / Travel/12 September 2026

The hotel Wi-Fi sign-in page was the compromise

Zscaler ThreatLabz, CaptiveCrunch: Midnight Blizzard Weaponizes Hotel Wi-Fi Captive Portals to Steal Microsoft 365 Credentials

Storm-2945 compromised the shared captive portal services that hotels, conference centres and similar venues run, then manipulated DNS and HTTP traffic on those networks to send guests to attacker infrastructure. Zscaler found compromised gateways in several US cities, in India and in Saudi Arabia. What the traveller sees is the sign-in page they were expecting. What follows is Microsoft 365 credential harvesting, device code phishing and malware delivery. The victims here are not the hotels. They are whoever stayed in them, across every sector.

What worked

Zscaler names no control that stopped an instance of this in a customer environment. The write-up lists the product settings that would have, which is a different claim, and the entry below is where the useful reading is.

What failed

Multi-factor authentication, and not because it was absent. The device code pages abuse the Entra ID authentication flow itself. The victim is shown a genuine Microsoft prompt and authenticates the attacker’s session rather than their own, which as Zscaler puts it "can bypass conventional multifactor authentication (MFA)" because no credential is being relayed and nothing is being faked. The user completes a real login. The attacker ends up with a device registered in the tenant.

The second failure is an assumption about the network. A laptop that drops its tunnel on an untrusted network so the captive portal will load is a laptop with no inspection at the exact moment it is talking to a hostile DNS server. That configuration is common because it is often the only way captive portals work at all, which makes it a design tension rather than an oversight, and this campaign is what the tension costs.

The number

500 MB

the per-cycle upload cap built into the CornFlake payload, which also limits itself to 1,000 files a cycle and collects 18 categories of host information.

What to do instead

Treat the captive portal as hostile, because in this campaign it was. The practical control is that the corporate tunnel comes up before anything else and stays up, in full rather than with a local proxy exception, and that DNS goes to your resolver instead of the network’s. Zscaler’s version of this is a list of their own settings, but the principle underneath it ports to whatever you run.

Then block device code flow in Conditional Access. It is the single change here that closes the identity half of the attack. Almost nobody uses the flow for real work, the people who do can be scoped into an exception, and without it the genuine Microsoft prompt that makes this work never appears.

Then alert on new device registrations in Entra ID, because that is what a successful device code phish looks like from your side of the glass. It is one of the few signals in this chain that reaches your tenant at all, given that everything before it happened on somebody else’s network.

And have the travel conversation, which is cheaper than any of the above. A phone hotspot removes the entire attack. Say so before the conference rather than after it.

Named for the doctrine distinction between a lesson observed and a lesson learned: a lesson is not learned until behaviour has changed and somebody has checked. Pretending otherwise is how the same finding turns up in three consecutive post-incident reports.