Loading

Attempts to Brute Force a Microsoft 365 User Account

Elastic Stack Serverless Security

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.

Rule type: esql

Rule indices: None

Severity: medium

Risk score: 47

Runs every: 5m

Searches indices from: now-9m (https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math[Date Math format], see also Additional look-back time)

Maximum alerts per execution: 100

References:

Tags:

  • Domain: Cloud
  • Domain: SaaS
  • Data Source: Microsoft 365
  • Use Case: Identity and Access Audit
  • Use Case: Threat Detection
  • Tactic: Credential Access
  • Resources: Investigation Guide

Version: 312

Rule authors:

  • Elastic
  • Willem D’Haese
  • Austin Songer

Rule license: Elastic License v2

Triage and analysis

[TBC: QUOTE]
Investigating Attempts to Brute Force a Microsoft 365 User Account

Microsoft 365 is a cloud-based service that provides productivity tools and services. Adversaries may attempt to gain unauthorized access by brute-forcing user accounts, exploiting weak passwords. The detection rule identifies such attempts by analyzing audit logs for numerous failed logins or diverse login sources within a short timeframe, indicating potential brute-force activity.

Possible investigation steps

  • Review the audit logs for the specific user identified by o365.audit.UserId to gather additional context on the failed login attempts, including timestamps and source IP addresses.
  • Analyze the source.ip field to identify any unusual or suspicious IP addresses, such as those originating from unexpected geographic locations or known malicious sources.
  • Check the o365.audit.LogonError field for any patterns or specific errors that might provide insight into the nature of the failed login attempts.
  • Investigate the o365.audit.ExtendedProperties.RequestType to determine if the login attempts were consistent with typical user behavior or if they suggest automated or scripted activity.
  • Correlate the findings with other security events or alerts in the environment to assess if the brute-force attempts are part of a larger attack campaign or isolated incidents.
  • Contact the affected user to verify if they experienced any issues accessing their account and to ensure they are aware of the potential security threat.

False positive analysis

  • High volume of legitimate login attempts from a single user can trigger false positives, especially during password resets or account recovery. To mitigate, consider excluding specific users or IP ranges known for such activities.
  • Automated scripts or applications performing frequent logins for legitimate purposes may be misidentified as brute-force attempts. Identify and whitelist these scripts or applications by their user IDs or IP addresses.
  • Users traveling or using VPNs may log in from multiple locations in a short period, leading to false positives. Implement geolocation-based exceptions for known travel patterns or VPN IP addresses.
  • Shared accounts accessed by multiple users from different locations can appear as multiple login sources. Limit monitoring on shared accounts or establish a baseline of expected behavior to differentiate between normal and suspicious activity.
  • Temporary spikes in login attempts due to system maintenance or updates can be mistaken for brute-force attacks. Schedule monitoring exclusions during planned maintenance windows to avoid false alerts.

Response and remediation

  • Immediately isolate the affected user account by disabling it to prevent further unauthorized access attempts.
  • Notify the user and relevant IT security personnel about the potential compromise and provide guidance on secure password creation.
  • Conduct a password reset for the affected user account, ensuring the new password adheres to strong password policies.
  • Review and analyze the source IP addresses involved in the failed login attempts to identify any patterns or known malicious sources.
  • Implement conditional access policies to restrict login attempts from suspicious or untrusted locations and devices.
  • Monitor the affected account and related accounts for any unusual activity or further unauthorized access attempts.
  • Escalate the incident to the security operations center (SOC) or incident response team for further investigation and to determine if additional accounts or systems are affected.
from logs-o365.audit-*
// 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")

  // filter only for UserLoginFailed or partial failures
  and event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword")

  // ignore specific logon errors
  and not o365.audit.LogonError in (
    "EntitlementGrantsNotFound",
    "UserStrongAuthEnrollmentRequired",
    "UserStrongAuthClientAuthNRequired",
    "InvalidReplyTo",
    "SsoArtifactExpiredDueToConditionalAccess",
    "PasswordResetRegistrationRequiredInterrupt",
    "SsoUserAccountNotFoundInResourceTenant",
    "UserStrongAuthExpired",
    "CmsiInterrupt"
)

  // ignore unavailable
  and o365.audit.UserId != "Not Available"

  // filters out non user or application logins based on target
  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(.*)"

// keep only relevant fields
| 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

// 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

// filter for users with more than 20 login sources or failed login attempts
| where (login_source_count >= 20 or failed_login_count >= 20)

Framework: MITRE ATT&CKTM