↳ GitHub sourceAnalytics ruleHigh

Dataverse - Terminated employee exfiltration over email

Description

This query identifies Dataverse exfiltration via email by terminated employees.
Rule type
Scheduled
Version
3.2.0
Declared status
Available
Query frequency
1h
Query period
14d
Trigger
gt 0

Declared MITRE coverage

Declared sources

Metadata from the source file. No dependencies inferred from KQL.

Connectors

Data types

KQL query

Original query, unchanged.

// 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

Declared entities

AccountIPCloudApplication

Related content

Links established from declared identifiers and solution manifests.

Source provenance

GitHub

Displayed values come from files in Azure/Azure-Sentinel. They describe the published template, not your workspace configuration.

Source identifier
de039242-47e0-43fa-84d7-b6be24305349
Additional source files 2Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Terminated employee exfiltration over email.yamlsource ↗Solutions/Microsoft Business Applications/Data/Solution_PowerPlatform.jsonsolution-membership ↗
GSTEP / CATALOG TRACKING

Added to catalog : 16 Sept 2026 · 05:49 UTC
Last change observed : 16 Sept 2026 · 05:49 UTC

GSTEP sync dates, separate from the source content’s publication dates.