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

Dataverse - New sign-in from an unauthorized domain

Back
Id4c1c9aee-8e44-4bb9-bd53-f3e7d6761282
RulenameDataverse - New sign-in from an unauthorized domain
DescriptionIdentifies Dataverse sign-in activity originating from users with UPN suffixes that have not been seen previously in the last 14 days and are not present on a predefined list of authorized domains. Common internal Power Platform system users are excluded by default.
SeverityMedium
TacticsInitialAccess
TechniquesT1078
T1190
T1133
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 - New sign-in from an unauthorized domain.yaml
Version3.2.0
Arm template4c1c9aee-8e44-4bb9-bd53-f3e7d6761282.json
Deploy To Azure
// Allow list of UPN suffixes allowed by the organization.
let allowed_domains = dynamic([
    'onmicrosoft.com',
    'microsoft.com'
    ]);
// All list of users allowed by the organization
let allowed_users = dynamic([
    'user1@mydomain.com',
    'user2@mydomain.com'
    ]);
let query_frequency = 1h;
let query_lookback = 14d;
let historical_users = DataverseActivity
    | where TimeGenerated between(ago(query_lookback) .. ago(query_frequency))
    | where Message == 'UserSignIn'
    | summarize by UserId;
DataverseActivity
| where TimeGenerated >= ago (query_frequency)
| where Message == 'UserSignIn'
| join kind=leftanti (historical_users) on UserId
| summarize FirstEvent = min(TimeGenerated), LastEvent = max(TimeGenerated) by UserId, ClientIp, InstanceUrl
| where isnotempty(ClientIp)
| extend CloudAppId = int(32780)
| extend AccountName = tostring(split(UserId, '@')[0])
| extend UPNSuffix = tostring(split(UserId, '@')[1])
| where UPNSuffix !in (allowed_domains) and UserId !in (allowed_users)
| project
    FirstEvent,
    LastEvent,
    UserId,
    ClientIp,
    InstanceUrl,
    AccountName,
    UPNSuffix,
    CloudAppId
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: UPNSuffix
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: ClientIp
- entityType: CloudApplication
  fieldMappings:
  - identifier: AppId
    columnName: CloudAppId
  - identifier: InstanceName
    columnName: InstanceUrl
kind: Scheduled
name: Dataverse - New sign-in from an unauthorized domain
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - New sign-in from an unauthorized domain.yaml
tactics:
- InitialAccess
triggerThreshold: 0
version: 3.2.0
requiredDataConnectors:
- connectorId: Dataverse
  dataTypes:
  - DataverseActivity
status: Available
description: Identifies Dataverse sign-in activity originating from users with UPN suffixes that have not been seen previously in the last 14 days and are not present on a predefined list of authorized domains. Common internal Power Platform system users are excluded by default.
queryPeriod: 14d
severity: Medium
queryFrequency: 1h
eventGroupingSettings:
  aggregationKind: SingleAlert
alertDetailsOverride:
  alertDisplayNameFormat: Dataverse - Unauthorized sign-in activity
  alertDescriptionFormat: New user sign-in activity was detected in {{InstanceUrl}} originating from user {{UserId}}. This user's UPN suffix is not on the authorized list of domains.
relevantTechniques:
- T1078
- T1190
- T1133
id: 4c1c9aee-8e44-4bb9-bd53-f3e7d6761282
triggerOperator: gt
query: |
  // Allow list of UPN suffixes allowed by the organization.
  let allowed_domains = dynamic([
      'onmicrosoft.com',
      'microsoft.com'
      ]);
  // All list of users allowed by the organization
  let allowed_users = dynamic([
      'user1@mydomain.com',
      'user2@mydomain.com'
      ]);
  let query_frequency = 1h;
  let query_lookback = 14d;
  let historical_users = DataverseActivity
      | where TimeGenerated between(ago(query_lookback) .. ago(query_frequency))
      | where Message == 'UserSignIn'
      | summarize by UserId;
  DataverseActivity
  | where TimeGenerated >= ago (query_frequency)
  | where Message == 'UserSignIn'
  | join kind=leftanti (historical_users) on UserId
  | summarize FirstEvent = min(TimeGenerated), LastEvent = max(TimeGenerated) by UserId, ClientIp, InstanceUrl
  | where isnotempty(ClientIp)
  | extend CloudAppId = int(32780)
  | extend AccountName = tostring(split(UserId, '@')[0])
  | extend UPNSuffix = tostring(split(UserId, '@')[1])
  | where UPNSuffix !in (allowed_domains) and UserId !in (allowed_users)
  | project
      FirstEvent,
      LastEvent,
      UserId,
      ClientIp,
      InstanceUrl,
      AccountName,
      UPNSuffix,
      CloudAppId  
{
  "$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/4c1c9aee-8e44-4bb9-bd53-f3e7d6761282')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/4c1c9aee-8e44-4bb9-bd53-f3e7d6761282')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "New user sign-in activity was detected in {{InstanceUrl}} originating from user {{UserId}}. This user's UPN suffix is not on the authorized list of domains.",
          "alertDisplayNameFormat": "Dataverse - Unauthorized sign-in activity"
        },
        "alertRuleTemplateName": "4c1c9aee-8e44-4bb9-bd53-f3e7d6761282",
        "customDetails": null,
        "description": "Identifies Dataverse sign-in activity originating from users with UPN suffixes that have not been seen previously in the last 14 days and are not present on a predefined list of authorized domains. Common internal Power Platform system users are excluded by default.",
        "displayName": "Dataverse - New sign-in from an unauthorized domain",
        "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": "SingleAlert"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - New sign-in from an unauthorized domain.yaml",
        "query": "// Allow list of UPN suffixes allowed by the organization.\nlet allowed_domains = dynamic([\n    'onmicrosoft.com',\n    'microsoft.com'\n    ]);\n// All list of users allowed by the organization\nlet allowed_users = dynamic([\n    'user1@mydomain.com',\n    'user2@mydomain.com'\n    ]);\nlet query_frequency = 1h;\nlet query_lookback = 14d;\nlet historical_users = DataverseActivity\n    | where TimeGenerated between(ago(query_lookback) .. ago(query_frequency))\n    | where Message == 'UserSignIn'\n    | summarize by UserId;\nDataverseActivity\n| where TimeGenerated >= ago (query_frequency)\n| where Message == 'UserSignIn'\n| join kind=leftanti (historical_users) on UserId\n| summarize FirstEvent = min(TimeGenerated), LastEvent = max(TimeGenerated) by UserId, ClientIp, InstanceUrl\n| where isnotempty(ClientIp)\n| extend CloudAppId = int(32780)\n| extend AccountName = tostring(split(UserId, '@')[0])\n| extend UPNSuffix = tostring(split(UserId, '@')[1])\n| where UPNSuffix !in (allowed_domains) and UserId !in (allowed_users)\n| project\n    FirstEvent,\n    LastEvent,\n    UserId,\n    ClientIp,\n    InstanceUrl,\n    AccountName,\n    UPNSuffix,\n    CloudAppId\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "InitialAccess"
        ],
        "techniques": [
          "T1078",
          "T1133",
          "T1190"
        ],
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}