Query Details

RULE 22 M365 Compliance Content Search Non Admin

Query

// Rule    : M365 - eDiscovery / Compliance Content Search Initiated by Non-Compliance Admin
// Severity: High
// Tactics : Collection, Discovery
// MITRE   : T1213.003 (Data from Information Repositories),
//           T1119 (Automated Collection)
// Freq    : PT1H   Period: PT1H
// Description: Dedicated detection for compliance center activity — Content Search,
//              eDiscovery case creation and export, and audit log searches initiated
//              by users outside of known compliance roles. Attackers with compromised
//              admin accounts abuse these tools to perform targeted data collection
//              across the entire tenant before exfiltration.
//==========================================================================================

let LookbackPeriod = 1h;

// Known legitimate compliance/eDiscovery operations
// Flag either: export actions (always alert) OR non-export actions by non-standard users
OfficeActivity
| where TimeGenerated > ago(LookbackPeriod)
| where RecordType in (
    "SecurityComplianceCenter",
    "ComplianceManager",
    "OfficeSecurityComplianceCenter")
| where Operation in (
    "SearchCreated",
    "SearchStarted",
    "SearchExported",
    "SearchPreviewed",
    "SearchPurged",
    "CaseCreated",
    "CaseMemberAdded",
    "HoldCreated",
    "HoldUpdated",
    "New-ComplianceSearch",
    "Start-ComplianceSearch",
    "New-ComplianceSearchAction",
    "Get-ComplianceSearch",
    "New-eDiscoveryCase",
    "New-UnifiedAuditLogRetentionPolicy",
    "AuditLogSearchStarted",
    "AuditLogSearchExported",
    "ContentSearchExportDownloaded")
| extend Params = tostring(Parameters)
| extend
    SearchName     = tostring(extract(@"Name.*?:([^\s,]+)", 1, Params)),
    ContentSources = tostring(extract(@"(ContentMatchQuery|AllowNotFoundExchangeLocationsEnabled|ExchangeLocation).*?:([^\n]+)", 2, Params)),
    IsExport       = Operation in (
        "SearchExported", "New-ComplianceSearchAction",
        "ContentSearchExportDownloaded", "SearchPurged",
        "AuditLogSearchExported")
| summarize
    ActionCount    = count(),
    Operations     = make_set(Operation, 10),
    SearchNames    = make_set(SearchName, 5),
    ExportCount    = countif(IsExport),
    ClientIPs      = make_set(ClientIP, 5),
    FirstSeen      = min(TimeGenerated),
    LastSeen       = max(TimeGenerated)
    by UserId
| extend AlertSeverity = case(
    ExportCount >= 1,    "High",
    ActionCount >= 5,    "Medium",
    "Low")
| project
    TimeGenerated  = LastSeen,
    UserId,
    ActionCount,
    ExportCount,
    Operations,
    SearchNames,
    ClientIPs,
    AlertSeverity

Explanation

This KQL query is designed to detect potentially unauthorized activities related to eDiscovery and compliance content searches within Microsoft 365. Here's a simplified breakdown of what the query does:

  1. Purpose: The query aims to identify content searches and related activities initiated by users who are not part of known compliance roles. This is important because attackers with access to compromised admin accounts might exploit these tools to gather data across the organization before exfiltrating it.

  2. Time Frame: It looks at activities that occurred within the last hour (LookbackPeriod = 1h).

  3. Activity Filtering: It filters activities from specific record types related to compliance and security centers, focusing on operations such as creating, starting, exporting, and previewing searches, as well as creating cases and audit log searches.

  4. Data Extraction: The query extracts specific details from the activity parameters, such as the search name and content sources involved.

  5. Export Identification: It identifies whether the operation involved exporting data, which is considered more critical.

  6. Summarization: For each user, it summarizes the number of actions taken, the types of operations performed, the names of searches conducted, the number of export actions, and the IP addresses used.

  7. Severity Assessment: It assigns an alert severity level based on the number of export actions and total actions:

    • "High" if there is at least one export action.
    • "Medium" if there are five or more actions.
    • "Low" otherwise.
  8. Output: Finally, it projects the results, showing the time of the last activity, user ID, counts of actions and exports, types of operations, search names, client IPs, and the alert severity.

In essence, this query helps security teams monitor and respond to potentially suspicious compliance-related activities by non-compliance admins in a Microsoft 365 environment.

Details

David Alonso profile picture

David Alonso

Released: March 18, 2026

Tables

OfficeActivity

Keywords

OfficeActivityComplianceeDiscoverySecurityComplianceCenterComplianceManagerOfficeSecurityComplianceCenterOperationSearchCreatedSearchStartedSearchExportedSearchPreviewedSearchPurgedCaseCreatedCaseMemberAddedHoldCreatedHoldUpdatedNewComplianceSearchStartComplianceSearchNewComplianceSearchActionGetComplianceSearchNeweDiscoveryCaseNewUnifiedAuditLogRetentionPolicyAuditLogSearchStartedAuditLogSearchExportedContentSearchExportDownloadedParametersSearchNameContentSourcesIsExportActionCountOperationsSearchNamesExportCountClientIPsFirstSeenLastSeenUserIdAlertSeverity

Operators

letagoinextendtostringextractsummarizecountmake_setcountifminmaxbycaseproject

Actions