↳ GitHub sourceAnalytics ruleMedium
Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection
Description
Identifies previously unseen IP and user agents in a Dataverse instance following disabling of cookie binding protection. See https://docs.microsoft.com/power-platform/admin/block-cookie-replay-attack
- Rule type
- Scheduled
- Version
- 3.2.0
- Declared status
- Available
- Query frequency
- 1h
- Query period
- 14d
- Trigger
- gt 0
Declared MITRE coverage
Declared sources
Metadata from the source file. No dependencies inferred from KQL.
Connectors
Data types
KQL query
Original query, unchanged.
let query_frequency = 1h;
let query_lookback = 14d;
let cookie_lifetime = 24h;
let cookie_binding_disabled_events = DataverseActivity
| where TimeGenerated >= ago(query_lookback)
| where Message == "Update" and EntityName == "organization"
| mv-expand Fields
| where Fields.Name == "enableipbasedcookiebinding" and Fields.Value == 'False'
| summarize CookieBindingDisabled = min(TimeGenerated) by CookieBindingDisabledBy = UserId, InstanceUrl;
let current_activity = cookie_binding_disabled_events
| join kind=inner(DataverseActivity
| where UserId !endswith "@onmicrosoft.com" and UserId !endswith "@microsoft.com"
| where isnotempty(ClientIp) and isnotempty(UserAgent)
| where TimeGenerated >= ago(query_frequency + cookie_lifetime)
| summarize LatestEvent = arg_max(TimeGenerated, *) by UserId, ClientIp, InstanceUrl)
on InstanceUrl;
let users_switched_ip = current_activity
| summarize IPCount = count() by UserId, InstanceUrl
| where IPCount > 1
| join kind=inner (current_activity) on UserId, InstanceUrl
| summarize arg_max(LatestEvent, *) by UserId, InstanceUrl;
users_switched_ip
| join kind = inner (DataverseActivity
| where TimeGenerated >= ago (query_lookback)
| where UserId !endswith "@onmicrosoft.com" and UserId !endswith "@microsoft.com"
| where isnotempty(ClientIp) and isnotempty(UserAgent)
| project-rename
HistoricalTime = TimeGenerated,
HistoricalIP = ClientIp,
HistoricalAgent = UserAgent)
on UserId, InstanceUrl
| where HistoricalTime >= ago(query_lookback) and HistoricalTime < LatestEvent
| summarize
HistoricalIPs = make_set(HistoricalIP, 100),
HistoricalAgents = make_set(HistoricalAgent, 100)
by
UserId,
UserAgent,
ClientIp,
InstanceUrl,
LatestEvent,
CookieBindingDisabled,
CookieBindingDisabledBy
| where (HistoricalIPs !has ClientIp) and (HistoricalAgents !has UserAgent)
| extend
CloudAppId = int(32780),
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[1])
| project
LatestEvent,
UserId,
ClientIp,
UserAgent,
InstanceUrl,
HistoricalIPs,
HistoricalAgents,
CookieBindingDisabled,
CookieBindingDisabledBy,
AccountName,
UPNSuffix,
CloudAppId
Declared entities
Related content
Links established from declared identifiers and solution manifests.
Source provenance
GitHubDisplayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.
- Commit
9800e51↗- Source identifier
d7c9549c-7246-4555-8e53-d7b0db546764
GSTEP / CATALOG TRACKING
Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC