Valid Accounts
Adversaries may obtain and abuse credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion. Compromised credentials may be used to bypass access controls placed on various resources on systems within the network and may even be used for persistent access to remote systems and externally available services, such as VPNs, Outlook Web Access, network devices, and remote desktop. Compromised credentials may also grant an adversary increased privilege to specific systems or access to restricted areas of the network. Adversaries may choose not to use malware or tools in conjunction with the legitimate access those credentials provide to make it harder to detect their presence. In some cases, adversaries may abuse inactive accounts belonging to individuals who are no longer part of an organization.
What is T1078 Valid Accounts?
Valid Accounts (T1078) maps to the Initial Access and Persistence and Privilege Escalation and Defense Evasion tactics — the adversary is trying to get into your network in MITRE ATT&CK.
This page provides production-ready detection logic for Valid Accounts, covering the data sources and telemetry it touches: Logon Session: Logon Session Creation, User Account: User Account Authentication, Azure Active Directory Sign-In Logs. The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Technique
- T1078 Valid Accounts
- Canonical reference
- https://attack.mitre.org/techniques/T1078/
// Detect anomalous logon patterns indicative of compromised valid accounts
let LookbackDays = 14d;
let AnomalyWindow = 1d;
// Baseline: countries/cities seen per user in lookback window
let UserLocationBaseline = SigninLogs
| where TimeGenerated between (ago(LookbackDays) .. ago(AnomalyWindow))
| where ResultType == 0
| summarize BaselineLocations=make_set(Location), BaselineIPs=make_set(IPAddress), BaselineApps=make_set(AppDisplayName) by UserPrincipalName;
// Recent logons to compare against baseline
let RecentLogons = SigninLogs
| where TimeGenerated > ago(AnomalyWindow)
| where ResultType == 0
| project TimeGenerated, UserPrincipalName, IPAddress, Location, AppDisplayName,
DeviceDetail, AuthenticationRequirement, ConditionalAccessStatus,
RiskLevelDuringSignIn, RiskLevelAggregated, IsInteractive;
// Join and find anomalies
RecentLogons
| join kind=leftouter UserLocationBaseline on UserPrincipalName
| extend NewLocation = not(Location in (BaselineLocations))
| extend NewIP = not(IPAddress in (BaselineIPs))
| extend NewApp = not(AppDisplayName in (BaselineApps))
| extend AnomalyScore = toint(NewLocation) + toint(NewIP) + toint(NewApp)
+ toint(RiskLevelDuringSignIn in ("high", "medium"))
+ toint(ConditionalAccessStatus == "notApplied")
| where AnomalyScore >= 2 or RiskLevelDuringSignIn == "high"
| project TimeGenerated, UserPrincipalName, IPAddress, Location, AppDisplayName,
NewLocation, NewIP, NewApp, AnomalyScore,
RiskLevelDuringSignIn, RiskLevelAggregated,
ConditionalAccessStatus, AuthenticationRequirement,
IsInteractive, DeviceDetail
| sort by AnomalyScore desc, TimeGenerated desc Detects anomalous sign-in patterns in Azure AD / Entra ID that may indicate valid account abuse. Compares recent logons against a 14-day baseline per user to identify new geolocations, new IP addresses, new application access, elevated risk scores, and missing Conditional Access enforcement. An anomaly score of 2+ triggers the alert. Covers Initial Access via external services and Persistence via re-authentication.
Data Sources
Required Tables
False Positives
- Legitimate travel — users accessing resources from new countries or cities during business travel
- VPN or proxy changes — users switching VPN exit nodes causing IP and apparent location changes
- New device enrollment — first-time access from a newly provisioned corporate device triggers 'new IP' anomaly
- After-hours legitimate access — on-call engineers or executives working outside normal hours from home networks
- Conditional Access policy rollout periods — new CA policies may temporarily show as 'notApplied' during staged deployment
Sigma rule & cross-platform mapping
The detection logic for Valid Accounts (T1078) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
product: azure Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1078
References (8)
- https://attack.mitre.org/techniques/T1078/
- https://www.cisa.gov/uscert/ncas/alerts/aa22-074a
- https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/concept-sign-ins
- https://learn.microsoft.com/en-us/azure/active-directory/identity-protection/overview-identity-protection
- https://docs.splunk.com/Documentation/SplunkCloud/latest/SearchReference/CommonStatsFunctions
- https://www.mandiant.com/resources/blog/unc3944-scattered-spider
- https://www.cisa.gov/sites/default/files/2024-02/aa24-038a-prc-state-sponsored-actors-compromise-us-critical-infrastructure_0.pdf
- https://technet.microsoft.com/en-us/library/dn535501.aspx
Testing Methodology
Validate this detection against 5 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulate Compromised Account Remote Logon (Windows)
Expected signal: Security Event ID 4648 on source host (explicit credential logon with alternate credentials). Security Event ID 4624 LogonType=3 (network) on target host. Sysmon Event ID 3 (network connection) from cmd.exe to TARGET_HOST:445. Security Event ID 4672 if USERNAME has special privileges.
- Test 2Simulate Service Account Lateral Movement via WMI
Expected signal: Security Event ID 4648 on initiating host. Security Event ID 4624 LogonType=3 on TARGET_HOST. Security Event ID 4688 (or Sysmon Event ID 1) showing WmiPrvSE.exe spawning cmd.exe on TARGET_HOST. Sysmon Event ID 3 showing DCOM/WMI network traffic to TARGET_HOST:135.
- Test 3Simulate Dormant Account Reactivation (Local)
Expected signal: Security Event ID 4720 (account created). Security Event ID 4725 (account disabled). Security Event ID 4722 (account enabled — key indicator of reactivation). Security Event ID 4624 LogonType=2 (interactive) for df00tech_dormant. Audit event for account enabling action.
- Test 4Simulate Cloud Account Compromise via Azure CLI
Expected signal: Azure AD SigninLogs entry with UserPrincipalName=compromised_user, AppDisplayName='Microsoft Azure CLI', ClientAppUsed='Other clients', AuthenticationRequirement='singleFactorAuthentication' (if no MFA). Azure Audit Log entries for resource enumeration. Entra ID Protection may generate a risk detection if login is from an unexpected location.
- Test 5Test Impossible Travel Detection Trigger
Expected signal: Two SigninLogs entries for [email protected]: first from US IP, second from EU IP approximately 2 minutes later. Entra ID Protection should generate an 'Impossible Travel' risk detection. Both entries appear in the 24h window, different Location fields.
Response Playbook
Triage
- Retrieve the full sign-in history for the account over the past 30 days — look for the first anomalous logon timestamp and what changed (new IP, new ASN, new country, new device fingerprint)
- Check whether the account is a human user or service account — service accounts should have fixed source IPs and hosts; any deviation is high-confidence malicious
- Identify the authentication method used — password-only auth on an MFA-enrolled account without an MFA event suggests MFA bypass (SIM swap, OTP phishing, adversary-in-the-middle)
- Cross-reference the source IP against threat intel feeds — check VirusTotal, Shodan, or AbuseIPDB for the IP/ASN; residential proxy infrastructure and VPN exit nodes are common for credential abuse
- Determine geographic plausibility — if the user logged in from New York 30 minutes before logging in from Singapore, the second login is impossible travel and high-confidence compromise
- Review what the account accessed after the anomalous logon — did it access sensitive SharePoint/OneDrive, email, admin portals, or begin lateral movement via RDP/SMB?
- Check if the account has recent MFA registration changes, password resets, or new app authorizations — adversaries often register new MFA devices or OAuth apps to maintain persistence after initial access
Containment
- Immediately revoke all active sessions and refresh tokens for the compromised account: in Entra ID use 'Revoke Sign-In Sessions' from the user blade, or run: Revoke-AzureADUserAllRefreshToken -ObjectId <user-object-id>
- Force password reset and require re-enrollment of MFA factors — specifically remove any MFA devices registered during or after the suspicious logon window
- If on-premises AD: reset the Kerberos ticket-granting ticket by resetting the account password twice and running 'klist purge' on affected endpoints
- Disable the account temporarily if immediate password reset is not operationally feasible, then coordinate with the user out-of-band (phone/in-person) for credential restoration
- Block the identified threat actor IP(s)/ASN at the perimeter firewall, Conditional Access named locations, and email gateway
- If lateral movement is detected: isolate affected endpoints using EDR network containment, and rotate credentials for any service accounts the compromised user could access
- Audit and revoke any OAuth application consents granted during the suspicious session window
Evidence Collection
- Azure AD / Entra ID Sign-In Logs (retention: 30 days default) — export to Log Analytics or Storage Account immediately if within window; include non-interactive sign-ins which are often missed
- Azure AD Audit Logs — capture any MFA registration changes, password resets, role assignments, or OAuth consent grants made during the suspicious window
- Windows Security Event ID 4624/4625/4648/4672 from domain controllers and affected endpoints — extract with wevtutil: wevtutil qe Security /q:"*[System[(EventID=4624 or EventID=4625) and TimeCreated[@SystemTime>='2026-03-14T00:00:00']]]"
- VPN/remote access gateway logs — source IPs, connection duration, and transferred data volume during the suspicious period
- Email access logs (Exchange/M365) — MailItemsAccessed audit record shows which emails were read; run: Search-UnifiedAuditLog -Operations MailItemsAccessed -UserIds <upn> -StartDate <date> -EndDate <date>
- SharePoint/OneDrive access logs — FileAccessed, FileDownloaded events in the Unified Audit Log for any mass download during the suspicious window
- Endpoint process creation and network events from the workstation(s) involved in the suspicious logon (Sysmon Event ID 1 and 3)
- UEBA/Identity Protection risk detections export from Entra ID Protection — these may contain pre-existing risk signals that predated the alert
Escalation Criteria
- ! Confirmed impossible travel — two geographically separated successful logons within a timeframe that is physically impossible
- ! MFA bypass evidence — successful authentication without a corresponding MFA event for an MFA-enrolled account
- ! Privileged account compromise — any Domain Admin, Global Admin, or high-privilege service account showing anomalous access patterns
- ! Evidence of email exfiltration — MailItemsAccessed events for large volumes of sensitive email, or inbox rules forwarding to external addresses created post-compromise
- ! Lateral movement detected — the compromised account authenticating to additional hosts, using WMI, PsExec, RDP, or SMB after the initial anomalous logon
- ! Persistence mechanism established — new MFA device registered, OAuth app authorized, scheduled task or service created using the compromised account
- ! Multiple accounts compromised simultaneously — same source IP/ASN with anomalous logons across several accounts suggests bulk credential stuffing or a broader breach
Investigation Guide
Forensic Artifacts
- >
Windows Event Log: Security — Event 4624 (successful logon) with LogonType, Source IP, AuthPackage; Event 4625 (failed logon); Event 4648 (explicit credential use); Event 4672 (special privilege assigned) - >
Windows Event Log: Security — Event 4768/4769 (Kerberos TGT/TGS requests) at domain controllers — reveals ticket-granting activity for the compromised account - >
Windows Event Log: Security — Event 4776 (NTLM authentication) at domain controllers — source workstation and account for NTLM-based access - >
Registry: HKLM\SYSTEM\CurrentControlSet\Control\Lsa — CachedLogonsCount, LmCompatibilityLevel affect authentication artifacts - >
Registry: HKCU\Software\Microsoft\Terminal Server Client\Servers — cached RDP server entries indicating lateral movement destinations - >
File System: C:\Users\<username>\AppData\Local\Microsoft\Credentials\ — DPAPI-protected credential blobs - >
File System: C:\Windows\System32\winevt\Logs\Security.evtx — primary authentication event log (export before rotation) - >
Azure AD: Sign-In Logs, Audit Logs, Risk Detections in Entra ID Protection (accessible via Azure Portal or Microsoft Graph API) - >
Memory: LSASS process memory contains active Kerberos tickets and NTLM hashes for logged-on users — volatile, capture immediately if endpoint is live - >
Network: NetFlow/firewall logs showing source IP, destination, protocol, and data volume for the suspicious session window
Tuning Guidance
Valid account detections require careful baseline establishment to avoid alert fatigue. Begin with a 30-day baseline of normal user behavior before enabling automated alerting. Key tuning steps: (1) Build an allowlist of known VPN exit node IP ranges and corporate proxy infrastructure — these create legitimate IP diversity. (2) Exclude service accounts from human-behavior anomaly rules and instead create dedicated rules for service account deviation (service accounts should have fixed source IPs, logon types, and target systems). (3) For MFA-enrolled accounts, add MFA success/failure as a required field — password-only auth on MFA accounts is almost always suspicious. (4) Use Entra ID Identity Protection risk scores as a pre-filter — risk scores of 'medium' or 'high' significantly reduce false positives. (5) Tune the dormancy threshold to match your organization's offboarding processes — if accounts are routinely disabled within 14 days of termination, a 30-day dormancy threshold may be appropriate. (6) For on-premises environments, create separate rules for interactive (Type 2, 10) vs. network (Type 3) logons — bulk Type 3 logons from service accounts are normal; bulk Type 10 (RDP) from non-admin accounts is suspicious. (7) Integrate with HR/ITSM systems to automatically exclude accounts with active travel requests or contractor engagements in new geographies.
Hunting Queries
Hunt for accounts authenticating from 3 or more distinct countries within a 24-hour window. This pattern indicates either account sharing (policy violation), credential compromise with active threat actor access, or legitimate global travel that warrants verification. APT groups like Scattered Spider are known to use residential proxies that appear as different country origins.
// Hunt for accounts logging in from multiple countries within 24h (impossible travel)
let TimeWindow = 24h;
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| summarize Countries=make_set(Location), IPs=make_set(IPAddress), LogonCount=count(),
FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated)
by UserPrincipalName, bin(TimeGenerated, TimeWindow)
| extend CountryCount=array_length(Countries)
| where CountryCount >= 3
| project-away TimeGenerated
| sort by CountryCount desc index=o365 sourcetype="o365:management:activity" Operation="UserLoggedIn" ResultStatus="Succeeded"
| iplocation ClientIP
| stats dc(Country) as CountryCount, values(Country) as Countries, values(ClientIP) as IPs,
count as LogonCount, earliest(_time) as FirstSeen, latest(_time) as LastSeen
by UserId, span=24h
| where CountryCount >= 3
| sort - CountryCount Hunt for accounts dormant for 90+ days that have suddenly become active. Adversaries frequently target inactive accounts of former employees or service accounts as they are less likely to have password changes, active MFA, or monitoring. This pattern is consistent with CISA-documented techniques used by groups targeting critical infrastructure.
// Hunt for dormant accounts suddenly becoming active after 90+ days of inactivity
let DormancyThreshold = 90d;
let RecentWindow = 7d;
let DormantAccounts = SigninLogs
| where TimeGenerated between (ago(365d) .. ago(DormancyThreshold))
| where ResultType == 0
| summarize LastActiveDate=max(TimeGenerated) by UserPrincipalName;
let RecentLogons = SigninLogs
| where TimeGenerated > ago(RecentWindow)
| where ResultType == 0
| summarize RecentLogonCount=count(), RecentIPs=make_set(IPAddress), RecentApps=make_set(AppDisplayName)
by UserPrincipalName, RecentLogonDate=bin(TimeGenerated, 1d);
DormantAccounts
| join kind=inner RecentLogons on UserPrincipalName
| extend DaysDormant = datetime_diff('day', RecentLogonDate, LastActiveDate)
| where DaysDormant >= DormancyThreshold
| project UserPrincipalName, LastActiveDate, RecentLogonDate, DaysDormant,
RecentLogonCount, RecentIPs, RecentApps
| sort by DaysDormant desc index=wineventlog sourcetype="WinEventLog:Security" EventCode=4624
| bucket span=1d _time
| stats latest(_time) as LastLogon by TargetUserName
| eval DaysSinceLastLogon=round((now()-LastLogon)/86400, 0)
| where DaysSinceLastLogon < 7
| join type=left TargetUserName
[search index=wineventlog sourcetype="WinEventLog:Security" EventCode=4624 earliest=-365d latest=-90d
| stats latest(_time) as PreviousLogon by TargetUserName
| eval DaysDormant=round((now()-PreviousLogon)/86400, 0)
| where DaysDormant >= 90]
| where isnotnull(PreviousLogon)
| table TargetUserName, LastLogon, PreviousLogon, DaysDormant
| sort - DaysDormant Hunt for accounts with concurrent or near-concurrent sessions from multiple distinct IP addresses within a 30-minute window. Legitimate users rarely authenticate from 3+ different IPs within 30 minutes. This pattern may indicate active credential sharing by a threat actor across multiple infrastructure nodes, or a credential-sharing botnet performing simultaneous actions with stolen credentials.
// Hunt for accounts used simultaneously from multiple distinct IP address ranges (concurrent sessions)
let ConcurrentWindow = 30m;
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| summarize Sessions=make_list(pack('time', TimeGenerated, 'ip', IPAddress, 'app', AppDisplayName, 'location', Location))
by UserPrincipalName
| mv-expand Session=Sessions
| extend SessionTime=todatetime(Session.time), SessionIP=tostring(Session.ip)
| order by UserPrincipalName, SessionTime asc
| serialize
| extend PrevTime=prev(SessionTime), PrevIP=prev(IPAddress), PrevUser=prev(UserPrincipalName)
| where UserPrincipalName == PrevUser
| extend TimeDiff=datetime_diff('minute', SessionTime, PrevTime)
| where TimeDiff <= toint(ConcurrentWindow / 1m) and SessionIP != PrevIP
| project UserPrincipalName, SessionTime, SessionIP, PrevTime, PrevIP, TimeDiff
| sort by TimeDiff asc index=wineventlog sourcetype="WinEventLog:Security" EventCode=4624 LogonType IN ("3", "10")
| stats list(_time) as LogonTimes, list(IpAddress) as IpAddresses, dc(IpAddress) as UniqueIPs
by TargetUserName span=30m
| where UniqueIPs >= 3
| mvexpand LogonTimes
| mvexpand IpAddresses
| stats values(IpAddresses) as IPs, count as Sessions by TargetUserName, UniqueIPs
| sort - UniqueIPs Atomic Red Team Tests
Uses stored credentials to perform a network logon to a remote system, simulating an adversary using compromised credentials to access internal resources. This generates Event ID 4648 (explicit credential use) on the source and 4624 LogonType 3 on the target. Replace TARGET_HOST, USERNAME, and DOMAIN with test environment values.
Command
cmdkey /add:TARGET_HOST /user:DOMAIN\USERNAME /pass:Password123!
net use \\TARGET_HOST\IPC$ /user:DOMAIN\USERNAME Password123!
net use \\TARGET_HOST\IPC$ /delete Cleanup
cmdkey /delete:TARGET_HOST Expected Telemetry
Security Event ID 4648 on source host (explicit credential logon with alternate credentials). Security Event ID 4624 LogonType=3 (network) on target host. Sysmon Event ID 3 (network connection) from cmd.exe to TARGET_HOST:445. Security Event ID 4672 if USERNAME has special privileges.
Expected Detection
SPL rule triggers on 4648 + 4624 combination with UniqueSourceIPs > 1 within the hour window. KQL anomaly rule flags new IP/workstation combination for USERNAME if not seen in 14-day baseline.
Uses WMI with explicit credentials to execute a command on a remote host, mimicking APT41 and FIN8 lateral movement techniques where compromised service account credentials are used for remote code execution. Generates Event 4648 and 4624 LogonType 3, plus WMI activity.
Command
wmic /node:TARGET_HOST /user:DOMAIN\svc_account /password:ServicePass1! process call create "cmd.exe /c whoami > C:\Windows\Temp\wmi_test.txt" Cleanup
wmic /node:TARGET_HOST /user:DOMAIN\svc_account /password:ServicePass1! process call create "cmd.exe /c del C:\Windows\Temp\wmi_test.txt" Expected Telemetry
Security Event ID 4648 on initiating host. Security Event ID 4624 LogonType=3 on TARGET_HOST. Security Event ID 4688 (or Sysmon Event ID 1) showing WmiPrvSE.exe spawning cmd.exe on TARGET_HOST. Sysmon Event ID 3 showing DCOM/WMI network traffic to TARGET_HOST:135.
Expected Detection
SPL risk score elevates due to NewCredentialUse (4648) + PrivilegedLogons if svc_account has admin rights. Lateral movement hunting query flags WmiPrvSE parent-child process chain on target host.
Creates a disabled local account, enables it, and performs a local interactive logon to simulate adversary reactivation of a dormant/inactive account — a technique used by groups like Scattered Spider to abuse former employee accounts. Requires local admin.
Command
net user df00tech_dormant TempPass123! /add /comment:"Test dormant account"
net user df00tech_dormant /active:no
ping -n 3 127.0.0.1 > nul
net user df00tech_dormant /active:yes
runas /user:df00tech_dormant cmd.exe Cleanup
net user df00tech_dormant /delete Expected Telemetry
Security Event ID 4720 (account created). Security Event ID 4725 (account disabled). Security Event ID 4722 (account enabled — key indicator of reactivation). Security Event ID 4624 LogonType=2 (interactive) for df00tech_dormant. Audit event for account enabling action.
Expected Detection
Dormant account hunting query matches df00tech_dormant (disabled then re-enabled). Event ID 4722 followed quickly by 4624 for an account with no prior logon history triggers escalation criteria.
Authenticates to Azure using compromised credentials and enumerates resources, simulating Initial Access via cloud console access as performed by groups like Scattered Spider and Volt Typhoon. Uses the Azure CLI — install with: curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
Command
az login --username [email protected] --password 'CompromisedPassword1!'
az account list --output table
az ad signed-in-user show
az role assignment list --assignee [email protected] Cleanup
az logout Expected Telemetry
Azure AD SigninLogs entry with UserPrincipalName=compromised_user, AppDisplayName='Microsoft Azure CLI', ClientAppUsed='Other clients', AuthenticationRequirement='singleFactorAuthentication' (if no MFA). Azure Audit Log entries for resource enumeration. Entra ID Protection may generate a risk detection if login is from an unexpected location.
Expected Detection
KQL anomaly detection fires if location or IP is new relative to 14-day baseline. AnomalyScore includes NewLocation + NewApp (CLI vs. browser) = 2, meeting threshold. Missing MFA event adds to escalation criteria.
Performs sequential authentications using VPN endpoints in geographically separated regions within a short time window to test impossible travel detection logic. Requires access to two VPN exit nodes in different countries/regions. This validates that your SIEM correctly identifies the impossible travel pattern.
Command
# Connect to VPN exit node 1 (e.g., US)
echo '[+] Authenticating from VPN endpoint 1 (US)'
curl -s -X POST 'https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token' \
-d 'grant_type=password&client_id=CLIENT_ID&[email protected]&password=TestPass1!&scope=openid'
sleep 120
# Connect to VPN exit node 2 (e.g., EU) and repeat authentication
echo '[+] Authenticating from VPN endpoint 2 (EU) - switch VPN now'
curl -s -X POST 'https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token' \
-d 'grant_type=password&client_id=CLIENT_ID&[email protected]&password=TestPass1!&scope=openid' Cleanup
# Revoke test sessions in Entra ID admin portal or via: az ad user revoke-sign-in-sessions --id [email protected] Expected Telemetry
Two SigninLogs entries for [email protected]: first from US IP, second from EU IP approximately 2 minutes later. Entra ID Protection should generate an 'Impossible Travel' risk detection. Both entries appear in the 24h window, different Location fields.
Expected Detection
KQL hunting query for 3+ countries in 24h may not fire for only 2 countries — adjust to 2+ for testing. Entra ID Protection impossible travel detection fires independently. AnomalyScore on second login = 2 (NewLocation + NewIP), meeting KQL alert threshold.