Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection

Back
Idd7c9549c-7246-4555-8e53-d7b0db546764
RulenameDataverse - Unusual sign-in following disabled IP address-based cookie binding protection
DescriptionIdentifies 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
SeverityMedium
TacticsDefenseEvasion
TechniquesT1629
Required data connectorsDataverse
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection.yaml
Version3.2.0
Arm templated7c9549c-7246-4555-8e53-d7b0db546764.json
Deploy To Azure
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
relevantTechniques:
- T1629
entityMappings:
- fieldMappings:
  - columnName: AccountName
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
  entityType: Account
- fieldMappings:
  - columnName: ClientIp
    identifier: Address
  entityType: IP
- fieldMappings:
  - columnName: CloudAppId
    identifier: AppId
  - columnName: InstanceUrl
    identifier: InstanceName
  entityType: CloudApplication
version: 3.2.0
triggerThreshold: 0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection.yaml
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
customDetails: {}
requiredDataConnectors:
- connectorId: Dataverse
  dataTypes:
  - DataverseActivity
triggerOperator: gt
alertDetailsOverride:
  alertDisplayNameFormat: Dataverse - Unusual sign-in after IP address-based cookie binding disabled
  alertDescriptionFormat: IP address-based cookie binding was disabled by in {{InstanceUrl}}. Following this, sign-in events from new IP {{ClientIp}}  for {{UserId}} were detected.
eventGroupingSettings:
  aggregationKind: AlertPerResult
id: d7c9549c-7246-4555-8e53-d7b0db546764
queryFrequency: 1h
query: |
  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  
severity: Medium
status: Available
queryPeriod: 14d
name: Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection
tactics:
- DefenseEvasion
kind: Scheduled