Incident Response Workflow: Data Exfiltration in Microsoft Defender XDR.
The investigation began with an unusually large OneDrive upload.
At first, it looked like routine file synchronisation. Then thousands of documents were accessed, several archive files appeared, and outbound traffic to cloud storage increased.
No malware alert had fired. No ransomware note appeared.
Agent Foskett was trying to answer one question: did sensitive company data leave the organisation?
Lesson overview
Learn how to investigate suspected data exfiltration by correlating Microsoft Defender XDR endpoint, identity, cloud, file and network telemetry to determine whether sensitive data was accessed, staged or transferred externally.
Why data exfiltration investigations matter
The data exfiltration response workflow
Step 1 — Review large file activity
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
let TimeFrame = 7d;
DeviceFileEvents
| where Timestamp > ago(TimeFrame)
| where ActionType in~ ("FileCreated", "FileModified", "FileRenamed", "FileCopied")
| summarize FileEventCount = count(),
FileNames = make_set(FileName, 50),
Folders = make_set(FolderPath, 30),
FirstSeen = min(Timestamp),
LastSeen = max(Timestamp)
by DeviceName,
InitiatingProcessAccountName
| where FileEventCount > 100
| order by FileEventCount descStep 2 — Identify archive creation
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
let TimeFrame = 7d;
DeviceFileEvents
| where Timestamp > ago(TimeFrame)
| where FileName endswith ".zip"
or FileName endswith ".7z"
or FileName endswith ".rar"
or FileName endswith ".tar"
| project Timestamp,
DeviceName,
InitiatingProcessAccountName,
FileName,
FolderPath,
InitiatingProcessFileName,
InitiatingProcessCommandLine
| order by Timestamp descStep 3 — Review cloud application activity
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
let TimeFrame = 7d;
CloudAppEvents
| where Timestamp > ago(TimeFrame)
| where ActionType has_any ("download", "upload", "share", "sync", "file")
| project Timestamp,
AccountDisplayName,
Application,
ActionType,
ObjectName,
IPAddress,
DeviceType,
UserAgent
| order by Timestamp descStep 4 — Hunt for external network destinations
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
let TimeFrame = 7d;
DeviceNetworkEvents
| where Timestamp > ago(TimeFrame)
| where isnotempty(RemoteUrl) or isnotempty(RemoteIP)
| where RemoteUrl has_any ("dropbox", "mega", "box.com", "drive.google", "wetransfer", "onedrive")
or RemotePort in (443, 8443)
| summarize ConnectionCount = count(),
Devices = make_set(DeviceName, 20),
Processes = make_set(InitiatingProcessFileName, 20),
FirstSeen = min(Timestamp),
LastSeen = max(Timestamp)
by RemoteUrl,
RemoteIP,
RemotePort
| order by ConnectionCount descStep 5 — Correlate identity and data access
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
let TimeFrame = 7d;
let SuspiciousUsers =
IdentityLogonEvents
| where Timestamp > ago(TimeFrame)
| where ActionType has_any ("risk", "suspicious", "unfamiliar", "success")
| summarize SignInCount = count(),
Locations = make_set(Location, 20),
IPAddresses = make_set(IPAddress, 50),
FirstSignIn = min(Timestamp),
LastSignIn = max(Timestamp)
by AccountUpn;
SuspiciousUsers
| join kind=leftouter (
CloudAppEvents
| where Timestamp > ago(TimeFrame)
| where ActionType has_any ("download", "upload", "share", "sync", "file")
| summarize CloudActions = count(),
Applications = make_set(Application, 20),
Objects = make_set(ObjectName, 50),
FirstCloudAction = min(Timestamp),
LastCloudAction = max(Timestamp)
by AccountDisplayName
) on $left.AccountUpn == $right.AccountDisplayName
| order by CloudActions descStep 6 — Build the exfiltration timeline
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
let TimeFrame = 3d;
let UserToInvestigate = "user@contoso.com";
let IdentityEvents =
IdentityLogonEvents
| where Timestamp > ago(TimeFrame)
| where AccountUpn =~ UserToInvestigate
| project Timestamp, Source = "IdentityLogonEvents", Entity = AccountUpn, Detail = strcat(ActionType, " from ", IPAddress, " ", tostring(Location));
let CloudEvents =
CloudAppEvents
| where Timestamp > ago(TimeFrame)
| where AccountDisplayName =~ UserToInvestigate
| project Timestamp, Source = "CloudAppEvents", Entity = AccountDisplayName, Detail = strcat(ActionType, " ", tostring(ObjectName));
union IdentityEvents, CloudEvents
| order by Timestamp ascCommon data exfiltration clues
False positives to consider
Investigation checklist
Related Agent Foskett Academy lessons
Coming next
Final thought
Incident Response Workflow Data Exfiltration in Microsoft Defender XDR
Agent Foskett Academy Lesson 117 teaches defenders how to investigate suspected data exfiltration using Microsoft Defender XDR endpoint, identity, cloud, file and network telemetry.
Learn data exfiltration investigation with KQL and Microsoft Defender XDR
Data exfiltration investigations help Microsoft security analysts identify sensitive data access, large file transfers, archive creation, cloud uploads, external sharing and suspicious user behaviour.
Microsoft Defender XDR data theft investigation tutorial
This lesson explains how to correlate DeviceFileEvents, DeviceNetworkEvents, CloudAppEvents and IdentityLogonEvents to determine whether sensitive data left the organisation.
