Microsoft Sentinelv1.0
Anomalous Windows Hello For Business Sign In Without Device ID
Anomalous Windows Hello for Business (WHfB) sign-ins without a Device ID often indicate security research or a cyberattack where malware silently invokes a hardware-bound WHfB key. This attack uses active endpoint sessions to mint tokens for Microsoft Entra ID without needing PIN extraction or biometric prompts.
By ThreatBeaconX Research Team · Updated Sep 2, 2026 · 41 views
anomalous-windows-hello-for-business-sign-in-without-device-id.kql
let Lookback = 1d;let BaselineWindow = 30d;let MinBaselineEvents = 10; // ignore users with too little history// Genuine primary WHfB authentications onlylet WHfBSignins =SigninLogs| where TimeGenerated > ago(BaselineWindow)| where ResultType == 0| where AuthenticationDetails has "Hello"| where IncomingTokenType in ("none", "") // exclude SSO follow-ups and token refreshes| mv-apply Detail = todynamic(AuthenticationDetails) on (where tobool(Detail.succeeded) == trueand tostring(Detail.authenticationMethod) == "Windows Hello for Business"and tostring(Detail.authenticationStepResultDetail) !has "claim" // drop inherited MFA claims| summarize StepDetail = make_set(tostring(Detail.authenticationStepResultDetail)))| extend DeviceId = tostring(DeviceDetail.deviceId),ASN = tostring(AutonomousSystemNumber);// Per-user baseline: how consistently does this user present a device ID?let Baseline =WHfBSignins| where TimeGenerated between (ago(BaselineWindow) .. ago(Lookback))| summarize BaselineEvents = count(),DeviceIdRatio = countif(isnotempty(DeviceId)) * 1.0 / count(),KnownASNs = make_set(ASN, 200),KnownAgents = make_set(UserAgent, 200)by UserPrincipalName;WHfBSignins| where TimeGenerated > ago(Lookback)| where isempty(DeviceId)| lookup kind=inner Baseline on UserPrincipalName| where BaselineEvents >= MinBaselineEvents| where DeviceIdRatio >= 0.95 // user virtually always submits a device ID| extend NewASN = isnotempty(ASN) and not(set_has_element(KnownASNs, ASN)),NewUserAgent = isnotempty(UserAgent) and not(set_has_element(KnownAgents, UserAgent)),RiskySignin = RiskLevelDuringSignIn in ("medium", "high")| extend Score = toint(iff(NewASN, 40, 0))+ toint(iff(NewUserAgent, 30, 0))+ toint(iff(RiskySignin, 30, 0))+ toint(iff(ConditionalAccessStatus == "notApplied", 10, 0))| where Score >= 40 // require at least one strong novelty signal| extend Verdict = case(Score >= 70, "High: WHfB primary auth without device ID from a previously unseen network or client","Medium: WHfB primary auth without device ID, single novelty signal")| project Verdict,Score,TimeGenerated,UserPrincipalName,IPAddress,ASN,Location,UserAgent,AppDisplayName,ResourceDisplayName,ConditionalAccessStatus,RiskLevelDuringSignIn,DeviceIdRatio,NewASN,NewUserAgent,CorrelationId| order by Score desc, TimeGenerated desc