Query Details
// Rule : M365 - Risky AAD Sign-In Correlated with M365 File Download Spike
// Severity: High
// Tactics : InitialAccess, Collection, Exfiltration
// MITRE : T1078.004 (Valid Accounts: Cloud Accounts),
// T1530 (Data from Cloud Storage)
// Freq : PT1H Period: PT1H
// Description: Correlates Microsoft Entra ID (AAD) risky sign-in events with a
// simultaneous M365 SharePoint/OneDrive file download spike for the same
// user. A risky sign-in alone may be a false positive; a download spike
// immediately following confirms active abuse. The combined signal
// significantly elevates confidence and severity of the finding.
//
// Tables : SigninLogs, AADUserRiskEvents, OfficeActivity
//==========================================================================================
let LookbackPeriod = 1h;
let DownloadThreshold = 20; // files downloaded in the same hour as risky sign-in
// Step 1: Users with risky sign-ins in the current window
let RiskySignIns = SigninLogs
| where TimeGenerated > ago(LookbackPeriod)
| where RiskLevelDuringSignIn in ("high", "medium")
or RiskState in ("atRisk", "confirmedCompromised")
| extend UserPrincipalNameLower = tolower(UserPrincipalName)
| summarize
RiskLevel = max(RiskLevelDuringSignIn),
RiskState = any(RiskState),
RiskReasons = make_set(RiskDetail, 5),
RiskIPs = make_set(IPAddress, 5),
SignInApps = make_set(AppDisplayName, 5),
RiskFirstSeen = min(TimeGenerated),
RiskLastSeen = max(TimeGenerated)
by UserPrincipalNameLower;
// Step 2: Users with download spikes in the same window
let DownloadSpike = OfficeActivity
| where TimeGenerated > ago(LookbackPeriod)
| where RecordType in ("SharePoint", "OneDrive")
| where Operation in (
"FileDownloaded", "FileSyncDownloadedFull",
"FileSyncDownloadedPartial", "MailItemsAccessed")
| extend UserIdLower = tolower(UserId)
| summarize
DownloadCount = count(),
FileList = make_set(SourceFileName, 15),
SiteURLs = make_set(SiteUrl, 5),
DownloadIPs = make_set(ClientIP, 5)
by UserIdLower
| where DownloadCount >= DownloadThreshold;
// Step 3: Correlate — same user appears in BOTH datasets
RiskySignIns
| join kind=inner DownloadSpike
on $left.UserPrincipalNameLower == $right.UserIdLower
| extend
// Did the risky sign-in IP also appear in the download session?
SameIPForSignInAndDownload = set_intersect(RiskIPs, DownloadIPs)
| extend AlertSeverity = case(
RiskState == "confirmedCompromised", "Critical",
array_length(SameIPForSignInAndDownload) > 0, "Critical",
RiskLevel == "high" and DownloadCount >= 100, "High",
RiskLevel == "high", "High",
"Medium")
| project
TimeGenerated = RiskLastSeen,
UserId = UserPrincipalNameLower,
RiskLevel,
RiskState,
RiskReasons,
RiskIPs,
DownloadCount,
FileList,
SiteURLs,
DownloadIPs,
SameIPForSignInAndDownload,
AlertSeverity
This query is designed to detect potential security threats by correlating risky sign-in events with unusual file download activity in Microsoft 365 environments. Here's a simplified breakdown of what the query does:
Lookback Period: The query examines data from the past hour.
Risky Sign-Ins: It identifies users who have had risky sign-in attempts within the last hour. These sign-ins are considered risky if they have a high or medium risk level, or if the account is marked as "at risk" or "confirmed compromised." The query collects details like risk level, risk reasons, IP addresses used, and the applications accessed during these sign-ins.
Download Spikes: It looks for users who have downloaded a large number of files (at least 20) from SharePoint or OneDrive within the same hour. It gathers information about the files downloaded, the sites accessed, and the IP addresses used during these downloads.
Correlation: The query then finds users who appear in both the risky sign-in list and the download spike list. This correlation suggests that a risky sign-in was followed by a significant file download activity, which could indicate malicious behavior.
Alert Severity: The query assigns a severity level to each correlated event based on certain conditions:
Output: Finally, it outputs relevant details such as the time of the last risky sign-in, user ID, risk level, reasons for risk, IP addresses, download count, list of files downloaded, site URLs, and the severity of the alert.
In summary, this query helps identify potential security incidents by linking risky sign-ins with unusual file download activities, thereby increasing the confidence in detecting active abuse.

David Alonso
Released: March 18, 2026
Tables
Keywords
Operators