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

Dataverse - Guest user exfiltration following Power Platform defense impairment

Back
Id39efbf4b-b347-4cc7-895e-99a868bf29ea
RulenameDataverse - Guest user exfiltration following Power Platform defense impairment
DescriptionIdentifies a chain of events starting with disablement of Power Platform tenant isolation and removal of an environment’s access security group. These events are correlated with Dataverse exfiltration alerts associated with the impacted environment and recently created Microsoft Entra guest users.



Note: Activate other Dataverse analytics rules with the MITRE tactic ‘Exfiltration’ before enabling this rule.
SeverityHigh
TacticsDefenseEvasion
Exfiltration
TechniquesT1629
T1567
Required data connectorsAzureActiveDirectory
AzureActiveDirectoryIdentityProtection
PowerPlatformAdmin
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 - Guest user exfiltration following Power Platform defense impairment.yaml
Version3.2.0
Arm template39efbf4b-b347-4cc7-895e-99a868bf29ea.json
Deploy To Azure
let query_lookback = 14d;
let query_frequncy = 1h;
let defense_evasion_events = PowerPlatformAdminActivity
    | where TimeGenerated >= ago(query_lookback)
    | where EventOriginalType == "TenantIsolationOperation"
    | mv-expand PropertyCollection
    | where PropertyCollection.Name == "powerplatform.analytics.resource.tenant.isolation_policy.enabled"
    | where PropertyCollection.Value == "False"
    | summarize
        TenantIsolationRemovalTimestamp = max(TimeGenerated)
        by SecurityDisablingUser = ActorName
    | join kind=inner (
        PowerPlatformAdminActivity
        | where TimeGenerated >= ago(query_lookback)
        | where EventOriginalType == "EnvironmentPropertyChange"
        | where PropertyCollection has "Property: SecurityGroupId, Old Value: , New Value: "
        | mv-expand PropertyCollection
        | extend
            GroupRemovalTimestamp = TimeGenerated,
            InstanceUrl = tostring(iif(PropertyCollection.Name == "powerplatform.analytics.resource.environment.url", PropertyCollection.Value, "")),
            EnvironmentId = tostring(iif(PropertyCollection.Name == "powerplatform.analytics.resource.environment.name", PropertyCollection.Value, ""))
        | summarize InstanceUrl = max(InstanceUrl), EnvironmentId = max(EnvironmentId) by GroupRemovalTimestamp, SecurityDisablingUser = ActorName)
        on SecurityDisablingUser
    | summarize
        GroupRemovalTimestamp = max(GroupRemovalTimestamp),
        TenantIsolationRemovalTimestamp = max(TenantIsolationRemovalTimestamp)
        by SecurityDisablingUser, InstanceUrl, EnvironmentId;
let exfiltration_alerts = SecurityAlert
    | where TimeGenerated >= ago(query_frequncy)
    | where Tactics has "Exfiltration"
    | where Entities has ('"AppId":32780')
    | mv-expand todynamic(Entities)
    | extend AlertUPN = iif(Entities.Type == "account", strcat(Entities.Name, "@", Entities.UPNSuffix), "")
    | extend InstanceUrl = tostring(iif(Entities.AppId == 32780, Entities.InstanceName, ""))
    | join kind=inner defense_evasion_events on InstanceUrl
    | where StartTime > TenantIsolationRemovalTimestamp and StartTime > GroupRemovalTimestamp
    | summarize InstanceUrl = max(InstanceUrl), AlertUPN = max(AlertUPN) by AlertName, SystemAlertId
    | extend AlertDetails = bag_pack("AlertName", AlertName, "SystemAlertId", SystemAlertId)
    | summarize AlertDetails = make_set(AlertDetails, 100) by AlertUPN, InstanceUrl
    | join kind=inner (
        AuditLogs
        | where OperationName == "Update user"
        | where Identity == "Microsoft Invitation Acceptance Portal"
        | mv-expand TargetResources
        | extend ModifiedProperties = TargetResources.modifiedProperties
        | mv-expand ModifiedProperties
        | where ModifiedProperties.displayName == "AcceptedAs"
        | summarize RedeemTime = max(TimeGenerated) by GuestUser = tostring(parse_json(replace_regex(tostring(ModifiedProperties.newValue), "\\r", ""))[0]))
        on $left.AlertUPN == $right.GuestUser;
defense_evasion_events
| join kind=inner exfiltration_alerts on InstanceUrl
| extend
    AccountName = tostring(split(SecurityDisablingUser, "@")[0]),
    UPNSuffix = tostring(split(SecurityDisablingUser, "@")[1]),
    GuestAccountName = tostring(split(GuestUser, "@")[0]),
    GuestUPNSuffix = tostring(split(GuestUser, "@")[0]),
    DataverseId = 32780
| project
    SecurityDisablingUser,
    GuestUser,
    AlertDetails,
    TenantIsolationRemovalTimestamp,
    GroupRemovalTimestamp,
    InstanceUrl,
    EnvironmentId,
    AccountName,
    UPNSuffix,
    GuestAccountName,
    GuestUPNSuffix,
    DataverseId
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: UPNSuffix
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: GuestAccountName
  - identifier: UPNSuffix
    columnName: GuestUPNSuffix
- entityType: CloudApplication
  fieldMappings:
  - identifier: AppId
    columnName: DataverseId
  - identifier: InstanceName
    columnName: InstanceUrl
queryFrequency: 1h
name: Dataverse - Guest user exfiltration following Power Platform defense impairment
alertDetailsOverride:
  alertDisplayNameFormat: 'Dataverse - exfiltration alerts following defense impairment in {{InstanceUrl}} '
  alertDescriptionFormat: '{{SecurityDisablingUser}} disabled Power Platform tenant isolation and removed the security group used to control access to {{{InstanceUrl}}. Exfiltration alerts associated with guest users were then detected from user {{{GuestUser}}'
kind: Scheduled
tactics:
- DefenseEvasion
- Exfiltration
triggerThreshold: 0
query: |
  let query_lookback = 14d;
  let query_frequncy = 1h;
  let defense_evasion_events = PowerPlatformAdminActivity
      | where TimeGenerated >= ago(query_lookback)
      | where EventOriginalType == "TenantIsolationOperation"
      | mv-expand PropertyCollection
      | where PropertyCollection.Name == "powerplatform.analytics.resource.tenant.isolation_policy.enabled"
      | where PropertyCollection.Value == "False"
      | summarize
          TenantIsolationRemovalTimestamp = max(TimeGenerated)
          by SecurityDisablingUser = ActorName
      | join kind=inner (
          PowerPlatformAdminActivity
          | where TimeGenerated >= ago(query_lookback)
          | where EventOriginalType == "EnvironmentPropertyChange"
          | where PropertyCollection has "Property: SecurityGroupId, Old Value: , New Value: "
          | mv-expand PropertyCollection
          | extend
              GroupRemovalTimestamp = TimeGenerated,
              InstanceUrl = tostring(iif(PropertyCollection.Name == "powerplatform.analytics.resource.environment.url", PropertyCollection.Value, "")),
              EnvironmentId = tostring(iif(PropertyCollection.Name == "powerplatform.analytics.resource.environment.name", PropertyCollection.Value, ""))
          | summarize InstanceUrl = max(InstanceUrl), EnvironmentId = max(EnvironmentId) by GroupRemovalTimestamp, SecurityDisablingUser = ActorName)
          on SecurityDisablingUser
      | summarize
          GroupRemovalTimestamp = max(GroupRemovalTimestamp),
          TenantIsolationRemovalTimestamp = max(TenantIsolationRemovalTimestamp)
          by SecurityDisablingUser, InstanceUrl, EnvironmentId;
  let exfiltration_alerts = SecurityAlert
      | where TimeGenerated >= ago(query_frequncy)
      | where Tactics has "Exfiltration"
      | where Entities has ('"AppId":32780')
      | mv-expand todynamic(Entities)
      | extend AlertUPN = iif(Entities.Type == "account", strcat(Entities.Name, "@", Entities.UPNSuffix), "")
      | extend InstanceUrl = tostring(iif(Entities.AppId == 32780, Entities.InstanceName, ""))
      | join kind=inner defense_evasion_events on InstanceUrl
      | where StartTime > TenantIsolationRemovalTimestamp and StartTime > GroupRemovalTimestamp
      | summarize InstanceUrl = max(InstanceUrl), AlertUPN = max(AlertUPN) by AlertName, SystemAlertId
      | extend AlertDetails = bag_pack("AlertName", AlertName, "SystemAlertId", SystemAlertId)
      | summarize AlertDetails = make_set(AlertDetails, 100) by AlertUPN, InstanceUrl
      | join kind=inner (
          AuditLogs
          | where OperationName == "Update user"
          | where Identity == "Microsoft Invitation Acceptance Portal"
          | mv-expand TargetResources
          | extend ModifiedProperties = TargetResources.modifiedProperties
          | mv-expand ModifiedProperties
          | where ModifiedProperties.displayName == "AcceptedAs"
          | summarize RedeemTime = max(TimeGenerated) by GuestUser = tostring(parse_json(replace_regex(tostring(ModifiedProperties.newValue), "\\r", ""))[0]))
          on $left.AlertUPN == $right.GuestUser;
  defense_evasion_events
  | join kind=inner exfiltration_alerts on InstanceUrl
  | extend
      AccountName = tostring(split(SecurityDisablingUser, "@")[0]),
      UPNSuffix = tostring(split(SecurityDisablingUser, "@")[1]),
      GuestAccountName = tostring(split(GuestUser, "@")[0]),
      GuestUPNSuffix = tostring(split(GuestUser, "@")[0]),
      DataverseId = 32780
  | project
      SecurityDisablingUser,
      GuestUser,
      AlertDetails,
      TenantIsolationRemovalTimestamp,
      GroupRemovalTimestamp,
      InstanceUrl,
      EnvironmentId,
      AccountName,
      UPNSuffix,
      GuestAccountName,
      GuestUPNSuffix,
      DataverseId  
relevantTechniques:
- T1629
- T1567
triggerOperator: gt
customDetails:
  Environment: EnvironmentId
queryPeriod: 14d
eventGroupingSettings:
  aggregationKind: SingleAlert
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Guest user exfiltration following Power Platform defense impairment.yaml
severity: High
status: Available
id: 39efbf4b-b347-4cc7-895e-99a868bf29ea
requiredDataConnectors:
- connectorId: PowerPlatformAdmin
  dataTypes:
  - PowerPlatformAdminActivity
- connectorId: AzureActiveDirectory
  dataTypes:
  - AuditLogs
- connectorId: AzureActiveDirectoryIdentityProtection
  dataTypes:
  - SecurityAlert
version: 3.2.0
description: |
  Identifies a chain of events starting with disablement of Power Platform tenant isolation and removal of an environment's access security group. These events are correlated with Dataverse exfiltration alerts associated with the impacted environment and recently created Microsoft Entra guest users.

  Note: Activate other Dataverse analytics rules with the MITRE tactic 'Exfiltration' before enabling this rule.  
{
  "$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/39efbf4b-b347-4cc7-895e-99a868bf29ea')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/39efbf4b-b347-4cc7-895e-99a868bf29ea')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "{{SecurityDisablingUser}} disabled Power Platform tenant isolation and removed the security group used to control access to {{{InstanceUrl}}. Exfiltration alerts associated with guest users were then detected from user {{{GuestUser}}",
          "alertDisplayNameFormat": "Dataverse - exfiltration alerts following defense impairment in {{InstanceUrl}} "
        },
        "alertRuleTemplateName": "39efbf4b-b347-4cc7-895e-99a868bf29ea",
        "customDetails": {
          "Environment": "EnvironmentId"
        },
        "description": "Identifies a chain of events starting with disablement of Power Platform tenant isolation and removal of an environment's access security group. These events are correlated with Dataverse exfiltration alerts associated with the impacted environment and recently created Microsoft Entra guest users.\n\nNote: Activate other Dataverse analytics rules with the MITRE tactic 'Exfiltration' before enabling this rule.\n",
        "displayName": "Dataverse - Guest user exfiltration following Power Platform defense impairment",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "GuestAccountName",
                "identifier": "Name"
              },
              {
                "columnName": "GuestUPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "CloudApplication",
            "fieldMappings": [
              {
                "columnName": "DataverseId",
                "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 - Guest user exfiltration following Power Platform defense impairment.yaml",
        "query": "let query_lookback = 14d;\nlet query_frequncy = 1h;\nlet defense_evasion_events = PowerPlatformAdminActivity\n    | where TimeGenerated >= ago(query_lookback)\n    | where EventOriginalType == \"TenantIsolationOperation\"\n    | mv-expand PropertyCollection\n    | where PropertyCollection.Name == \"powerplatform.analytics.resource.tenant.isolation_policy.enabled\"\n    | where PropertyCollection.Value == \"False\"\n    | summarize\n        TenantIsolationRemovalTimestamp = max(TimeGenerated)\n        by SecurityDisablingUser = ActorName\n    | join kind=inner (\n        PowerPlatformAdminActivity\n        | where TimeGenerated >= ago(query_lookback)\n        | where EventOriginalType == \"EnvironmentPropertyChange\"\n        | where PropertyCollection has \"Property: SecurityGroupId, Old Value: , New Value: \"\n        | mv-expand PropertyCollection\n        | extend\n            GroupRemovalTimestamp = TimeGenerated,\n            InstanceUrl = tostring(iif(PropertyCollection.Name == \"powerplatform.analytics.resource.environment.url\", PropertyCollection.Value, \"\")),\n            EnvironmentId = tostring(iif(PropertyCollection.Name == \"powerplatform.analytics.resource.environment.name\", PropertyCollection.Value, \"\"))\n        | summarize InstanceUrl = max(InstanceUrl), EnvironmentId = max(EnvironmentId) by GroupRemovalTimestamp, SecurityDisablingUser = ActorName)\n        on SecurityDisablingUser\n    | summarize\n        GroupRemovalTimestamp = max(GroupRemovalTimestamp),\n        TenantIsolationRemovalTimestamp = max(TenantIsolationRemovalTimestamp)\n        by SecurityDisablingUser, InstanceUrl, EnvironmentId;\nlet exfiltration_alerts = SecurityAlert\n    | where TimeGenerated >= ago(query_frequncy)\n    | where Tactics has \"Exfiltration\"\n    | where Entities has ('\"AppId\":32780')\n    | mv-expand todynamic(Entities)\n    | extend AlertUPN = iif(Entities.Type == \"account\", strcat(Entities.Name, \"@\", Entities.UPNSuffix), \"\")\n    | extend InstanceUrl = tostring(iif(Entities.AppId == 32780, Entities.InstanceName, \"\"))\n    | join kind=inner defense_evasion_events on InstanceUrl\n    | where StartTime > TenantIsolationRemovalTimestamp and StartTime > GroupRemovalTimestamp\n    | summarize InstanceUrl = max(InstanceUrl), AlertUPN = max(AlertUPN) by AlertName, SystemAlertId\n    | extend AlertDetails = bag_pack(\"AlertName\", AlertName, \"SystemAlertId\", SystemAlertId)\n    | summarize AlertDetails = make_set(AlertDetails, 100) by AlertUPN, InstanceUrl\n    | join kind=inner (\n        AuditLogs\n        | where OperationName == \"Update user\"\n        | where Identity == \"Microsoft Invitation Acceptance Portal\"\n        | mv-expand TargetResources\n        | extend ModifiedProperties = TargetResources.modifiedProperties\n        | mv-expand ModifiedProperties\n        | where ModifiedProperties.displayName == \"AcceptedAs\"\n        | summarize RedeemTime = max(TimeGenerated) by GuestUser = tostring(parse_json(replace_regex(tostring(ModifiedProperties.newValue), \"\\\\r\", \"\"))[0]))\n        on $left.AlertUPN == $right.GuestUser;\ndefense_evasion_events\n| join kind=inner exfiltration_alerts on InstanceUrl\n| extend\n    AccountName = tostring(split(SecurityDisablingUser, \"@\")[0]),\n    UPNSuffix = tostring(split(SecurityDisablingUser, \"@\")[1]),\n    GuestAccountName = tostring(split(GuestUser, \"@\")[0]),\n    GuestUPNSuffix = tostring(split(GuestUser, \"@\")[0]),\n    DataverseId = 32780\n| project\n    SecurityDisablingUser,\n    GuestUser,\n    AlertDetails,\n    TenantIsolationRemovalTimestamp,\n    GroupRemovalTimestamp,\n    InstanceUrl,\n    EnvironmentId,\n    AccountName,\n    UPNSuffix,\n    GuestAccountName,\n    GuestUPNSuffix,\n    DataverseId\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "High",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "DefenseEvasion",
          "Exfiltration"
        ],
        "techniques": [
          "T1567"
        ],
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}