Query Details

Purview DLP Exchange Alert Info

Query

let alert_id = "<<<>>>";
let query_period = 1d;
let internet_message_ids = toscalar(
    AlertEvidence
    | where Timestamp > ago(query_period)
    | where AlertId == strcat("dl", alert_id) and EntityType == "MailMessage"
    | extend AdditionalFields = todynamic(AdditionalFields)
    | summarize make_set(AdditionalFields["InternetMessageId"])
);
let network_message_ids = toscalar(
    AlertEvidence
    | where Timestamp > ago(query_period)
    | where AlertId == strcat("dl", alert_id) and EntityType == "MailMessage"
    | summarize make_set(NetworkMessageId)
);
CloudAppEvents
| where Timestamp > ago(query_period)
| where ActionType in ("AlertTriggered", "AlertUpdated") and tostring(RawEventData["AlertId"]) == alert_id
| summarize arg_max(Timestamp, *)
| extend
    AlertId = tostring(RawEventData["AlertId"]),
    Data = todynamic(tostring(RawEventData["Data"]))
| extend
    UserPrincipalName = tolower(tostring(Data["f3u"])),
    Severity = tostring(Data["sev"]),
    Workload = tostring(Data["wl"]),
    SensitiveInformationContentType = split(tostring(Data["sict"]), ";"),
    SensitiveInformationTypeMatchInfo = split(tostring(Data["sitmi"]), ";"),
    PolicyId = tostring(Data["dpid"]),
    PolicyName = tostring(Data["dpn"]),
    RuleId = tostring(Data["drid"]),
    RuleName = tostring(Data["drn"]),
    ProtectionActions = split(tostring(Data["dact"]), ", "),
    ObjectName = tostring(Data["von"]),
    SenderFromAddress = tostring(Data["mfrm"]),
    RecipientEmailAddress = split(tostring(Data["to"]), ","),
    CCEmailAddress = split(tostring(Data["cc"]), ","),
    BCCEmailAddress = split(tostring(Data["bcc"]), ",")
| where Workload == "Exchange" and tostring(RawEventData["Category"]) == "DataLossPrevention"
| project
    Timestamp,
    Application,
    ActionType,
    AlertId,
    UserPrincipalName,
    Severity,
    Workload,
    SensitiveInformationContentType,
    SensitiveInformationTypeMatchInfo,
    PolicyId,
    PolicyName,
    RuleId,
    RuleName,
    ProtectionActions,
    Subject = ObjectName,
    SenderFromAddress,
    RecipientEmailAddress,
    CCEmailAddress,
    BCCEmailAddress,
    AlertTriggered_RawEventData = RawEventData,
    AlertTriggered_ReportId = ReportId,
    // We will assume there is only 1 email associated to an alert
    InternetMessageId = tostring(internet_message_ids[0]),
    NetworkMessageId = tostring(network_message_ids[0])
| lookup kind=leftouter (
    EmailEvents
    | where Timestamp > ago(query_period)
    | where NetworkMessageId == tostring(network_message_ids[0])
    | summarize FinalRecipientEmailAddress = array_sort_asc(make_list(RecipientEmailAddress)) by NetworkMessageId, DeliveryAction
    | summarize FinalRecipientEmailAddress = make_bag(bag_pack(DeliveryAction, FinalRecipientEmailAddress)) by NetworkMessageId, DeliveryAction
    ) on NetworkMessageId
| lookup kind=leftouter (
    EmailUrlInfo
    | where Timestamp > ago(query_period)
    | where NetworkMessageId == tostring(network_message_ids[0])
    | summarize EmailUrlInfo = make_list(bag_pack("Url", Url, "UrlDomain", UrlDomain, "UrlLocation", UrlLocation)) by NetworkMessageId
    ) on NetworkMessageId
| lookup kind=leftouter (
    EmailAttachmentInfo
    | where Timestamp > ago(query_period)
    | where NetworkMessageId == tostring(network_message_ids[0])
    | distinct NetworkMessageId, FileName, FileType, SHA256, FileSize
    | summarize EmailAttachmentInfo = make_list(bag_pack("FileName", FileName, "FileType", FileType, "FileSize", FileSize, "SHA256", SHA256)) by NetworkMessageId
    ) on NetworkMessageId

Explanation

This KQL query is designed to gather and process information related to a specific alert in an email system, particularly focusing on data loss prevention (DLP) incidents in Exchange. Here's a simplified breakdown of what the query does:

  1. Define Variables:

    • alert_id: A placeholder for the specific alert ID you are interested in.
    • query_period: The time frame for the query, set to 1 day.
  2. Extract Internet and Network Message IDs:

    • It retrieves the InternetMessageId and NetworkMessageId associated with the specified alert from the AlertEvidence table, filtering by the alert ID and ensuring the data is recent (within the last day).
  3. Filter Cloud App Events:

    • It looks into the CloudAppEvents table for events related to the alert, specifically those that are either "AlertTriggered" or "AlertUpdated".
    • It extracts and processes various fields from the event data, such as user information, severity, policy details, and email addresses.
    • It focuses on events related to the "Exchange" workload and categorized under "DataLossPrevention".
  4. Project Relevant Data:

    • The query selects specific fields to output, including timestamps, user details, policy information, and email metadata.
    • It assumes there is only one email associated with the alert and uses the first InternetMessageId and NetworkMessageId found.
  5. Enrich Data with Email Details:

    • It performs left outer joins with three other tables (EmailEvents, EmailUrlInfo, and EmailAttachmentInfo) to enrich the alert data with additional email-related information:
      • EmailEvents: Provides the final recipient email addresses and delivery actions.
      • EmailUrlInfo: Adds information about URLs contained in the email, including domain and location.
      • EmailAttachmentInfo: Includes details about any attachments in the email, such as file name, type, size, and hash.

The overall goal of this query is to compile a comprehensive view of a specific alert related to email data loss prevention, combining alert metadata with detailed email content and context.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: May 7, 2025

Tables

AlertEvidence CloudAppEvents EmailEvents EmailUrlInfo EmailAttachmentInfo

Keywords

AlertEvidenceCloudAppEventsEmailEventsEmailUrlInfoEmailAttachmentInfoMailMessageRawEventDataDataLossPreventionExchangeUserPrincipalNameSeverityWorkloadSensitiveInformationContentTypeSensitiveInformationTypeMatchInfoPolicyIdPolicyNameRuleIdRuleNameProtectionActionsObjectNameSenderFromAddressRecipientEmailAddressCCEmailAddressBCCEmailAddressInternetMessageIdNetworkMessageIdFinalRecipientEmailAddressDeliveryActionUrlUrlDomainUrlLocationFileNameFileTypeSHA256FileSize

Operators

lettoscalarwhereagostrcatextendtodynamicsummarizemake_setintostringarg_maxsplitprojectlookupkind=leftouterarray_sort_ascmake_listmake_bagbag_packdistinct

Actions

GitHub