Query Details
// Rule : M365 - Office Activity from ThreatIntelligence-Known Malicious IP
// Severity: High
// Tactics : InitialAccess, Collection, Exfiltration
// MITRE : T1078.004 (Valid Accounts: Cloud Accounts),
// T1530 (Data from Cloud Storage)
// Freq : PT1H Period: PT1H
// Description: Enriches all M365 OfficeActivity events with the Microsoft Sentinel
// ThreatIntelIndicators table (unified TI, STIX 2.1 - replaces deprecated
// ThreatIntelligenceIndicator). Flags any mailbox access, file download,
// SharePoint operation, or Teams activity performed from an IP address
// that matches an active threat intelligence indicator (malware C2,
// APT infrastructure, known-malicious hosting). This is the "known actor
// logging in" detection pattern.
//
// Tables : OfficeActivity, ThreatIntelIndicators
//==========================================================================================
let LookbackPeriod = 1h;
// Active TI indicators - IPv4 only, not expired (STIX 2.1 pattern extraction)
let MaliciousIPs = ThreatIntelIndicators
| where TimeGenerated > ago(14d)
| where IsActive == true
| where isempty(ValidUntil) or ValidUntil > now()
| where Pattern has "ipv4-addr:value"
| extend TIIp = extract(@"ipv4-addr:value\s*=\s*'([^']+)'", 1, tostring(Pattern))
| where isnotempty(TIIp)
| summarize
ThreatType = make_set(Tags, 5),
ThreatSeverity = max(Confidence),
TIDescription = any(tostring(Data.description)),
TITags = make_set(Tags, 5),
IndicatorCount = count()
by TIIp;
// Join all M365 activity against malicious IPs
OfficeActivity
| where TimeGenerated > ago(LookbackPeriod)
| where isnotempty(ClientIP)
| join kind=inner MaliciousIPs on $left.ClientIP == $right.TIIp
| extend
RiskyOperation = Operation in (
"FileDownloaded", "FileSyncDownloadedFull",
"MailItemsAccessed", "New-InboxRule",
"SharingInvitationCreated", "AnonymousLinkCreated",
"AnonymousLinkUsed", "MessageCreated", "MemberAdded",
"Add-MailboxPermission", "New-MailboxExportRequest")
| summarize
HitCount = count(),
Operations = make_set(Operation, 15),
Workloads = make_set(OfficeWorkload, 5),
RiskyOps = countif(RiskyOperation),
ThreatType = any(ThreatType),
ThreatSeverity = any(ThreatSeverity),
TIDescription = any(TIDescription),
FilesOrItems = make_set(coalesce(SourceFileName, ObjectId), 10),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by UserId, ClientIP
| extend AlertSeverity = case(
RiskyOps >= 5, "Critical",
RiskyOps >= 1, "High",
HitCount >= 10, "Medium",
"Low")
| project
TimeGenerated = LastSeen,
UserId,
MaliciousIP = ClientIP,
ThreatType,
ThreatSeverity,
TIDescription,
HitCount,
RiskyOps,
Operations,
Workloads,
FilesOrItems,
FirstSeen,
AlertSeverity
This query is designed to detect potentially malicious activities in Microsoft 365 (M365) by identifying actions performed from known malicious IP addresses. Here's a simplified breakdown:
Purpose: The query aims to flag any M365 activities (like accessing mailboxes, downloading files, or performing SharePoint operations) that originate from IP addresses identified as malicious by threat intelligence data.
Data Sources: It uses two main data sources:
Process:
Alert Generation: Based on the number of risky operations and total hits, the query assigns an alert severity level (Critical, High, Medium, or Low).
Output: The final output includes details such as the user ID, malicious IP, threat type and severity, description, number of hits, risky operations, types of operations, workloads involved, files or items accessed, and the alert severity.
Overall, this query helps security teams quickly identify and assess potential security threats within their M365 environment by correlating user activities with known malicious IP addresses.

David Alonso
Released: May 14, 2026
Tables
Keywords
Operators