From 61c9344677d5db7ec121680bbc679d6614f9fcd7 Mon Sep 17 00:00:00 2001 From: Terrance DeJesus <99630311+terrancedejesus@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:13:35 -0500 Subject: [PATCH] [Rule Tuning] M365 OneDrive Excessive File Downloads with OAuth Token (#5365) * [Rule Tuning] M365 OneDrive Excessive File Downloads with OAuth Token Fixes #5361 * adding keep operation * updating non-ecs --- detection_rules/etc/non-ecs-schema.json | 5 ++- ...ion_onedrive_excessive_file_downloads.toml | 38 ++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/detection_rules/etc/non-ecs-schema.json b/detection_rules/etc/non-ecs-schema.json index eba0ec55d..eae5d6174 100644 --- a/detection_rules/etc/non-ecs-schema.json +++ b/detection_rules/etc/non-ecs-schema.json @@ -145,7 +145,7 @@ "kibana.alert.rule.threat.tactic.id": "keyword", "kibana.alert.workflow_status": "keyword", "kibana.alert.rule.rule_id": "keyword", - "kibana.alert.rule.name": "keyword", + "kibana.alert.rule.name": "keyword", "kibana.alert.risk_score": "long", "kibana.alert.rule.type": "keyword", "kibana.alert.rule.threat.tactic.name": "keyword" @@ -237,7 +237,8 @@ "o365.audit.ExtendedProperties.ResultStatusDetail": "keyword", "o365.audit.OperationProperties.Name": "keyword", "o365.audit.OperationProperties.Value": "keyword", - "o365.audit.OperationCount": "long" + "o365.audit.OperationCount": "long", + "o365.audit.AppAccessContext.AADSessionId": "keyword" }, "logs-okta*": { "okta.debug_context.debug_data.flattened.requestedScopes": "keyword", diff --git a/rules/integrations/o365/collection_onedrive_excessive_file_downloads.toml b/rules/integrations/o365/collection_onedrive_excessive_file_downloads.toml index 90f37ea45..af239de29 100644 --- a/rules/integrations/o365/collection_onedrive_excessive_file_downloads.toml +++ b/rules/integrations/o365/collection_onedrive_excessive_file_downloads.toml @@ -2,7 +2,7 @@ creation_date = "2025/02/19" integration = ["o365"] maturity = "production" -updated_date = "2025/09/26" +updated_date = "2025/11/25" [rule] author = ["Elastic"] @@ -83,28 +83,38 @@ type = "esql" query = ''' from logs-o365.audit-* | where - @timestamp > now() - 14d and event.dataset == "o365.audit" and event.provider == "OneDrive" and event.action == "FileDownloaded" and o365.audit.AuthenticationType == "OAuth" and event.outcome == "success" -| eval - Esql.time_window_date_trunc = date_trunc(1 minutes, @timestamp) -| keep - Esql.time_window_date_trunc, - o365.audit.UserId, - file.name, - source.ip + and (user.id is not null and o365.audit.ApplicationId is not null) +| eval session.id = coalesce(o365.audit.AppAccessContext.AADSessionId, session.id, null) +| where session.id is not null +| eval Esql.time_window_date_trunc = date_trunc(1 minutes, @timestamp) | stats + Esql.file_directory_values = values(file.directory), + Esql.file_extension_values = values(file.extension), + Esql.application_name_values = values(application.name), Esql.file_name_count_distinct = count_distinct(file.name), + Esql.o365_audit_Site_values = values(o365.audit.Site), + Esql.o365_audit_SiteUrl_values = values(o365.audit.SiteUrl), + Esql.user_domain_values = values(user.domain), + Esql.token_id_values = values(token.id), Esql.event_count = count(*) - by +by Esql.time_window_date_trunc, - o365.audit.UserId, - source.ip -| where - Esql.file_name_count_distinct >= 25 + user.id, + session.id, + source.ip, + o365.audit.ApplicationId +| where Esql.file_name_count_distinct >= 25 +| keep + Esql.*, + user.id, + source.ip, + o365.audit.ApplicationId, + session.id '''