← ~/DETECTIONS

2024-07-15 // Dylan Evans

Rapid Bulk SharePoint File Downloads from Unregistered Devices

Microsoft Sentinel

Detects suspicious rapid bulk downloads of SharePoint files following sign-ins from unregistered devices.

sharepointfile-downloadunregistered-devicebulk-data-exfiltration

Rapid Bulk SharePoint Downloads After Sign-In

Overview

This detection identifies suspicious activity where users from unregistered devices perform rapid bulk downloads of SharePoint files shortly after successful sign-ins. The query correlates sign-in events with file download operations to flag potential data exfiltration attempts, particularly targeting corporate files (e.g., documents, spreadsheets) from non-trusted sources.

Query

let TimeRange = 90d;
let TimeWindow = 10s;
let MinDownloads = 3;
let MaxTimeWindow = 10m;

// Get suspicious sign-ins from unregistered devices
let SuspiciousSignIns = SigninLogs
| where TimeGenerated >= ago(TimeRange)
| where ResultType == "0"
| where isnotempty(UserPrincipalName) and isnotempty(IPAddress)
| where isempty(DeviceDetail.displayName)
| project SignInTime, UserId = UserPrincipalName, UserPrincipalName, IPAddress, RiskLevel = RiskLevelDuringSignIn, Location;

// Get file download operations with suspicious patterns
let SuspiciousFileDownloads = OfficeActivity
| where TimeGenerated >= ago(TimeRange)
| where RecordType == "SharePointFileOperation"
| where Operation == "FileDownloaded"
| where isnotempty(UserId) and isnotempty(SourceFileName)
| where not(SourceFileName matches regex @"(?i)\.(tmp|temp|cache|log|~)$")
| where not(SourceFileName startswith "~")
| project DownloadTime, UserId, FileName = SourceFileName, IPAddress1 = ClientIP, UserAgent;

// Time for correlation!
let CorrelatedEvents = SuspiciousSignIns
| join kind=inner (
    SuspiciousFileDownloads
    | where isnotempty(UserId)
) on UserId
| where DownloadTime between (SignInTime .. (SignInTime + TimeWindow))
| where IPAddress == IPAddress1
| project SignInTime, UserPrincipalName, IPAddress, RiskLevel, Location, DownloadTime, FileName, UserAgent;

// Identify bulk download patterns
CorrelatedEvents
| summarize FirstDownload = min(DownloadTime), LastDownload = max(DownloadTime), DownloadCount = count(), UniqueFiles = dcount(FileName), FileNames = make_list(FileName, 20), UserAgents = make_set(UserAgent) by SignInTime, UserPrincipalName, IPAddress, RiskLevel, tostring(Location)
| extend DownloadDuration = LastDownload - FirstDownload
// Filter for bulk download patterns
| where (DownloadCount >= MinDownloads and DownloadDuration <= MaxTimeWindow and UniqueFiles >= 2) or (DownloadCount >= 5 or (DownloadCount >= 3 and DownloadDuration <= 1m))
| project SignInTime, UserPrincipalName, IPAddress, Location, RiskLevel, DownloadCount, UniqueFiles, DownloadDuration, FirstDownload, LastDownload, SampleFiles = strcat_array(array_slice(FileNames, 0, 5), "; "), UserAgents
| order by DownloadCount desc, SignInTime desc

Logic Explanation

The query performs a two-phase correlation:

  1. Sign-in Filtering: Identifies sign-ins from unregistered devices (no DeviceDetail.displayName) with successful results (ResultType == 0).
  2. File Download Analysis: Captures SharePoint file downloads (RecordType = "SharePointFileOperation", Operation = "FileDownloaded") excluding system files (e.g., .tmp, logs) and non-corporate files.

The correlation step joins these events by:

  • User identity (UserId).
  • Time window (±10 seconds) between sign-in and first download.
  • Matching IP addresses for consistency.

Bulk Detection Logic:

  • Thresholds: Flags downloads with ≥3 files within ≤10 minutes (or ≥5 files regardless of time) or ≥3 files with ≤1 minute duration, plus ≥2 unique files.
  • Output: Prioritizes high-volume events by DownloadCount, showing sample filenames and user agents.

Tuning Notes

  • False positives from legitimate bulk operations (e.g., scheduled backups):
    • Adjust MinDownloads or MaxTimeWindow to exclude routine workflows.
  • IP-based correlation may miss lateral movement if IPs change during the event:
    • Consider adding SourceNetwork or DestinationNetwork joins for broader context.

References