On the campaign’s escalation day, 15 of the 23 impacted organizations had MFA turned on. It didn’t matter. Their attacker never saw an MFA prompt — because the login request never went through a browser at all.
TL;DR
- Between June 12–26, 2026, activity from LSHIY LLC’s IPv6 range compromised 78 Microsoft accounts across 64 organizations, firing over 81 million login attempts in 14 days (Huntress).
- The core technique wasn’t clever malware — it was recycled breached credentials combined with the OAuth 2.0 ROPC (Resource Owner Password Credentials) flow, which sends a password straight to Microsoft’s
/tokenendpoint with no interactive MFA prompt.- Of 23 impacted organizations Huntress analyzed on June 22, 15 had MFA misconfigured (wrong app scope, admin-only groups, “trusted location” loopholes) and 8 had no MFA policy at all.
- This isn’t an isolated incident: Huntress reports a 155x increase in credential spray volume across its customer base over six months, averaging 1,964 failed spray attempts per tenant, per month.
- The fix isn’t “turn on MFA” — most of these orgs already had. It’s closing the specific gap that lets a password alone still be enough.
Why This Matters
If your organization runs Microsoft 365 or Azure and you believe MFA “handles” credential attacks, this campaign is the counter-example. It matters for anyone responsible for Conditional Access policy, identity security, or SOC detection engineering — not because MFA failed as a concept, but because a legacy authentication path exposed accounts where Conditional Access did not actually require strong authentication. If you administer Entra ID (Azure AD), this is worth 15 minutes of policy review today.
Table of Contents
- What Happened: The LSHIY Campaign
- Red Team: How Password Spray + ROPC Actually Works
- Why MFA Didn’t Stop It
- Blue Team: Detecting Password Spray and ROPC Abuse
- Mitigations
- What You Can Do Today
- Related Posts
- Sources
What Happened: The LSHIY Campaign
Everything in this section is as reported by Huntress in their own incident writeup — this is their confirmed telemetry, not third-party speculation.
Infrastructure. Huntress tied most of the activity to LSHIY LLC, operating from autonomous system AS32167 (registered June 14, 2021), using an IPv6-only range (2a0a:d683::/32) with no IPv4 equivalent — itself an unusual footprint. A secondary ASN, AS955 (registered June 22, 2022), was also linked to the same operator. Registration records point to Hong Kong, Wuhan, and a shared office space (TKO Suites) in New York.
Scope and volume. Between June 12 and 26, 2026, Huntress tracked 78 compromised Microsoft accounts across 64 organizations. The attack fired more than 81 million login attempts in that 14-day window — this was not a handful of guesses, it was industrial-scale credential testing.
Timeline:
| Date | Activity |
|---|---|
| June 12–21 | Steady baseline: 2–4 accounts compromised per day |
| June 19 | Spike to 12 accounts in a single day |
| June 22 | Major escalation: 30 accounts across 23 businesses |
| June 25–26 | Campaign continues |
Credential source. Huntress states the attacker replayed “old username/password combinations where the credentials were previously breached but had never been rotated” — this is credential stuffing feeding a spray, not a novel breach against the victims themselves.
Geographic evasion. Source IPs geolocated inconsistently — some to China, others to Nebraska, US. That inconsistency wasn’t noise; it let the attacker’s traffic slip past conditional access rules that only trigger on “untrusted” geographies.
Red Team: How Password Spray + ROPC Actually Works
The spray, in plain terms
Traditional brute forcing tries many passwords against one account — and trips lockout policies fast. Password spraying flips this: try a small number of likely passwords (or, as here, previously breached real passwords) against many accounts, spaced out to stay under per-account lockout thresholds. MITRE ATT&CK catalogs this as T1110.003 – Brute Force: Password Spraying, under the Credential Access tactic.
Think of it like trying one spare key on every door in an apartment building instead of trying every key on one door — the security guard watching one door never notices, because the “attack” against it is a single, unremarkable attempt.
The ROPC trick that made MFA irrelevant
This is the part that makes the LSHIY case worth studying rather than filing under “yet another spray.”
Modern Microsoft 365 / Entra ID logins normally go through an interactive flow: browser redirect → password field → MFA challenge (push notification, code, etc.) → token issued. OAuth 2.0 ROPC (Resource Owner Password Credentials) is a different, older grant type built for a specific legacy use case: a trusted application collects a username and password directly (no browser, no redirect) and exchanges them for a token in a single API call to Microsoft’s /token endpoint.
The catch: because there’s no interactive session, there’s no interactive MFA challenge either. Microsoft explicitly warns that ROPC is incompatible with MFA: if the user must satisfy MFA, the request should be blocked rather than challenged. Red Canary’s write-up on BAV2ROPC and Embrace The Red’s “So, you think you have MFA?” both cover the same underlying weakness LSHIY exploited at scale. In effect:
Normal login: user → browser → password → MFA prompt → tokenROPC login: tool → password → /token endpoint → token (no MFA step exists)An attacker with a valid breached password doesn’t need to phish a session or bypass a push notification — they just need a client that speaks ROPC (a script, curl, or in this campaign, tooling built around the Azure CLI authentication path) and a Conditional Access policy that does not fail closed for that sign-in path.
Why MFA Didn’t Stop It
Huntress’s own breakdown of the 23 organizations impacted on June 22 (the escalation day) is the most useful part of this case, because it shows exactly which MFA configurations failed and how:
| Gap | Orgs affected | Why it failed |
|---|---|---|
| MFA scoped to specific apps only | Some of 15 | Policy targeted e.g. “Microsoft Admin Portals,” not “All Cloud Apps” — ROPC traffic against Azure CLI / Graph fell outside scope |
| MFA scoped to admin groups only | Some of 15 | Attackers targeted regular users, who had no MFA requirement at all |
| ”Trusted location” exemption | Some of 15 | Attacker IPs geolocated (incorrectly, per the geo-inconsistency above) as US-based “trusted” traffic |
| MFA in “Report-only” mode | 2 orgs | Policy existed but was never switched from audit to enforce |
| No MFA policy | 8 orgs | Nothing to bypass — password alone was sufficient |
The pattern across all of these: MFA existed as a checkbox, not as a universally enforced control. That distinction is the entire story.
Blue Team: Detecting Password Spray and ROPC Abuse
Detect the ROPC flow itself
Entra ID sign-in logs include an AuthenticationProtocol field that is populated with "ropc" when that grant type is used — this is documented Microsoft telemetry, and Elastic ships a prebuilt detection rule built directly on it. A starting KQL query for Sentinel / Log Analytics:
// Illustrative starting point — tune against your own tenant baseline.// Static ROPC filters alone produce noise from legitimate service accounts.SigninLogs| where AuthenticationProtocol == "ropc"| where ResultType == 0 // successful sign-in| summarize Accounts = dcount(UserPrincipalName), Attempts = count(), IPs = make_set(IPAddress) by AppDisplayName, bin(TimeGenerated, 1h)| where Accounts > 5Treat this as a hunting starting point, not a drop-in rule — as security researchers who’ve built this detection note, a bare AuthenticationProtocol == "ropc" filter alone flags known-good automation too. Baseline ROPC usage per app/user over 14 days before alerting on deviations.
Detect the spray pattern itself
Independent of ROPC, the spray pattern (many accounts, few passwords, tight time window, single source or IP range) is a classic Sigma-style detection:
title: Potential Password Spray Against Cloud Identitystatus: experimentallogsource: product: azure service: signinlogsdetection: selection: ResultType: [50126, 50053] # invalid credentials / account locked timeframe: 1h condition: selection | count(distinct UserPrincipalName) by IPAddress > 15level: highMFA / Conditional Access checklist
Given the exact gaps LSHIY exploited, audit your tenant against this list today:
- Conditional Access MFA policy targets “All Cloud Apps”, not a named subset
- Policy targets “All Users”, not just admin/privileged groups
- No blanket exemption for “trusted locations” without verifying how that trust is determined
- No policy left in Report-only mode past initial testing
- Legacy/basic authentication is blocked tenant-wide
- ROPC and other non-interactive grants are explicitly restricted to apps that genuinely require them
Mitigations
| Action | Why it matters | Priority |
|---|---|---|
| Enforce MFA for All Users, All Cloud Apps, all client app types, unconditionally | Closes every scoping gap Huntress found (app-only, admin-only, location-exempt policies) | Critical |
| Configure Conditional Access to actively deny sign-ins Microsoft’s Entra platform flags as requiring strong authentication the client cannot satisfy (this is how CA can fail-closed against ROPC, per Huntress’s own remediation guidance) | ROPC has no MFA challenge mechanism — a correctly scoped policy denies the sign-in outright instead of letting it through | Critical |
| Restrict the Azure CLI application (and other native/legacy clients) for non-admin users | Removes a major ROPC-capable client from the hands of the accounts attackers actually targeted | High |
| Rotate any credentials known to appear in breach dumps, even if “nothing happened yet” | LSHIY’s initial access was entirely recycled, never-rotated breached passwords | High |
| Triage spray alerts by credential validity (did a login actually succeed?), not raw volume | 81 million attempts is meaningless without knowing which handful actually returned a valid token | Medium |
| Move any Conditional Access policy out of Report-only once tested | Two organizations in this campaign had the right idea and never flipped the switch | Medium |
What You Can Do Today
- Pull your Conditional Access policies and check the scope field first — “All Cloud Apps” and “All Users,” not a curated list. This single check would have closed the gap at 15 of the 23 organizations Huntress analyzed.
- Search your Entra sign-in logs for
AuthenticationProtocol == "ropc"over the last 30 days and confirm every result maps to a known, intended automation — not an unrecognized script or IP. - Confirm no policy is stuck in Report-only. It takes one query and prevents this exact failure mode.
- Cross-reference active user passwords against known breach corpora (e.g., via Have I Been Pwned’s password API or your identity provider’s built-in leaked-credential detection) and force rotation on matches.
Related Posts
- Entra ID Attacks in Practice: Device Code Phishing, PRT Theft, and Conditional Access Bypass — covers other ways attackers walk past Conditional Access without touching a password.
- AitM Phishing: How Attackers Bypass MFA and How to Stop Them — the interactive-flow counterpart to ROPC’s non-interactive MFA bypass.
- OAuth Consent Phishing in 2026: MFA Stops Password Theft, Not Bad App Grants — another case where MFA alone doesn’t cover the whole identity attack surface.
- Identity-First Attacks in Cloud: How Permissions Become the New Perimeter — broader context on why identity, not the network edge, is where cloud attacks actually land.
Sources
- LSHIY Password Spray Attack — Huntress (primary source for all campaign-specific facts and figures)
- T1110.003 – Brute Force: Password Spraying — MITRE ATT&CK
- Microsoft identity platform and OAuth 2.0 Resource Owner Password Credentials — Microsoft Learn
- When MFA isn’t an option: The legacy of ROPC — Red Canary
- Legacy authentication: The curious case of BAV2ROPC — Red Canary
- ROPC - So, you think you have MFA? — Embrace The Red
- Entra ID OAuth ROPC Grant Login Detected — Elastic Security