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

Dataverse - Login from IP not in the allow list

Back
Id81c693fe-f6c4-4352-bc10-3526f6e22637
RulenameDataverse - Login from IP not in the allow list
DescriptionIdentifies logons from IPv4 addresses not matching IPv4 subnets maintained on an allow list. This analytics rule uses the NetworkAddresses watchlist template.
SeverityHigh
TacticsInitialAccess
TechniquesT1078
T1190
T1133
Required data connectorsDataverse
KindScheduled
Query frequency1h
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Login from IP not in the allow list.yaml
Version3.2.0
Arm template81c693fe-f6c4-4352-bc10-3526f6e22637.json
Deploy To Azure
// Use static IP address or CIDR list specified in the
// NetworkAddresses watchlist template with tag "AllowDataverse"
let allowed_networks = MSBizAppsNetworkAddresses()
    | where Tags has "AllowDataverse"
    | summarize by IPSubnet;
let query_frequency = 1h;
let watchlist_entries_count = toscalar (allowed_networks
    | summarize count());
let dataverse_signin_activity = materialize(
    DataverseActivity
    | where watchlist_entries_count > 0
    | where TimeGenerated >= ago (query_frequency)
    | where Message == "UserSignIn" and isnotempty(ClientIp)
    | summarize FirstEvent = arg_min(TimeGenerated, *) by UserId, ClientIp, InstanceUrl
    );
let authorized_ip_addresses = dataverse_signin_activity
    | evaluate ipv4_lookup(allowed_networks, ClientIp, IPSubnet);
dataverse_signin_activity
| join kind=leftanti(authorized_ip_addresses) on ClientIp
| extend
    CloudAppId = int(32780),
    AccountName = tostring(split(UserId, '@')[0]),
    UPNSuffix = tostring(split(UserId, '@')[1])
| project
    FirstEvent,
    UserId,
    ClientIp,
    InstanceUrl,
    CloudAppId,
    AccountName,
    UPNSuffix
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
queryFrequency: 1h
name: Dataverse - Login from IP not in the allow list
alertDetailsOverride:
  alertDisplayNameFormat: 'Dataverse - Login from IP not on the allow list in {{InstanceUrl}} '
  alertDescriptionFormat: Sign-in activity detected in {{InstanceUrl}} from an IP {{ClientIp}} not on the allow list.
kind: Scheduled
tactics:
- InitialAccess
triggerThreshold: 0
query: |
  // Use static IP address or CIDR list specified in the
  // NetworkAddresses watchlist template with tag "AllowDataverse"
  let allowed_networks = MSBizAppsNetworkAddresses()
      | where Tags has "AllowDataverse"
      | summarize by IPSubnet;
  let query_frequency = 1h;
  let watchlist_entries_count = toscalar (allowed_networks
      | summarize count());
  let dataverse_signin_activity = materialize(
      DataverseActivity
      | where watchlist_entries_count > 0
      | where TimeGenerated >= ago (query_frequency)
      | where Message == "UserSignIn" and isnotempty(ClientIp)
      | summarize FirstEvent = arg_min(TimeGenerated, *) by UserId, ClientIp, InstanceUrl
      );
  let authorized_ip_addresses = dataverse_signin_activity
      | evaluate ipv4_lookup(allowed_networks, ClientIp, IPSubnet);
  dataverse_signin_activity
  | join kind=leftanti(authorized_ip_addresses) on ClientIp
  | extend
      CloudAppId = int(32780),
      AccountName = tostring(split(UserId, '@')[0]),
      UPNSuffix = tostring(split(UserId, '@')[1])
  | project
      FirstEvent,
      UserId,
      ClientIp,
      InstanceUrl,
      CloudAppId,
      AccountName,
      UPNSuffix  
relevantTechniques:
- T1078
- T1190
- T1133
triggerOperator: gt
queryPeriod: 1d
eventGroupingSettings:
  aggregationKind: AlertPerResult
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Login from IP not in the allow list.yaml
severity: High
status: Available
id: 81c693fe-f6c4-4352-bc10-3526f6e22637
requiredDataConnectors:
- connectorId: Dataverse
  dataTypes:
  - DataverseActivity
version: 3.2.0
description: Identifies logons from IPv4 addresses not matching IPv4 subnets maintained on an allow list. This analytics rule uses the NetworkAddresses watchlist template.
{
  "$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/81c693fe-f6c4-4352-bc10-3526f6e22637')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/81c693fe-f6c4-4352-bc10-3526f6e22637')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "Sign-in activity detected in {{InstanceUrl}} from an IP {{ClientIp}} not on the allow list.",
          "alertDisplayNameFormat": "Dataverse - Login from IP not on the allow list in {{InstanceUrl}} "
        },
        "alertRuleTemplateName": "81c693fe-f6c4-4352-bc10-3526f6e22637",
        "customDetails": null,
        "description": "Identifies logons from IPv4 addresses not matching IPv4 subnets maintained on an allow list. This analytics rule uses the NetworkAddresses watchlist template.",
        "displayName": "Dataverse - Login from IP not in the allow list",
        "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 - Login from IP not in the allow list.yaml",
        "query": "// Use static IP address or CIDR list specified in the\n// NetworkAddresses watchlist template with tag \"AllowDataverse\"\nlet allowed_networks = MSBizAppsNetworkAddresses()\n    | where Tags has \"AllowDataverse\"\n    | summarize by IPSubnet;\nlet query_frequency = 1h;\nlet watchlist_entries_count = toscalar (allowed_networks\n    | summarize count());\nlet dataverse_signin_activity = materialize(\n    DataverseActivity\n    | where watchlist_entries_count > 0\n    | where TimeGenerated >= ago (query_frequency)\n    | where Message == \"UserSignIn\" and isnotempty(ClientIp)\n    | summarize FirstEvent = arg_min(TimeGenerated, *) by UserId, ClientIp, InstanceUrl\n    );\nlet authorized_ip_addresses = dataverse_signin_activity\n    | evaluate ipv4_lookup(allowed_networks, ClientIp, IPSubnet);\ndataverse_signin_activity\n| join kind=leftanti(authorized_ip_addresses) on ClientIp\n| extend\n    CloudAppId = int(32780),\n    AccountName = tostring(split(UserId, '@')[0]),\n    UPNSuffix = tostring(split(UserId, '@')[1])\n| project\n    FirstEvent,\n    UserId,\n    ClientIp,\n    InstanceUrl,\n    CloudAppId,\n    AccountName,\n    UPNSuffix\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P1D",
        "severity": "High",
        "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"
    }
  ]
}