Entra ID Sign-in Brute Force Attempted (Microsoft 365)

Last updated 15 days ago on 2025-12-10
Created a year ago on 2024-09-06

About

Identifies potential brute-force attacks targeting Microsoft 365 user accounts by analyzing failed sign-in patterns in Microsoft Entra ID Sign-In Logs. This detection focuses on a high volume of failed interactive or non-interactive authentication attempts within a short time window, often indicative of password spraying, credential stuffing, or password guessing. Adversaries may use these techniques to gain unauthorized access to Microsoft 365 services such as Exchange Online, SharePoint, or Teams.
Tags
Domain: CloudDomain: SaaSDomain: IdentityData Source: AzureData Source: Entra IDData Source: Entra ID Sign-in LogsUse Case: Identity and Access AuditUse Case: Threat DetectionTactic: Credential AccessLanguage: esql
Severity
medium
Risk Score
47
MITRE ATT&CK™

Credential Access (TA0006)(external, opens in a new tab or window)

False Positive Examples
Automated processes that attempt to authenticate using expired credentials or have misconfigured authentication settings may lead to false positives.
License
Elastic License v2(external, opens in a new tab or window)

Definition

Integration Pack
Prebuilt Security Detection Rules
Related Integrations

azure(external, opens in a new tab or window)

Query
text code block:
from logs-azure.signinlogs-* | eval Esql.time_window_date_trunc = date_trunc(15 minutes, @timestamp), Esql_priv.azure_signinlogs_properties_user_principal_name_lower = to_lower(azure.signinlogs.properties.user_principal_name), Esql.azure_signinlogs_properties_incoming_token_type_lower = to_lower(azure.signinlogs.properties.incoming_token_type), Esql.azure_signinlogs_properties_app_display_name_lower = to_lower(azure.signinlogs.properties.app_display_name), Esql.user_agent_original = user_agent.original | where event.dataset == "azure.signinlogs" and event.category == "authentication" and azure.signinlogs.category in ("NonInteractiveUserSignInLogs", "SignInLogs") and azure.signinlogs.properties.resource_display_name rlike "(.*)365|SharePoint|Exchange|Teams|Office(.*)" and event.outcome == "failure" and azure.signinlogs.properties.status.error_code != 50053 and azure.signinlogs.properties.status.error_code in ( 50034, // UserAccountNotFound 50126, // InvalidUsernameOrPassword 50055, // PasswordExpired 50056, // InvalidPassword 50057, // UserDisabled 50064, // CredentialValidationFailure 50076, // MFARequiredButNotPassed 50079, // MFARegistrationRequired 50105, // EntitlementGrantsNotFound 70000, // InvalidGrant 70008, // ExpiredOrRevokedRefreshToken 70043, // BadTokenDueToSignInFrequency 80002, // OnPremisePasswordValidatorRequestTimedOut 80005, // OnPremisePasswordValidatorUnpredictableWebException 50144, // InvalidPasswordExpiredOnPremPassword 50135, // PasswordChangeCompromisedPassword 50142, // PasswordChangeRequiredConditionalAccess 120000, // PasswordChangeIncorrectCurrentPassword 120002, // PasswordChangeInvalidNewPasswordWeak 120020 // PasswordChangeFailure ) and azure.signinlogs.properties.user_principal_name is not null and azure.signinlogs.properties.user_principal_name != "" and user_agent.original != "Mozilla/5.0 (compatible; MSAL 1.0) PKeyAuth/1.0" | stats Esql.azure_signinlogs_properties_authentication_requirement_values = values(azure.signinlogs.properties.authentication_requirement), Esql.azure_signinlogs_properties_app_id_values = values(azure.signinlogs.properties.app_id), Esql.azure_signinlogs_properties_app_display_name_values = values(azure.signinlogs.properties.app_display_name), Esql.azure_signinlogs_properties_resource_id_values = values(azure.signinlogs.properties.resource_id), Esql.azure_signinlogs_properties_resource_display_name_values = values(azure.signinlogs.properties.resource_display_name), Esql.azure_signinlogs_properties_conditional_access_status_values = values(azure.signinlogs.properties.conditional_access_status), Esql.azure_signinlogs_properties_device_detail_browser_values = values(azure.signinlogs.properties.device_detail.browser), Esql.azure_signinlogs_properties_device_detail_device_id_values = values(azure.signinlogs.properties.device_detail.device_id), Esql.azure_signinlogs_properties_device_detail_operating_system_values = values(azure.signinlogs.properties.device_detail.operating_system), Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type), Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state), Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id), Esql.azure_signinlogs_properties_user_id_values = values(azure.signinlogs.properties.user_id), Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name), Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description), Esql.azure_signinlogs_result_signature_values = values(azure.signinlogs.result_signature), Esql.azure_signinlogs_result_type_values = values(azure.signinlogs.result_type), Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct = count_distinct(Esql_priv.azure_signinlogs_properties_user_principal_name_lower), Esql_priv.azure_signinlogs_properties_user_principal_name_lower_values = values(Esql_priv.azure_signinlogs_properties_user_principal_name_lower), Esql.azure_signinlogs_result_description_count_distinct = count_distinct(azure.signinlogs.result_description), Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description), Esql.azure_signinlogs_properties_status_error_code_count_distinct = count_distinct(azure.signinlogs.properties.status.error_code), Esql.azure_signinlogs_properties_status_error_code_values = values(azure.signinlogs.properties.status.error_code), Esql.azure_signinlogs_properties_incoming_token_type_lower_values = values(Esql.azure_signinlogs_properties_incoming_token_type_lower), Esql.azure_signinlogs_properties_app_display_name_lower_values = values(Esql.azure_signinlogs_properties_app_display_name_lower), 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.@timestamp.min = min(@timestamp), Esql.@timestamp.max = max(@timestamp), Esql.event_count = count() by Esql.time_window_date_trunc | eval Esql.event_duration_seconds = date_diff("seconds", Esql.@timestamp.min, Esql.@timestamp.max), Esql.event_bf_type = case( Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct >= 10 and Esql.event_count >= 30 and Esql.azure_signinlogs_result_description_count_distinct <= 3 and Esql.source_ip_count_distinct >= 5 and Esql.event_duration_seconds <= 600 and Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct > Esql.source_ip_count_distinct, "credential_stuffing", Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct >= 15 and Esql.azure_signinlogs_result_description_count_distinct == 1 and Esql.event_count >= 15 and Esql.event_duration_seconds <= 1800, "password_spraying", (Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct == 1 and Esql.azure_signinlogs_result_description_count_distinct == 1 and Esql.event_count >= 30 and Esql.event_duration_seconds <= 300) or (Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct <= 3 and Esql.source_ip_count_distinct > 30 and Esql.event_count >= 100), "password_guessing", "other" ) | where Esql.event_bf_type != "other" | keep Esql.time_window_date_trunc, Esql.event_bf_type, Esql.event_duration_seconds, Esql.event_count, Esql.@timestamp.min, Esql.@timestamp.max, Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct, Esql_priv.azure_signinlogs_properties_user_principal_name_lower_values, Esql.azure_signinlogs_result_description_count_distinct, Esql.azure_signinlogs_result_description_values, Esql.azure_signinlogs_properties_status_error_code_count_distinct, Esql.azure_signinlogs_properties_status_error_code_values, Esql.azure_signinlogs_properties_incoming_token_type_lower_values, Esql.azure_signinlogs_properties_app_display_name_lower_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.azure_signinlogs_properties_authentication_requirement_values, Esql.azure_signinlogs_properties_app_id_values, Esql.azure_signinlogs_properties_app_display_name_values, Esql.azure_signinlogs_properties_resource_id_values, Esql.azure_signinlogs_properties_resource_display_name_values, Esql.azure_signinlogs_properties_conditional_access_status_values, Esql.azure_signinlogs_properties_device_detail_browser_values, Esql.azure_signinlogs_properties_device_detail_device_id_values, Esql.azure_signinlogs_properties_device_detail_operating_system_values, Esql.azure_signinlogs_properties_incoming_token_type_values, Esql.azure_signinlogs_properties_risk_state_values, Esql.azure_signinlogs_properties_session_id_values, Esql.azure_signinlogs_properties_user_id_values

Install detection rules in Elastic Security

Detect Entra ID Sign-in Brute Force Attempted (Microsoft 365) 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).