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

Dataverse - Terminated employee exfiltration over email

Back
Idde039242-47e0-43fa-84d7-b6be24305349
RulenameDataverse - Terminated employee exfiltration over email
DescriptionThis query identifies Dataverse exfiltration via email by terminated employees.
SeverityHigh
TacticsExfiltration
TechniquesT1639
T1567
Required data connectorsAzureActiveDirectoryIdentityProtection
IdentityInfo
MicrosoftThreatProtection
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 - Terminated employee exfiltration over email.yaml
Version3.2.0
Arm templatede039242-47e0-43fa-84d7-b6be24305349.json
Deploy To Azure
// Note this detection relies upon the user's UPN matching their email address.
// UEBA can provide more accurate data if enabled.
let query_frequency = 1h;
let allowed_destination_smtp_domains = dynamic([
// Specify a list of recipient domains to exclude from alerting.
// Example:
// "microsoft.com", "contoso.com"
    ]);
let exfiltration_alert_users = SecurityAlert
    | where Tactics has 'Exfiltration' and Entities has_all ('account', '32780')
    | mv-expand DataverseEntities = todynamic(Entities)
    | where DataverseEntities.AppId == 32780
    | extend InstanceUrl = tostring(DataverseEntities.InstanceName)
    | mv-expand AccountEntities = todynamic(Entities)
    | where AccountEntities.Type == 'account'
    | extend
        AccountName = tostring(AccountEntities.Name),
        UPNSuffix = tostring(AccountEntities.UPNSuffix)
    | summarize InstanceUrls = make_set(InstanceUrl, 100) by AccountName, UPNSuffix
    | extend UserId = tolower(strcat(AccountName, "@", UPNSuffix));
exfiltration_alert_users
| join kind=inner (
    MSBizAppsTerminatedEmployees
    | project UserId = tolower(UserPrincipalName), NotificationDate
    | where startofday(NotificationDate) <= startofday(now()))
    // Uncomment the below KQL if UEBA is available to gain more accurate
    // email address data:
    // | join kind=leftouter (_ASIM_IdentityInfo) on $left.UserId == $right.Username
    // | extend UserId = iif(UserId == UserMailAddress or isempty(UserMailAddress), UserId, UserMailAddress))
    on UserId
| join kind=inner (
    EmailEvents
    | where TimeGenerated >= ago (query_frequency)
    | where EmailDirection == "Outbound" and AttachmentCount > 0
    | extend RecipientDomain = tolower(split(RecipientEmailAddress, '@')[1])
    | where RecipientDomain !in (allowed_destination_smtp_domains)
    | summarize
        RecipientAddresses = make_set(RecipientEmailAddress, 1000),
        Subject = make_set(Subject, 1000)
        by SenderAddress = tolower(SenderMailFromAddress), SenderIPv4)
    on $left.UserId == $right.SenderAddress
| mv-expand InstanceUrl = InstanceUrls to typeof(string)
| extend
    CloudAppId = int(32780),
    AccountName = tostring(split(UserId, "@")[0]),
    UPNSuffix = tostring(split(UserId, "@")[1])
| project
    UserId,
    InstanceUrl,
    SenderIPv4,
    RecipientAddresses,
    Subject,
    AccountName,
    UPNSuffix,
    CloudAppId
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: UPNSuffix
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SenderIPv4
- entityType: CloudApplication
  fieldMappings:
  - identifier: AppId
    columnName: CloudAppId
  - identifier: InstanceName
    columnName: InstanceUrl
queryFrequency: 1h
name: Dataverse - Terminated employee exfiltration over email
alertDetailsOverride:
  alertDisplayNameFormat: Email attachment sent externally by terminated user following Dataverse exfiltration alerts
  alertDescriptionFormat: 'Departing or terminated user {{UserId}} was found to send email to external domains not on the allowed list: {{RecipientAddresses}}'
kind: Scheduled
tactics:
- Exfiltration
triggerThreshold: 0
query: |
  // Note this detection relies upon the user's UPN matching their email address.
  // UEBA can provide more accurate data if enabled.
  let query_frequency = 1h;
  let allowed_destination_smtp_domains = dynamic([
  // Specify a list of recipient domains to exclude from alerting.
  // Example:
  // "microsoft.com", "contoso.com"
      ]);
  let exfiltration_alert_users = SecurityAlert
      | where Tactics has 'Exfiltration' and Entities has_all ('account', '32780')
      | mv-expand DataverseEntities = todynamic(Entities)
      | where DataverseEntities.AppId == 32780
      | extend InstanceUrl = tostring(DataverseEntities.InstanceName)
      | mv-expand AccountEntities = todynamic(Entities)
      | where AccountEntities.Type == 'account'
      | extend
          AccountName = tostring(AccountEntities.Name),
          UPNSuffix = tostring(AccountEntities.UPNSuffix)
      | summarize InstanceUrls = make_set(InstanceUrl, 100) by AccountName, UPNSuffix
      | extend UserId = tolower(strcat(AccountName, "@", UPNSuffix));
  exfiltration_alert_users
  | join kind=inner (
      MSBizAppsTerminatedEmployees
      | project UserId = tolower(UserPrincipalName), NotificationDate
      | where startofday(NotificationDate) <= startofday(now()))
      // Uncomment the below KQL if UEBA is available to gain more accurate
      // email address data:
      // | join kind=leftouter (_ASIM_IdentityInfo) on $left.UserId == $right.Username
      // | extend UserId = iif(UserId == UserMailAddress or isempty(UserMailAddress), UserId, UserMailAddress))
      on UserId
  | join kind=inner (
      EmailEvents
      | where TimeGenerated >= ago (query_frequency)
      | where EmailDirection == "Outbound" and AttachmentCount > 0
      | extend RecipientDomain = tolower(split(RecipientEmailAddress, '@')[1])
      | where RecipientDomain !in (allowed_destination_smtp_domains)
      | summarize
          RecipientAddresses = make_set(RecipientEmailAddress, 1000),
          Subject = make_set(Subject, 1000)
          by SenderAddress = tolower(SenderMailFromAddress), SenderIPv4)
      on $left.UserId == $right.SenderAddress
  | mv-expand InstanceUrl = InstanceUrls to typeof(string)
  | extend
      CloudAppId = int(32780),
      AccountName = tostring(split(UserId, "@")[0]),
      UPNSuffix = tostring(split(UserId, "@")[1])
  | project
      UserId,
      InstanceUrl,
      SenderIPv4,
      RecipientAddresses,
      Subject,
      AccountName,
      UPNSuffix,
      CloudAppId  
relevantTechniques:
- T1639
- T1567
triggerOperator: gt
queryPeriod: 14d
eventGroupingSettings:
  aggregationKind: AlertPerResult
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Terminated employee exfiltration over email.yaml
severity: High
status: Available
id: de039242-47e0-43fa-84d7-b6be24305349
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
  dataTypes:
  - EmailEvents
- connectorId: AzureActiveDirectoryIdentityProtection
  dataTypes:
  - SecurityAlert
- connectorId: IdentityInfo
  dataTypes:
  - IdentityInfo
version: 3.2.0
description: This query identifies Dataverse exfiltration via email by terminated employees.
{
  "$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/de039242-47e0-43fa-84d7-b6be24305349')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/de039242-47e0-43fa-84d7-b6be24305349')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "Departing or terminated user {{UserId}} was found to send email to external domains not on the allowed list: {{RecipientAddresses}}",
          "alertDisplayNameFormat": "Email attachment sent externally by terminated user following Dataverse exfiltration alerts"
        },
        "alertRuleTemplateName": "de039242-47e0-43fa-84d7-b6be24305349",
        "customDetails": null,
        "description": "This query identifies Dataverse exfiltration via email by terminated employees.",
        "displayName": "Dataverse - Terminated employee exfiltration over email",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SenderIPv4",
                "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 - Terminated employee exfiltration over email.yaml",
        "query": "// Note this detection relies upon the user's UPN matching their email address.\n// UEBA can provide more accurate data if enabled.\nlet query_frequency = 1h;\nlet allowed_destination_smtp_domains = dynamic([\n// Specify a list of recipient domains to exclude from alerting.\n// Example:\n// \"microsoft.com\", \"contoso.com\"\n    ]);\nlet exfiltration_alert_users = SecurityAlert\n    | where Tactics has 'Exfiltration' and Entities has_all ('account', '32780')\n    | mv-expand DataverseEntities = todynamic(Entities)\n    | where DataverseEntities.AppId == 32780\n    | extend InstanceUrl = tostring(DataverseEntities.InstanceName)\n    | mv-expand AccountEntities = todynamic(Entities)\n    | where AccountEntities.Type == 'account'\n    | extend\n        AccountName = tostring(AccountEntities.Name),\n        UPNSuffix = tostring(AccountEntities.UPNSuffix)\n    | summarize InstanceUrls = make_set(InstanceUrl, 100) by AccountName, UPNSuffix\n    | extend UserId = tolower(strcat(AccountName, \"@\", UPNSuffix));\nexfiltration_alert_users\n| join kind=inner (\n    MSBizAppsTerminatedEmployees\n    | project UserId = tolower(UserPrincipalName), NotificationDate\n    | where startofday(NotificationDate) <= startofday(now()))\n    // Uncomment the below KQL if UEBA is available to gain more accurate\n    // email address data:\n    // | join kind=leftouter (_ASIM_IdentityInfo) on $left.UserId == $right.Username\n    // | extend UserId = iif(UserId == UserMailAddress or isempty(UserMailAddress), UserId, UserMailAddress))\n    on UserId\n| join kind=inner (\n    EmailEvents\n    | where TimeGenerated >= ago (query_frequency)\n    | where EmailDirection == \"Outbound\" and AttachmentCount > 0\n    | extend RecipientDomain = tolower(split(RecipientEmailAddress, '@')[1])\n    | where RecipientDomain !in (allowed_destination_smtp_domains)\n    | summarize\n        RecipientAddresses = make_set(RecipientEmailAddress, 1000),\n        Subject = make_set(Subject, 1000)\n        by SenderAddress = tolower(SenderMailFromAddress), SenderIPv4)\n    on $left.UserId == $right.SenderAddress\n| mv-expand InstanceUrl = InstanceUrls to typeof(string)\n| extend\n    CloudAppId = int(32780),\n    AccountName = tostring(split(UserId, \"@\")[0]),\n    UPNSuffix = tostring(split(UserId, \"@\")[1])\n| project\n    UserId,\n    InstanceUrl,\n    SenderIPv4,\n    RecipientAddresses,\n    Subject,\n    AccountName,\n    UPNSuffix,\n    CloudAppId\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "High",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Exfiltration"
        ],
        "techniques": [
          "T1567"
        ],
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}