[Rule Tuning] M365/Azure Brute-Forcing New Rule and Tuning; Deprecate Similar Rule (#4057)
* deprecated rule; tuned for single source inclusion * adjusted query comments * added min-stack * updated date * added Azure-based rule for brute forcing * added reference to o365spray * fixed tag * adjusted query comment * added rule for repeat source * adjusted query to use count distinct * added intervals; adjusted lookback window according to time truncation
This commit is contained in:
+83
@@ -0,0 +1,83 @@
|
||||
[metadata]
|
||||
creation_date = "2024/09/06"
|
||||
integration = ["azure"]
|
||||
maturity = "production"
|
||||
min_stack_comments = "ES|QL not available until 8.13.0 in technical preview."
|
||||
min_stack_version = "8.13.0"
|
||||
updated_date = "2024/09/06"
|
||||
|
||||
[rule]
|
||||
author = ["Elastic"]
|
||||
description = """
|
||||
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. 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.
|
||||
"""
|
||||
false_positives = [
|
||||
"""
|
||||
Automated processes that attempt to authenticate using expired credentials or have misconfigured authentication
|
||||
settings may lead to false positives.
|
||||
""",
|
||||
]
|
||||
from = "now-60m"
|
||||
language = "esql"
|
||||
interval = "10m"
|
||||
license = "Elastic License v2"
|
||||
name = "Azure Entra Sign-in Brute Force against Microsoft 365 Accounts"
|
||||
note = "This rule relies on Azure Entra ID sign-in logs, but filters for Microsoft 365 resources."
|
||||
references = [
|
||||
"https://cloud.hacktricks.xyz/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying",
|
||||
"https://github.com/0xZDH/o365spray"
|
||||
]
|
||||
risk_score = 47
|
||||
rule_id = "35ab3cfa-6c67-11ef-ab4d-f661ea17fbcc"
|
||||
severity = "medium"
|
||||
tags = [
|
||||
"Domain: Cloud",
|
||||
"Domain: SaaS",
|
||||
"Data Source: Azure",
|
||||
"Data Source: Entra ID",
|
||||
"Data Source: Entra ID Sign-in",
|
||||
"Use Case: Identity and Access Audit",
|
||||
"Use Case: Threat Detection",
|
||||
"Tactic: Credential Access",
|
||||
]
|
||||
timestamp_override = "event.ingested"
|
||||
type = "esql"
|
||||
|
||||
query = '''
|
||||
from logs-azure.signinlogs*
|
||||
// truncate the timestamp to a 30-minute window
|
||||
| eval target_time_window = DATE_TRUNC(30 minutes, @timestamp)
|
||||
| WHERE
|
||||
event.dataset == "azure.signinlogs"
|
||||
and event.category == "authentication"
|
||||
and to_lower(azure.signinlogs.properties.resource_display_name) rlike "(.*)365(.*)"
|
||||
and azure.signinlogs.category in ("NonInteractiveUserSignInLogs", "SignInLogs")
|
||||
and event.outcome != "success"
|
||||
// for tuning review azure.signinlogs.properties.status.error_code
|
||||
// https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes
|
||||
// count the number of login sources and failed login attempts
|
||||
| stats
|
||||
login_source_count = count(source.ip),
|
||||
failed_login_count = count(*) by target_time_window, azure.signinlogs.properties.user_principal_name
|
||||
|
||||
// filter for users with more than 20 login sources or failed login attempts
|
||||
| where (login_source_count >= 20 or failed_login_count >= 20)
|
||||
'''
|
||||
|
||||
|
||||
[[rule.threat]]
|
||||
framework = "MITRE ATT&CK"
|
||||
[[rule.threat.technique]]
|
||||
id = "T1110"
|
||||
name = "Brute Force"
|
||||
reference = "https://attack.mitre.org/techniques/T1110/"
|
||||
|
||||
|
||||
[rule.threat.tactic]
|
||||
id = "TA0006"
|
||||
name = "Credential Access"
|
||||
reference = "https://attack.mitre.org/tactics/TA0006/"
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
[metadata]
|
||||
creation_date = "2024/09/06"
|
||||
integration = ["azure"]
|
||||
maturity = "production"
|
||||
min_stack_comments = "ES|QL not available until 8.13.0 in technical preview."
|
||||
min_stack_version = "8.13.0"
|
||||
updated_date = "2024/09/06"
|
||||
|
||||
[rule]
|
||||
author = ["Elastic"]
|
||||
description = """
|
||||
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.
|
||||
"""
|
||||
false_positives = [
|
||||
"""
|
||||
Automated processes that attempt to authenticate using expired credentials or have misconfigured authentication
|
||||
settings may lead to false positives.
|
||||
""",
|
||||
]
|
||||
from = "now-30m"
|
||||
language = "esql"
|
||||
interval = "10m"
|
||||
license = "Elastic License v2"
|
||||
name = "Azure Entra Sign-in Brute Force Microsoft 365 Accounts by Repeat Source"
|
||||
note = "This rule relies on Azure Entra ID sign-in logs, but filters for Microsoft 365 resources."
|
||||
references = [
|
||||
"https://cloud.hacktricks.xyz/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying",
|
||||
"https://github.com/0xZDH/o365spray"
|
||||
]
|
||||
risk_score = 47
|
||||
rule_id = "c6655282-6c79-11ef-bbb5-f661ea17fbcc"
|
||||
severity = "medium"
|
||||
tags = [
|
||||
"Domain: Cloud",
|
||||
"Domain: SaaS",
|
||||
"Data Source: Azure",
|
||||
"Data Source: Entra ID",
|
||||
"Data Source: Entra ID Sign-in",
|
||||
"Use Case: Identity and Access Audit",
|
||||
"Use Case: Threat Detection",
|
||||
"Tactic: Credential Access",
|
||||
]
|
||||
timestamp_override = "event.ingested"
|
||||
type = "esql"
|
||||
|
||||
query = '''
|
||||
from logs-azure.signinlogs*
|
||||
| WHERE
|
||||
event.dataset == "azure.signinlogs"
|
||||
and event.category == "authentication"
|
||||
and to_lower(azure.signinlogs.properties.resource_display_name) rlike "(.*)365(.*)"
|
||||
and azure.signinlogs.category in ("NonInteractiveUserSignInLogs", "SignInLogs")
|
||||
and event.outcome != "success"
|
||||
|
||||
// For tuning, review azure.signinlogs.properties.status.error_code
|
||||
// https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes
|
||||
|
||||
// Count the number of unique targets per source IP
|
||||
| stats
|
||||
target_count = count_distinct(azure.signinlogs.properties.user_principal_name) by source.ip
|
||||
|
||||
// Filter for at least 10 distinct failed login attempts from a single source
|
||||
| where target_count >= 10
|
||||
'''
|
||||
|
||||
|
||||
[[rule.threat]]
|
||||
framework = "MITRE ATT&CK"
|
||||
[[rule.threat.technique]]
|
||||
id = "T1110"
|
||||
name = "Brute Force"
|
||||
reference = "https://attack.mitre.org/techniques/T1110/"
|
||||
|
||||
|
||||
[rule.threat.tactic]
|
||||
id = "TA0006"
|
||||
name = "Credential Access"
|
||||
reference = "https://attack.mitre.org/tactics/TA0006/"
|
||||
|
||||
+24
-20
@@ -2,13 +2,14 @@
|
||||
creation_date = "2020/11/30"
|
||||
integration = ["o365"]
|
||||
maturity = "production"
|
||||
updated_date = "2024/07/01"
|
||||
min_stack_comments = "ES|QL not available until 8.13.0 in technical preview."
|
||||
min_stack_version = "8.13.0"
|
||||
updated_date = "2024/09/05"
|
||||
|
||||
[rule]
|
||||
author = ["Elastic", "Willem D'Haese", "Austin Songer"]
|
||||
description = """
|
||||
Identifies attempts to brute force a Microsoft 365 user account. An adversary may attempt a brute force attack to obtain
|
||||
unauthorized access to user accounts.
|
||||
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.
|
||||
"""
|
||||
false_positives = [
|
||||
"""
|
||||
@@ -20,13 +21,10 @@ from = "now-9m"
|
||||
language = "esql"
|
||||
license = "Elastic License v2"
|
||||
name = "Attempts to Brute Force a Microsoft 365 User Account"
|
||||
note = """## Setup
|
||||
|
||||
The Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule."""
|
||||
references = [
|
||||
"https://blueteamblog.com/7-ways-to-monitor-your-office-365-logs-using-siem",
|
||||
"https://learn.microsoft.com/en-us/purview/audit-log-detailed-properties"
|
||||
]
|
||||
"https://learn.microsoft.com/en-us/purview/audit-log-detailed-properties",
|
||||
]
|
||||
risk_score = 47
|
||||
rule_id = "26f68dba-ce29-497b-8e13-b4fde1db5a2d"
|
||||
severity = "medium"
|
||||
@@ -35,6 +33,7 @@ tags = [
|
||||
"Domain: SaaS",
|
||||
"Data Source: Microsoft 365",
|
||||
"Use Case: Identity and Access Audit",
|
||||
"Use Case: Threat Detection",
|
||||
"Tactic: Credential Access",
|
||||
]
|
||||
timestamp_override = "event.ingested"
|
||||
@@ -42,18 +41,20 @@ type = "esql"
|
||||
|
||||
query = '''
|
||||
from logs-o365.audit-*
|
||||
| MV_EXPAND event.category
|
||||
| WHERE event.dataset == "o365.audit"
|
||||
AND event.category == "authentication"
|
||||
// truncate the timestamp to a 30-minute window
|
||||
| eval target_time_window = DATE_TRUNC(30 minutes, @timestamp)
|
||||
| mv_expand event.category
|
||||
| where event.dataset == "o365.audit"
|
||||
and event.category == "authentication"
|
||||
|
||||
// filter only on Entra ID or Exchange audit logs in O365 integration
|
||||
AND event.provider in ("AzureActiveDirectory", "Exchange")
|
||||
and event.provider in ("AzureActiveDirectory", "Exchange")
|
||||
|
||||
// filter only for UserLoginFailed or partial failures
|
||||
AND event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword")
|
||||
and event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword")
|
||||
|
||||
// ignore specific logon errors
|
||||
AND not o365.audit.LogonError in (
|
||||
and not o365.audit.LogonError in (
|
||||
"EntitlementGrantsNotFound",
|
||||
"UserStrongAuthEnrollmentRequired",
|
||||
"UserStrongAuthClientAuthNRequired",
|
||||
@@ -65,16 +66,18 @@ from logs-o365.audit-*
|
||||
"CmsiInterrupt"
|
||||
)
|
||||
// filters out non user or application logins based on target
|
||||
AND o365.audit.Target.Type in ("0", "2", "3", "5", "6", "10")
|
||||
and o365.audit.Target.Type in ("0", "2", "3", "5", "6", "10")
|
||||
|
||||
// filters only for logins from user or application, ignoring oauth:token
|
||||
AND to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(.*)login(.*)"
|
||||
and to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(.*)login(.*)"
|
||||
|
||||
| STATS
|
||||
// count the number of failed login attempts target per user
|
||||
login_attempt_counts = COUNT(*) by o365.audit.Target.ID, o365.audit.LogonError
|
||||
// count the number of login sources and failed login attempts
|
||||
| stats
|
||||
login_source_count = count(source.ip),
|
||||
failed_login_count = count(*) by target_time_window, o365.audit.UserId
|
||||
|
||||
| WHERE login_attempt_counts > 10
|
||||
// filter for users with more than 20 login sources or failed login attempts
|
||||
| where (login_source_count >= 20 or failed_login_count >= 20)
|
||||
'''
|
||||
|
||||
|
||||
@@ -90,3 +93,4 @@ reference = "https://attack.mitre.org/techniques/T1110/"
|
||||
id = "TA0006"
|
||||
name = "Credential Access"
|
||||
reference = "https://attack.mitre.org/tactics/TA0006/"
|
||||
|
||||
|
||||
+3
-5
@@ -2,7 +2,7 @@
|
||||
creation_date = "2020/12/01"
|
||||
integration = ["o365"]
|
||||
maturity = "production"
|
||||
updated_date = "2024/05/21"
|
||||
updated_date = "2024/09/05"
|
||||
|
||||
[rule]
|
||||
author = ["Elastic"]
|
||||
@@ -21,10 +21,8 @@ from = "now-30m"
|
||||
index = ["filebeat-*", "logs-o365*"]
|
||||
language = "kuery"
|
||||
license = "Elastic License v2"
|
||||
name = "Potential Password Spraying of Microsoft 365 User Accounts"
|
||||
note = """## Setup
|
||||
|
||||
The Office 365 Logs Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule."""
|
||||
name = "Deprecated - Potential Password Spraying of Microsoft 365 User Accounts"
|
||||
note = """This rule has been deprecated in favor of `Attempts to Brute Force a Microsoft 365 User Account` (26f68dba-ce29-497b-8e13-b4fde1db5a2d)."""
|
||||
risk_score = 73
|
||||
rule_id = "3efee4f0-182a-40a8-a835-102c68a4175d"
|
||||
severity = "high"
|
||||
|
||||
Reference in New Issue
Block a user