Attempts to Brute Force a Microsoft 365 User Account
Identifies potential brute-force attempts against Microsoft 365 user accounts by detecting a high number of failed login attempts or login sources within a 30-minute window. Attackers may attempt to brute force user accounts to gain unauthorized access to Microsoft 365 services.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2020/11/30"
3integration = ["o365"]
4maturity = "production"
5min_stack_comments = "ES|QL not available until 8.13.0 in technical preview."
6min_stack_version = "8.13.0"
7updated_date = "2024/10/09"
8
9[rule]
10author = ["Elastic", "Willem D'Haese", "Austin Songer"]
11description = """
12Identifies potential brute-force attempts against Microsoft 365 user accounts by detecting a high number of failed login attempts or login sources within a 30-minute window. Attackers may attempt to brute force user accounts to gain unauthorized access to Microsoft 365 services.
13"""
14false_positives = [
15 """
16 Automated processes that attempt to authenticate using expired credentials and unbounded retries may lead to false
17 positives.
18 """,
19]
20from = "now-9m"
21language = "esql"
22license = "Elastic License v2"
23name = "Attempts to Brute Force a Microsoft 365 User Account"
24references = [
25 "https://blueteamblog.com/7-ways-to-monitor-your-office-365-logs-using-siem",
26 "https://learn.microsoft.com/en-us/purview/audit-log-detailed-properties",
27]
28risk_score = 47
29rule_id = "26f68dba-ce29-497b-8e13-b4fde1db5a2d"
30severity = "medium"
31tags = [
32 "Domain: Cloud",
33 "Domain: SaaS",
34 "Data Source: Microsoft 365",
35 "Use Case: Identity and Access Audit",
36 "Use Case: Threat Detection",
37 "Tactic: Credential Access",
38]
39timestamp_override = "event.ingested"
40type = "esql"
41
42query = '''
43from logs-o365.audit-*
44// truncate the timestamp to a 30-minute window
45| eval target_time_window = DATE_TRUNC(30 minutes, @timestamp)
46| mv_expand event.category
47| where event.dataset == "o365.audit"
48 and event.category == "authentication"
49
50 // filter only on Entra ID or Exchange audit logs in O365 integration
51 and event.provider in ("AzureActiveDirectory", "Exchange")
52
53 // filter only for UserLoginFailed or partial failures
54 and event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword")
55
56 // ignore specific logon errors
57 and not o365.audit.LogonError in (
58 "EntitlementGrantsNotFound",
59 "UserStrongAuthEnrollmentRequired",
60 "UserStrongAuthClientAuthNRequired",
61 "InvalidReplyTo",
62 "SsoArtifactExpiredDueToConditionalAccess",
63 "PasswordResetRegistrationRequiredInterrupt",
64 "SsoUserAccountNotFoundInResourceTenant",
65 "UserStrongAuthExpired",
66 "CmsiInterrupt"
67)
68
69 // ignore unavailable
70 and o365.audit.UserId != "Not Available"
71
72 // filters out non user or application logins based on target
73 and o365.audit.Target.Type in ("0", "2", "3", "5", "6", "10")
74
75 // filters only for logins from user or application, ignoring oauth:token
76 and to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(.*)login(.*)"
77
78// keep only relevant fields
79| keep event.provider, event.dataset, event.category, o365.audit.UserId, event.action, source.ip, o365.audit.LogonError, o365.audit.ExtendedProperties.RequestType, o365.audit.Target.Type, target_time_window
80
81// count the number of login sources and failed login attempts
82| stats
83 login_source_count = count(source.ip),
84 failed_login_count = count(*) by target_time_window, o365.audit.UserId
85
86// filter for users with more than 20 login sources or failed login attempts
87| where (login_source_count >= 20 or failed_login_count >= 20)
88'''
89
90
91[[rule.threat]]
92framework = "MITRE ATT&CK"
93[[rule.threat.technique]]
94id = "T1110"
95name = "Brute Force"
96reference = "https://attack.mitre.org/techniques/T1110/"
97
98
99[rule.threat.tactic]
100id = "TA0006"
101name = "Credential Access"
102reference = "https://attack.mitre.org/tactics/TA0006/"
References
Related rules
- Azure Entra Sign-in Brute Force Microsoft 365 Accounts by Repeat Source
- Azure Entra Sign-in Brute Force against Microsoft 365 Accounts
- Deprecated - Potential Password Spraying of Microsoft 365 User Accounts
- O365 Excessive Single Sign-On Logon Errors
- Multiple Device Token Hashes for Single Okta Session