Query Details

Non-Interactive Brute Force - Single User Targeted by Multiple IPs

23 Brute Force Single User Targeted

Query

let BruteForceErrors = dynamic([
    "50126",  // InvalidPasswordOrUsernameOrTenantInvalid
    "50055",  // InvalidPasswordExpiredPassword
    "50056",  // InvalidPasswordNullPassword
    "50064",  // CredentialAuthenticationError
    "50053",  // IdsLocked (account locked)
    "50034",  // UserAccountNotFound
    "50057",  // UserDisabled
    "50128"   // InvalidTenantName
]);
AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(1h)
| extend ErrorCode = tostring(ResultType)
| where ErrorCode in (BruteForceErrors)
| summarize
    FailCount   = count(),
    UniqueIPs   = dcount(IPAddress),
    IPs         = make_set(IPAddress, 20),
    Countries   = make_set(Location),
    ErrorCodes  = make_set(ErrorCode),
    FirstSeen   = min(TimeGenerated),
    LastSeen    = max(TimeGenerated)
  by UserPrincipalName
| where FailCount > 20
| extend IPAddress = tostring(IPs[0])
| order by FailCount desc

Explanation

This query is designed to detect potential brute force or credential stuffing attacks on a single user account. Here's a simple breakdown of what it does:

  1. Purpose: It identifies situations where multiple IP addresses are used to attempt to log into a single user account unsuccessfully. This is a common tactic to bypass rate limiting and indicates a possible attack.

  2. Data Source: The query uses logs from Azure Active Directory, specifically focusing on non-interactive sign-in attempts.

  3. Error Codes: It looks for specific error codes that indicate failed login attempts, such as incorrect passwords or locked accounts.

  4. Time Frame: The query checks for these events within the last hour.

  5. Criteria for Alert:

    • More than 20 failed login attempts for a single user.
    • These attempts come from multiple distinct IP addresses.
  6. Output: For each user account that meets the criteria, the query provides:

    • The total number of failed attempts.
    • The number of unique IP addresses involved.
    • A list of these IP addresses and their locations.
    • The error codes encountered.
    • The time range of these attempts.
  7. Alerting: If the criteria are met, an alert is generated. The alert includes details like the number of failures and the number of IPs involved, and it is designed to help security teams quickly identify and respond to potential attacks.

  8. Incident Management: The system can automatically create an incident if such an attack pattern is detected, helping streamline the response process. It groups incidents by user account to manage related alerts effectively.

Overall, this query helps in identifying and responding to distributed brute force attacks targeting specific user accounts by analyzing failed login attempts from various IP addresses.

Details

David Alonso profile picture

David Alonso

Released: May 29, 2026

Tables

AADNonInteractiveUserSignInLogs

Keywords

AzureActiveDirectoryAADNonInteractiveUserSignInLogsUserPrincipalNameIPAddressLocationTimeGeneratedResultTypeAccountIP

Operators

letdynamicagoextendtostringinsummarizecountdcountmake_setminmaxbyorder bydesc

Severity

Medium

Tactics

CredentialAccessInitialAccess

MITRE Techniques

Frequency: 1h

Period: 1h

Actions

GitHub