Credential Access (TA0006)(external, opens in a new tab or window)
text code block:from logs-o365.audit-* | mv_expand event.category | eval Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp) | where event.dataset == "o365.audit" and event.category == "authentication" and event.provider in ("AzureActiveDirectory", "Exchange") and event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword") and to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(oauth.*||.*login.*)" and o365.audit.LogonError == "IdsLocked" and to_lower(o365.audit.UserId) != "not available" and o365.audit.Target.Type in ("0", "2", "6", "10") and source.`as`.organization.name != "MICROSOFT-CORP-MSN-as-BLOCK" | stats Esql_priv.o365_audit_UserId_count_distinct = count_distinct(to_lower(o365.audit.UserId)), Esql_priv.o365_audit_UserId_values = values(to_lower(o365.audit.UserId)), Esql.source_ip_values = values(source.ip), Esql.source_ip_count_distinct = count_distinct(source.ip), Esql.source_as_organization_name_values = values(source.`as`.organization.name), Esql.source_as_organization_name_count_distinct = count_distinct(source.`as`.organization.name), Esql.source_geo_country_name_values = values(source.geo.country_name), Esql.source_geo_country_name_count_distinct = count_distinct(source.geo.country_name), Esql.o365_audit_ExtendedProperties_RequestType_values = values(to_lower(o365.audit.ExtendedProperties.RequestType)), Esql.timestamp_first_seen = min(@timestamp), Esql.timestamp_last_seen = max(@timestamp), Esql.event_count = count(*) by Esql.time_window_date_trunc | eval Esql.event_duration_seconds = date_diff("seconds", Esql.timestamp_first_seen, Esql.timestamp_last_seen) | keep Esql.time_window_date_trunc, Esql_priv.o365_audit_UserId_count_distinct, Esql_priv.o365_audit_UserId_values, Esql.source_ip_values, Esql.source_ip_count_distinct, Esql.source_as_organization_name_values, Esql.source_as_organization_name_count_distinct, Esql.source_geo_country_name_values, Esql.source_geo_country_name_count_distinct, Esql.o365_audit_ExtendedProperties_RequestType_values, Esql.timestamp_first_seen, Esql.timestamp_last_seen, Esql.event_count, Esql.event_duration_seconds | where Esql_priv.o365_audit_UserId_count_distinct >= 10 and Esql.event_count >= 10 and Esql.event_duration_seconds <= 300
Install detection rules in Elastic Security
Detect M365 Identity User Account Lockouts in the Elastic Security detection engine by installing this rule into your Elastic Stack.
To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(external, opens in a new tab or window).