A Phished OTP Can Buy the Attacker a Passkey in Your Tenant, and the Registration Audit Trail Is Your Most Direct Signal
A caller tells your user their passkey enrollment is overdue, walks them to a page that looks like Microsoft’s, and collects the password plus whatever the tenant throws next — SMS OTP, a TOTP code, a number-match push. While the user is busy copying down a fake “recovery phrase,” the operator on the other end feeds those secrets into the real Entra login and registers the attacker’s own passkey against the account. Okta is careful here — it assesses this as the kit’s likely purpose and says it hasn’t directly observed Microsoft-account compromise, because the analyzed kit doesn’t handle redirection to third-party IdPs like Okta — but the phishing pages are engineered for exactly this flow.
If the operator completes that enrollment, the result is a legitimate, phishing-resistant credential the attacker holds the private key to. Reset the password all you want; the passkey doesn’t care. The most direct durable evidence in your tenant is the authentication-method registration audit trail — a User registered security info record — written from a session that satisfied your applicable sign-in controls, often because the registration action itself was protected only by relayable MFA. That audit trail isn’t the only trace (the interactive sign-in and its device/IP/ASN context, Microsoft’s own “a passkey was registered” notification email to the user, and later passkey sign-ins all leave marks) — it’s the most direct tenant-side artifact of the persistence mechanism. That is the shape of the campaign Okta’s threat intelligence team is tracking as O-UNC-066, and it inverts the whole passkey pitch: the property that makes a passkey resistant to credential phishing is exactly what makes an attacker-controlled passkey survive a password-only containment action.
TL;DR
- Vishing crews tracked as O-UNC-066 (which Okta says Palo Alto Unit 42 reports as CL-CRI-1147, tied to The Com) walk phished users through a fake Entra passkey enrollment and relay the password and any OTP/push in real time via a PHP operator panel; the kit appears designed to register an attacker-controlled passkey, a phishing-resistant credential that survives password resets.
- The attack targets registration, not authentication: where passkeys are enabled for the user and the registration action is protected only by ordinary MFA, a phished password plus relayed MFA is enough to add a method — and Microsoft’s May 2026 passkey registration campaigns (sign-in nudges, which admins can enable or hand to a Microsoft-managed state that’s rolling out to more tenants) make the pretext resemble a legitimate tenant prompt.
- The most direct durable artifact is a small audit sequence — a ‘User registered security info’ record plus, on most paths, a generic ‘Update user’ whose StrongAuthenticationMethod/resultReason names the method — but alerting on it raw fires on every legitimate rollout enrollment and gets muted fast.
- The real signal is registration context: correlate the AuditLogs registration back to the originating SigninLogs event by user identity, time, IP/device, and app/resource context (don’t rely on correlationId as a cross-table key — Microsoft says its presence in multiple logs doesn’t mean they join), then tier it — page on a new passkey from an unmanaged device on a novel network, investigate on any single strong anomaly, downgrade but don’t automatically discard managed-device or corporate/VPN-location activity, and explicitly account for new-hire onboarding.
- Close the door by protecting the Register security information CA action with an approved strong-auth or controlled-bootstrap path (a built-in phishing-resistant strength won’t admit a TAP, so design the bootstrap deliberately and verify in report-only), monitor TAP issuance separately as a privileged admin event, and on a confirmed hit delete the passkey, reset the password, and revoke sign-in sessions together — recognizing that refresh-token revocation takes time to propagate and already-issued access tokens or application-managed sessions can remain usable until expiry or CAE enforcement.
Okta reports that Palo Alto Networks Unit 42 tracks the same cluster as CL-CRI-1147, tied to The Com, the loose extortion collective that also spun up Scattered Spider and LAPSUS$. Per The Hacker News writeup, the group has run a data-leak site called Pink since April 2026 and has hit food-and-beverage, healthcare, aviation, automotive, tech, and construction orgs. Motivation is boring — data extortion. The tradecraft is the interesting part, because it’s aimed squarely at the control most shops spent the last two years standing up.
Why the enrollment step is the soft spot
Phishing-resistant MFA solves authentication. It does nothing for registration. And the registration surface in Entra is wide by default: where passkeys are enabled for the user in the Authentication Methods policy and the Register security information action carries no stronger control than ordinary MFA, anyone who completes that MFA can walk into combined security-info registration and add the method. That’s the design — self-service registration is how passkeys scale without the helpdesk drowning. It’s also why, under those preconditions, a phished password and a single relayed OTP is enough to mint a new authenticator. (Users can only register methods the tenant has actually enabled for them, so the exposure is scoped to what your Authentication Methods policy allows — which, for most tenants standing up passwordless, now includes passkeys.)
The operator side is a real-time PHP panel, not an automated kit that fires and forgets. Okta’s breakdown shows distinct panel endpoints for each MFA type the victim might face (/submit-otp, /submit-authenticator, /approve-authenticator), so the operator adapts the fake flow to whatever the tenant actually enforces mid-session. Number-match push? The panel shows the victim the number to approve. TOTP? It prompts for the six digits and relays them before they expire. The BIP-39 seed-phrase page is pure misdirection — it keeps the user’s eyes on their own screen during the seconds the attacker needs to finish enrollment on the real one.
Here’s the part that ruins your Tuesday. As of May 2026, Microsoft supports passkey registration campaigns that nudge selected users to enroll during sign-in. Admins can turn them on directly (State = Enabled), or hand control to a Microsoft-managed state that Microsoft is incrementally rolling out — one that shifts the default nudge toward passkeys and widens targeting from just voice/SMS users to all MFA-capable users. Either way, the story the attacker tells — “you need to set up a passkey” — matches a prompt your own tenant may already be showing users at sign-in. The social engineering isn’t fighting your security awareness training. It’s riding on top of your own change management. (Separately, Microsoft emails the account owner after a passkey is registered. That notification is useful corroborating evidence for the victim or the SOC — but it lands after the persistence event, so treat it as a warning signal, not a control.)
What the event actually looks like in the index
Stop thinking about this as “detect the phishing.” The phishing session that harvested the OTP is transient and, from the tenant’s side, looks like a successful interactive sign-in. The durable artifact — the thing that outlives the password reset and preserves the attacker’s access until the method is discovered and removed — is the method registration. Alert on that.
In Sentinel, the anchor is the AuditLogs table. Depending on the registration path and the schema your connector exports, you may see both a high-level registration event and a lower-level user-update event — which trips people up the first time. The high-level one comes from the Authentication Methods service under category UserManagement with a friendly OperationName like User registered security info (you’ll also see User started security info registration and User changed default security info), and it’s readable but thin — it tells you that a method was registered, not which one. Where exposed, the lower-level record may appear as a generic Update user; in the schema used by Splunk’s analytic and the documented KQL hunting examples, the method change appears in TargetResources.modifiedProperties under StrongAuthenticationMethod, and resultReason may contain a description such as User registered Fido2 Authentication Method. Where your export exposes that StrongAuthenticationMethod change, that lower-level record can identify the method more precisely than the generic registration event — but don’t treat the paired representation as a guaranteed contract across every connector; confirm the shape your own tenant emits before you build field-level KQL against it.
Splunk’s shipped analytic, Azure AD New MFA Method Registered, keys on exactly this: sourcetype=azure:monitor:aad, operationName="Update user", pull targetResources{}.modifiedProperties{}.displayName, filter to StrongAuthenticationMethod, and count MethodType occurrences in the new value versus the old to decide a method was added rather than removed. Fine as a primitive. But it ships disabled in Enterprise Security, runs hourly on a 70-minute lookback, and — read the vendor’s own note — its false-positive guidance is “users register MFA methods legitimately, investigate and filter as needed.” Which is another way of saying: on its own, this fires on every passkey your rollout campaign successfully lands.
That’s the volume problem. During an active passkey rollout the raw User registered security info event is high-volume and almost entirely legitimate — how high depends on your rollout scope, user population, campaign configuration, and onboarding cadence, so measure it against your own enrollment baseline rather than trusting anyone’s fleet-wide number. Alert on the raw event and you’ve built a firehose that the SOC mutes by Thursday. The registration event is necessary but nowhere near sufficient.
The signal is registration context, not registration
The most useful distinction is usually the context of the session that performed the enrollment — location is only one component; authentication sequence, prior method history, device state, IP reputation, ASN novelty, and app context can matter as much. In a managed-enterprise rollout, legitimate enrollment may disproportionately originate from compliant or previously observed devices and familiar network context, often already past a device-compliance grant. The O-UNC-066 registration, by contrast, is performed through the operator’s parallel Microsoft sign-in — the session established with the relayed credentials: frequently a non-compliant device, an IP/ASN the user has never touched, often a hosting-provider range, landing within a few minutes of an interactive password-plus-OTP sign-in rather than following an existing strong session.
So the detection worth building joins two tables: the registration event from AuditLogs, correlated back to the originating sign-in in SigninLogs. The tempting shortcut is to join on correlationId, and where the values demonstrably line up in your tenant, use it — but do not depend on it. Microsoft’s own schema doc is explicit that a correlation ID’s presence in multiple logs “doesn’t indicate the ability to join logs across services,” so treat it as a nice-to-have, not a foreign key. The practical fallback is a bounded, multi-field temporal correlation — a probabilistic association rather than a deterministic join: same user identity, a tight window (10 minutes is a reasonable start), plus initiating IP where available, sign-in time, authentication details, and app/resource context to tie the registration to the session that established it. It isn’t foolproof either — multiple concurrent sign-ins, background authentications, NAT, and shared or delayed-ingestion IPs can all create false associations, so weight it, don’t trust it blindly. The audit event’s InitiatedBy structure and the sign-in record often give you stronger linking fields than the presumed shared ID.
Then rank rather than filter to a single hard intersection. An AND of “non-compliant device and untrusted location” is high-precision but low-recall — it misses attackers on residential proxies near the victim, in the victim’s normal geography, on a remote-controlled managed device, inheriting a device claim from an existing session, or where the device state is simply null rather than an explicit false. A tiered model holds up better:
- Page (high severity): a new passkey/FIDO2 method registered from an unmanaged or non-compliant device on an untrusted or novel network.
- Investigate (medium severity): a new passkey plus any one strong anomaly — a new ASN, an atypical- or impossible-travel finding associated with the account, unfamiliar sign-in properties, relayable MFA immediately before the registration, or no prior strong-authenticator use on the account.
- Hunt: all new passkeys, baselined against history with onboarding excluded.
Treat null/unavailable device state as its own bucket, not as “known good” — a missing compliance value is not the same as compliant.
First tuning round, in order of what actually bites:
- Managed-device signals carve out most of the noise — as a downgrade, not a hard drop. Join on
deviceDetail.isCompliant/isManagedfrom the sign-in and lower the severity of registrations from known-compliant devices rather than discarding them globally. This is your biggest single reduction, but a blanket exclusion contradicts the threat model above — a vishing crew that remote-controls a managed endpoint or rides a session carrying a trusted device claim would land in exactly the bucket you dropped. Reserve a hard exclusion for cases your own testing justifies. - Named locations for the corporate egress and known VPN ranges kill another chunk, but only if someone has actually maintained the named-location list. The one that’s two years stale and still lists an office you closed will quietly pass attacker traffic.
- The bootstrap window. New-hire onboarding legitimately registers a first strong method from a fresh device that isn’t compliant yet, from home. That’s the same fingerprint as the attack. You’ll need to except your provisioning flow explicitly (by the onboarding app, the HR-driven group, or a first-N-days grace) or your genuine detection will bury the real hit under new-starter noise every Monday.
Environment assumptions that change the whole calculus. If your workforce is heavily remote and BYOD, isCompliant is mostly false across the board and the managed-device filter buys you almost nothing — you’ll lean much harder on location and on the tight temporal join to the OTP sign-in. If you run a flat tenant with self-service registration wide open and no device compliance in Conditional Access at all, you don’t have the fields to build the good version of this detection, and the honest answer is that the raw registration alert is all you’ve got until you fix the upstream policy. B2B guests are largely a separate case rather than another tuning bucket. Microsoft currently states that passkey support for guest users isn’t available and that guests aren’t nudged by passkey registration campaigns, so external guests shouldn’t be routinely enrolling Entra passkeys in your resource tenant at all — and where they do authenticate, home-tenant device and MFA claims may or may not be trusted through your cross-tenant access settings, so the context won’t line up with your own compliance signals anyway. Validate the behavior for internal guests, converted users, and any future cross-tenant passkey support before you fold guest identities into this detection.
Closing the registration path, and the reset that actually works
Detection buys you response time. It doesn’t close the door. The door is the security-info registration user action in Conditional Access. Target Register security information and require an authentication strength that admits only your approved bootstrap paths. For established users, that means requiring an existing phishing-resistant authenticator — FIDO2, Windows Hello for Business, or certificate-based. Once that’s on, a phished password and a relayed OTP no longer satisfy the policy to register a new method; the attacker would need an existing phishing-resistant credential to bootstrap another one, which is the whole point.
The catch is the chicken-and-egg problem, and it’s a real one, not a footnote. A brand-new user has no phishing-resistant credential yet, so a policy that demands one to register one locks them out on day zero. Microsoft’s answer is the Temporary Access Pass — but watch the detail that bites here: the built-in phishing-resistant MFA authentication strength does not include TAP, so if you naively require that strength on Register security information, you’ll wall out the very TAP bootstrap you were relying on. The fix is to create an approved bootstrap strength — typically a custom authentication strength containing TAP — and apply it through a registration policy whose scope is mutually exclusive with the established-user policy, then verify in report-only that the strength you selected actually permits the intended TAP path before you enforce it. (Those aren’t two alternatives; the usual implementation needs both the custom strength and the scoped policy.) One trap to design around: authentication-strength requirements from multiple applicable registration policies are cumulative, not OR conditions — a user must satisfy every policy that targets the action. So an all-users phishing-resistant policy sitting next to a TAP-bootstrap policy still blocks the new user; make the bootstrap and established-user scopes mutually exclusive (exclude the bootstrap population from the strict policy) rather than assuming the second policy opens an alternative path. And a TAP is issued by an administrator or automation, not self-registered by the user — Authentication Administrators and Privileged Authentication Administrators create it, within their administrative scope — so it’s now among the most valuable things in your tenant: whoever can issue a TAP for a target user can potentially bootstrap a passkey for that account, and The Com’s entire playbook is social-engineering helpdesks. So the CA policy moves the attack from the end user to the TAP issuance path; it doesn’t delete it. Restrict TAP creation through least-privilege role assignment, PIM, and administrative-unit scoping — “a small named group” isn’t a single TAP policy setting — configure short lifetimes and one-time use where the workflow permits, and monitor TAP issuance as a distinct privileged-admin event, separate from the user passkey-registration detection above; then correlate the subsequent TAP use (in sign-in telemetry) with the passwordless method registered from that session. Set the CA policy to report-only first and read the sign-in logs for a week before you flip it on, or you’ll wall off legitimate registration you didn’t know depended on a weaker method.
The cleanup step people get wrong: deleting the rogue passkey is not remediation. A successful attacker sign-in may already have produced refresh and access tokens, and method deletion is not itself a token-revocation event — removing the authenticator does nothing to those tokens. Delete the passkey, reset the password, and revoke sign-in sessions (Revoke-MgUserSignInSession or the portal equivalent) together, and for a confirmed compromise consider blocking the account’s sign-in during remediation. Do it recognizing that revocation isn’t instantaneous or total: refresh-token revocation can take several minutes to propagate, while already-issued access tokens or application-managed sessions may remain usable until they expire or a CAE-capable service enforces the revocation — so the goal is to close the refresh-token loop, not to assume every live token dies the instant you click revoke. Skip the revoke entirely and the attacker re-registers a fresh passkey from the still-valid session before your ticket closes, and you’re back to square one wondering why the alert fired twice.
Where this lands in 800-53, briefly:
| Control | What it covers here |
|---|---|
| IA-5 | Authenticator management — the entire registration lifecycle is the attack surface; enrollment needs the same assurance as authentication |
| IA-2 | Phishing-resistant MFA as an authentication-strength gate on the registration action, not just on resource access |
| AC-2 | Account management — session revocation and credential reset as a single response, plus TAP issuance scoping |
| AU-6 | Audit review — the correlated AuditLogs/SigninLogs detection is an AU-6 analysis capability, not raw AU-2 collection |
| SI-4 | System monitoring — alerting on registration-in-risky-context |
The uncomfortable takeaway is that “we deployed phishing-resistant MFA” and “our identity enrollment is phishing-resistant” are different sentences, and O-UNC-066 makes a living in the gap between them. The credential is strong. The moment you create it is not, unless you went and made it so. Check whether your Register security information user action has an authentication-strength grant on it right now. If it doesn’t, that’s the first thing to fix, ahead of any detection you build.
Sources
- Vishing actors target Microsoft Entra passkey enrollment (Okta Threat Intelligence)
- Hackers use fake Microsoft Entra passkey enrollment to gain Microsoft 365 access (The Hacker News)
- Azure AD New MFA Method Registered (Splunk Security Content)
- Control security information registration with Conditional Access (Microsoft Learn)
- Overview of Conditional Access authentication strengths (Microsoft Learn)
- Run a registration campaign to set up a passkey or Microsoft Authenticator (Microsoft Learn)
- Configure a Temporary Access Pass to register passwordless authentication methods (Microsoft Learn)
- Learn about the monitoring and health activity log schemas — correlationId caveat (Microsoft Learn)
- Hunting for MFA manipulations in Entra ID tenants using KQL (Microsoft Community Hub)
- Decoding UserAuthenticationMethod in Microsoft 365 audit logs (Sekoia)
This post was engineered and validated through a multi-agent AI workflow — drafted, adversarially reviewed by several independent models, checked against primary sources, and given a human review before publishing. See an inaccuracy, or found this useful? Leave a comment below — corrections and feedback are read and shape what comes next.