Azure Entra Sign-in Brute Force Microsoft 365 Accounts by Repeat Source

Identifies potential brute-force attempts against Microsoft 365 user accounts by detecting a high number of failed interactive or non-interactive login attempts within a 30-minute window from a single source. Attackers may attempt to brute force user accounts to gain unauthorized access to Microsoft 365 services via different services such as Exchange, SharePoint, or Teams.

Elastic rule (View on GitHub)

 1[metadata]
 2creation_date = "2024/09/06"
 3integration = ["azure"]
 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"]
11description = """
12Identifies potential brute-force attempts against Microsoft 365 user accounts by detecting a high number of failed
13interactive or non-interactive login attempts within a 30-minute window from a single source. Attackers may attempt to brute force user
14accounts to gain unauthorized access to Microsoft 365 services via different services such as Exchange, SharePoint, or
15Teams.
16"""
17false_positives = [
18    """
19    Automated processes that attempt to authenticate using expired credentials or have misconfigured authentication
20    settings may lead to false positives.
21    """,
22]
23from = "now-30m"
24language = "esql"
25interval = "10m"
26license = "Elastic License v2"
27name = "Azure Entra Sign-in Brute Force Microsoft 365 Accounts by Repeat Source"
28note = "This rule relies on Azure Entra ID sign-in logs, but filters for Microsoft 365 resources."
29references = [
30    "https://cloud.hacktricks.xyz/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying",
31    "https://github.com/0xZDH/o365spray"
32]
33risk_score = 47
34rule_id = "c6655282-6c79-11ef-bbb5-f661ea17fbcc"
35severity = "medium"
36tags = [
37    "Domain: Cloud",
38    "Domain: SaaS",
39    "Data Source: Azure",
40    "Data Source: Entra ID",
41    "Data Source: Entra ID Sign-in",
42    "Use Case: Identity and Access Audit",
43    "Use Case: Threat Detection",
44    "Tactic: Credential Access",
45]
46timestamp_override = "event.ingested"
47type = "esql"
48
49query = '''
50from logs-azure.signinlogs*
51| WHERE
52  event.dataset == "azure.signinlogs"
53  and event.category == "authentication"
54  and to_lower(azure.signinlogs.properties.resource_display_name) rlike "(.*)365(.*)"
55  and azure.signinlogs.category in ("NonInteractiveUserSignInLogs", "SignInLogs")
56  and event.outcome != "success"
57
58  // For tuning, review azure.signinlogs.properties.status.error_code
59  // https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes
60
61// keep only relevant fields
62| keep event.dataset, event.category, azure.signinlogs.properties.resource_display_name, azure.signinlogs.category, event.outcome, azure.signinlogs.properties.user_principal_name, source.ip
63
64// Count the number of unique targets per source IP
65| stats
66  target_count = count_distinct(azure.signinlogs.properties.user_principal_name) by source.ip
67
68// Filter for at least 10 distinct failed login attempts from a single source
69| where target_count >= 10
70'''
71
72
73[[rule.threat]]
74framework = "MITRE ATT&CK"
75[[rule.threat.technique]]
76id = "T1110"
77name = "Brute Force"
78reference = "https://attack.mitre.org/techniques/T1110/"
79
80
81[rule.threat.tactic]
82id = "TA0006"
83name = "Credential Access"
84reference = "https://attack.mitre.org/tactics/TA0006/"

This rule relies on Azure Entra ID sign-in logs, but filters for Microsoft 365 resources.

References

Related rules

to-top