Description
Description
From recent VOID BLIZZARD research, password spraying and brute-force were a key observation for initial access to accounts in Entra ID. As such we have rules to detect this behavior, but not excessive lockouts if the method used were credential stuffing or password guessing. This error is often returned when authentication is attempted for an account that is locked. A high volume of these would be a decent signal.
Target Ruleset
azure
Target Rule Type
ES|QL
Tested ECS Version
No response
Query
FROM logs-azure.signinlogs*
| EVAL
time_window = DATE_TRUNC(15 minutes, @timestamp),
user_id = TO_LOWER(azure.signinlogs.properties.user_principal_name),
ip = source.ip,
login_error = azure.signinlogs.result_description,
error_code = azure.signinlogs.properties.status.error_code,
request_type = TO_LOWER(azure.signinlogs.properties.incoming_token_type),
app_name = TO_LOWER(azure.signinlogs.properties.app_display_name),
asn_org = source.`as`.organization.name,
country = source.geo.country_name,
user_agent = user_agent.original,
event_time = @timestamp
| WHERE event.dataset == "azure.signinlogs"
AND event.category == "authentication"
AND azure.signinlogs.category IN ("NonInteractiveUserSignInLogs", "SignInLogs")
//AND event.outcome == "failure"
AND azure.signinlogs.properties.authentication_requirement == "singleFactorAuthentication"
AND error_code == 50053
AND user_id IS NOT NULL AND user_id != ""
AND user_agent != "Mozilla/5.0 (compatible; MSAL 1.0) PKeyAuth/1.0"
AND asn_org != "MICROSOFT-CORP-MSN-AS-BLOCK"
| STATS
authentication_requirement = VALUES(azure.signinlogs.properties.authentication_requirement),
client_app_id = VALUES(azure.signinlogs.properties.app_id),
client_app_display_name = VALUES(azure.signinlogs.properties.app_display_name),
target_resource_id = VALUES(azure.signinlogs.properties.resource_id),
target_resource_display_name = VALUES(azure.signinlogs.properties.resource_display_name),
conditional_access_status = VALUES(azure.signinlogs.properties.conditional_access_status),
device_detail_browser = VALUES(azure.signinlogs.properties.device_detail.browser),
device_detail_device_id = VALUES(azure.signinlogs.properties.device_detail.device_id),
device_detail_operating_system = VALUES(azure.signinlogs.properties.device_detail.operating_system),
incoming_token_type = VALUES(azure.signinlogs.properties.incoming_token_type),
risk_state = VALUES(azure.signinlogs.properties.risk_state),
session_id = VALUES(azure.signinlogs.properties.session_id),
user_id = VALUES(azure.signinlogs.properties.user_id),
user_principal_name = VALUES(azure.signinlogs.properties.user_principal_name),
result_description = VALUES(azure.signinlogs.result_description),
result_signature = VALUES(azure.signinlogs.result_signature),
result_type = VALUES(azure.signinlogs.result_type),
unique_users = COUNT_DISTINCT(user_id),
user_id_list = VALUES(user_id),
login_errors = VALUES(login_error),
unique_login_errors = COUNT_DISTINCT(login_error),
error_codes = VALUES(error_code),
unique_error_codes = COUNT_DISTINCT(error_code),
request_types = VALUES(request_type),
app_names = VALUES(app_name),
ip_list = VALUES(ip),
unique_ips = COUNT_DISTINCT(ip),
source_orgs = VALUES(asn_org),
countries = VALUES(country),
unique_country_count = COUNT_DISTINCT(country),
unique_asn_orgs = COUNT_DISTINCT(asn_org),
first_seen = MIN(event_time),
last_seen = MAX(event_time),
total_attempts = COUNT()
BY time_window
| WHERE unique_users >= 15 AND (total_attempts >= unique_users)
| KEEP
time_window, total_attempts, first_seen, last_seen,
unique_users, user_id_list, login_errors, unique_login_errors,
unique_error_codes, error_codes, request_types, app_names,
ip_list, unique_ips, source_orgs, countries,
unique_country_count, unique_asn_orgs,
authentication_requirement, client_app_id, client_app_display_name,
target_resource_id, target_resource_display_name, conditional_access_status,
device_detail_browser, device_detail_device_id, device_detail_operating_system,
incoming_token_type, risk_state, session_id, user_id,
user_principal_name, result_description, result_signature, result_type
New fields required in ECS/data sources for this rule?
No response
Related issues or PRs
No response
References
- https://www.microsoft.com/en-us/security/blog/2025/05/27/new-russia-affiliated-actor-void-blizzard-targets-critical-sectors-for-espionage/
- https://www.sprocketsecurity.com/blog/exploring-modern-password-spraying
Redacted Example Data
No response