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
name: Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection
queryPeriod: 14d
triggerThreshold: 0
customDetails: {}
alertDetailsOverride:
  alertDescriptionFormat: IP address-based cookie binding was disabled by in {{InstanceUrl}}. Following this, sign-in events from new IP {{ClientIp}}  for {{UserId}} were detected.
  alertDisplayNameFormat: Dataverse - Unusual sign-in after IP address-based cookie binding disabled
id: d7c9549c-7246-4555-8e53-d7b0db546764
eventGroupingSettings:
  aggregationKind: AlertPerResult
severity: Medium
requiredDataConnectors:
- dataTypes:
  - DataverseActivity
  connectorId: Dataverse
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
version: 3.2.0
status: Available
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: AccountName
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
- entityType: IP
  fieldMappings:
  - columnName: ClientIp
    identifier: Address
- entityType: CloudApplication
  fieldMappings:
  - columnName: CloudAppId
    identifier: AppId
  - columnName: InstanceUrl
    identifier: InstanceName
tactics:
- DefenseEvasion
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  
kind: Scheduled
triggerOperator: gt
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
queryFrequency: 1h
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "workspace": {
      "type": "String"
    }
  },
  "resources": [
    {
      "apiVersion": "2024-01-01-preview",
      "id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/d7c9549c-7246-4555-8e53-d7b0db546764')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/d7c9549c-7246-4555-8e53-d7b0db546764')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "IP address-based cookie binding was disabled by in {{InstanceUrl}}. Following this, sign-in events from new IP {{ClientIp}}  for {{UserId}} were detected.",
          "alertDisplayNameFormat": "Dataverse - Unusual sign-in after IP address-based cookie binding disabled"
        },
        "alertRuleTemplateName": "d7c9549c-7246-4555-8e53-d7b0db546764",
        "customDetails": {},
        "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",
        "displayName": "Dataverse - Unusual sign-in following disabled IP address-based cookie binding protection",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIp",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "CloudApplication",
            "fieldMappings": [
              {
                "columnName": "CloudAppId",
                "identifier": "AppId"
              },
              {
                "columnName": "InstanceUrl",
                "identifier": "InstanceName"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "AlertPerResult"
        },
        "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",
        "query": "let query_frequency = 1h;\nlet query_lookback = 14d;\nlet cookie_lifetime = 24h;\nlet cookie_binding_disabled_events = DataverseActivity\n    | where TimeGenerated >= ago(query_lookback)\n    | where Message == \"Update\" and EntityName == \"organization\"\n    | mv-expand Fields\n    | where Fields.Name == \"enableipbasedcookiebinding\" and Fields.Value == 'False'\n    | summarize CookieBindingDisabled = min(TimeGenerated) by CookieBindingDisabledBy = UserId, InstanceUrl;\nlet current_activity = cookie_binding_disabled_events\n    | join kind=inner(DataverseActivity\n        | where UserId !endswith \"@onmicrosoft.com\" and UserId !endswith \"@microsoft.com\"\n        | where isnotempty(ClientIp) and isnotempty(UserAgent)\n        | where TimeGenerated >= ago(query_frequency + cookie_lifetime)\n        | summarize LatestEvent = arg_max(TimeGenerated, *) by UserId, ClientIp, InstanceUrl)\n        on InstanceUrl;\nlet users_switched_ip = current_activity\n    | summarize IPCount = count() by UserId, InstanceUrl\n    | where IPCount > 1\n    | join kind=inner (current_activity) on UserId, InstanceUrl\n    | summarize arg_max(LatestEvent, *) by UserId, InstanceUrl;\nusers_switched_ip\n| join kind = inner (DataverseActivity\n    | where TimeGenerated >= ago (query_lookback)\n    | where UserId !endswith \"@onmicrosoft.com\" and UserId !endswith \"@microsoft.com\"\n    | where isnotempty(ClientIp) and isnotempty(UserAgent)\n    | project-rename\n        HistoricalTime = TimeGenerated,\n        HistoricalIP = ClientIp,\n        HistoricalAgent = UserAgent)\n    on UserId, InstanceUrl\n| where HistoricalTime >= ago(query_lookback) and HistoricalTime < LatestEvent\n| summarize\n    HistoricalIPs = make_set(HistoricalIP, 100),\n    HistoricalAgents = make_set(HistoricalAgent, 100)\n    by\n    UserId,\n    UserAgent,\n    ClientIp,\n    InstanceUrl,\n    LatestEvent,\n    CookieBindingDisabled,\n    CookieBindingDisabledBy\n| where (HistoricalIPs !has ClientIp) and (HistoricalAgents !has UserAgent)\n| extend\n    CloudAppId = int(32780),\n    AccountName = tostring(split(UserId, '@')[0]),\n    UPNSuffix = tostring(split(UserId, '@')[1])\n| project\n    LatestEvent,\n    UserId,\n    ClientIp,\n    UserAgent,\n    InstanceUrl,\n    HistoricalIPs,\n    HistoricalAgents,\n    CookieBindingDisabled,\n    CookieBindingDisabledBy,\n    AccountName,\n    UPNSuffix,\n    CloudAppId\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion"
        ],
        "techniques": null,
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}