↳ 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

AccountIPCloudApplication

Related content

Links established from declared identifiers and solution manifests.

Source provenance

GitHub

Displayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.

Source identifier
d7c9549c-7246-4555-8e53-d7b0db546764
Additional source files 2Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection.yamlsource ↗Solutions/Microsoft Business Applications/Data/Solution_PowerPlatform.jsonsolution-membership ↗
GSTEP / CATALOG TRACKING

Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC

GSTEP sync dates, separate from the source content’s publication dates.