Audit Defender XDR Activities

While Microsoft is creating a unified portal for all security related activities we still lacked visibility into the audit activities in the security portal, this has now been changed! You can now audit Defender XDR activities and see who removed a device from isolation, deleted that custom detection rule, downloaded a Defender For Endpoint Offboarding Package and many more.

This blow will explain what should be configured to audit activities in Defender XDR. Furthermore, it will provide insight into how you can collect these activities from the Unified Audit Log. Lastly, multiple query and detection samples are shared to further safeguard your environment.

/images/Audit-XDR/Audit.jpg

Configuration

To allow auditing activities to flow into the Unified Audit Log and to the CloudAppEvents table you might need to change the configuration.

The first step is to enable Unified Audit Log integration in Defender For Endpoint (Microsoft Docs), this can be done by moving to the Settings -> Endpoints -> General -> Advanced Features and enabling Unified audit log as seen below. Once that is completed all changes from that point will be flowing to the UAL.

/images/Audit-XDR/DefenderSetting.png
Enable Unified audit log integration

The changes can be further integrated into Defender For Cloud Apps, which allows you to build detections and hunting queries based on the activities. The logs are collected via the Microsoft 365 connector in Defender For Cloud Apps, if you have an MCAS licence and you have not enabled the connector yet I highly recommend activating the connector (no additional cost involved). This connector can also collect Entra ID Management events and Exchange Online events.

The Microsoft 365 connector can be configured via: Settings -> Cloud Apps -> Connected Apps -> Enable Microsoft 365 -> App Connectors.

/images/Audit-XDR/CloudApps365.png
Connect Microsoft 365 Defender For Cloud Apps

Configure the Microsoft 365 connector to collect at least all Office 365 activities, if that setting is not enabled the Defender XDR changes will not be logged.

/images/Audit-XDR/SettingsOffice365.png
Microsoft 365 Connector Settings

If you have configured the Microsoft 365 connector but your CloudAppEvents table does not show any Defender XDR activities, you need to disable and enable the connector again to allow logs to flow to the CloudAppEvents table.

Unified Audit Log

To view the activities in the Unified Audit Logs you will need to have one of the following roles:

  • Global Administrator
  • Compliance Administrator
  • Organization Management

If you have one of these roles the Audit menu item is available from the settings blade. This opens a familiar Audit log search (also available in the Purview portal). In the workloads section, you can filter explicitly for Defender products. The Audit log activities page describes which actions are logged for each product.

/images/Audit-XDR/DefenderAudit.png
Defende XDR UAL Integration

Once the search has been completed the activities can be investigated.

/images/Audit-XDR/UALResults.png
Defende XDR UAL Results

CloudAppEvents

The power of these audit activities is in my opinion related to the Defender For Cloud Apps integration, this is because the logs flow to the CloudAppEvents. If data is available in one of the tables in Defender XDR, custom detection possibilities, creating graphs, visualizations and new enrichment potential becomes available. Besides that the permission model is different, you do not need highly permissive roles to access the data. Once you can query the CloudAppEvents table you have enough permissions.

The activities can be extracted by creating a KQL query that uses the CloudAppEvents table, then extracts the workload and lists the unique Defender Workloads (Products) from which audit activities have been logged.

/images/Audit-XDR/UniqueWorkloads.png
Query Defender XDR Audit Activities

Query:

CloudAppEvents
| extend WorkLoad = tostring(parse_json(RawEventData).Workload)
| where WorkLoad contains "Defender"
| distinct WorkLoad

Visualize Activities

As mentioned above one of the abilities we have gotten is that we can use the power of visualization to show Defener XDR activities. The column chart below shows which activities are executed and how often they occur in your environment.

/images/Audit-XDR/AuditActivities.png
Visualize Defender XDR Audit Activities

Query:

CloudAppEvents
| extend WorkLoad = tostring(parse_json(RawEventData).Workload)
| where WorkLoad contains "Defender"
| summarize Total = count() by ActionType
| render columnchart with (title="Defender XDR Activities") 

Detections

New data = new detection possibilities! What else would you expect on kqlquery.com? The section below describes several detections that leverage the Defender XDR audit events, these are:

Offboarding Package Downloaded

Disabling or Modifying Security Tools (T1562.001) is one of the techniques within the tactic Defense Evasion. With the Defender For Endpoint Offboarding Package and (local) Administrator permissions, you can offboard any device. This means that you have no EDR visibility anymore! The query below can be used to create a custom detection for this activity, this is highly recommended!!!

/images/Audit-XDR/OffboardMeme.jpg

Query:

CloudAppEvents
| where ActionType == "DownloadOffboardingPkg"
| extend UserId = tostring(parse_json(RawEventData).UserId), ClientIP = tostring(parse_json(RawEventData).ClientIP)
| project-rename InitiatedByAccountName = AccountDisplayName, InitiatedByAccounttId = AccountId
| project-reorder Timestamp, InitiatedByAccountName, UserId, ClientIP, ActionType

Live Response File Collection

The query below lists all the getfile activities that have been executed. This includes listing the SHA256 hash of the collected file (when available). The results can be further enriched with the [FileProfile()] function as well as with the DeviceFileEvents table.

Query:

CloudAppEvents
| where Timestamp > ago(30d)
| where ActionType == "LiveResponseGetFile"
| extend FileName = tostring(parse_json(RawEventData).FileName), FileSHA256 = tostring(parse_json(RawEventData).FileSHA256)
| project-rename InitiatedByAccountName = AccountDisplayName, InitiatedByAccounttId = AccountId, SHA256 = FileSHA256
| invoke FileProfile(SHA256, 1000)
| project-reorder Timestamp, FileName, SHA256, InitiatedByAccountName, InitiatedByAccounttId, GlobalPrevalence, SignatureState

Device Removed From Isolation

This query lists all the devices that are removed from isolation. It is good practice to review those once every x period. The query extracts multiple events from the removal action, such as which device is isolated, what isolation comment has been used and the type of isolation that has been executed. The removal action is enriched with the original isolation information to return an overview of why the device has been isolated, by who and why it is removed from isolation and who initiated the action. An example of the result is shared below.

/images/Audit-XDR/DeviceIsolation.png
Isolation Removal Results

Query:

CloudAppEvents
| where Timestamp > ago(30d)
| where ActionType == "ReleaseFromIsolation"
| extend ReleasedDevice = tostring(parse_json(RawEventData).DeviceName), ReleaseComment = tostring(parse_json(RawEventData).ActionComment)
| project-rename InitiatedByAccountName = AccountDisplayName, InitiatedByAccounttId = AccountId
// Lookup Isolation Reason
| lookup kind=leftouter (CloudAppEvents
 | where Timestamp > ago(30d)
 | where ActionType == "IsolateDevice"
 | extend IsolatedDevice = tostring(parse_json(RawEventData).DeviceName), IsolationComment = tostring(parse_json(RawEventData).ActionComment), IsolationScope = tostring(parse_json(RawEventData).ActionScope)
 | project-rename IsolationInitiatedByAccountName = AccountDisplayName, IsoaltionInitiatedByAccounttId = AccountId, IsolationTime = Timestamp
 | project IsolationTime, IsolatedDevice, IsolationComment, IsolationScope, IsolationInitiatedByAccountName, IsoaltionInitiatedByAccounttId) on $left.ReleasedDevice == $right.IsolatedDevice
|project-reorder Timestamp, ReleasedDevice, ReleaseComment, InitiatedByAccountName, InitiatedByAccounttId, IsolationTime, IsolationComment, IsolationScope, IsolationInitiatedByAccountName, IsoaltionInitiatedByAccounttId

Custom Detection Deletion

This query lists all the custom detections that have been deleted in Defender For XDR regardless of which table the query uses. The query lists the following details of the deleted custom detection:

  • RuleName
  • Query
  • AlertDescription
  • Initiator

Query:

CloudAppEvents
| where Timestamp > ago(30d)
| where ActionType == "DeleteCustomDetection"
| extend RuleName = tostring(parse_json(RawEventData).RuleName), Query = tostring(parse_json(RawEventData).Query), AlertDescription = parse_json(RawEventData).AlertDescription
| project-reorder AccountDisplayName, AccountId, RuleName, AlertDescription, Query

More KQL Queries related to this topic are available on GitHub.

Email Notifications

In case you do not want to create detections based on these activities, you can create Logic Apps (Playbooks) that automatically email you when such activities are found in your environment. The blog Sentinel Automation Part 1: Enriching Sentinel Incidents with KQL Results explains how you can query data from Sentinel (also works for Defender XDR only users via the Graph API). Instead of posting the data as a comment in a Sentinel, you can email the HTML table. The next part of the Sentinel Automation series will discuss this in more detail.

Questions? Feel free to reach out to me on any of my socials.