Query Details

23 Brute Force Single User Targeted

Query

id: e8f4a6b7-c2d3-5e9f-0a1b-2c3d4e5f6a7b
name: Non-Interactive Brute Force - Single User Targeted by Multiple IPs
version: 1.0.0
kind: Scheduled
description: |
  Detects targeted brute force / credential stuffing attacks against a single user account
  via non-interactive sign-ins, where the attacker uses multiple IP addresses to avoid
  rate limiting. The attack manifests as many authentication failures with wrong-password
  or locked-account error codes across distributed source IPs targeting the same user.
  MITRE ATT&CK: T1110 (Brute Force), T1110.001 (Password Guessing), T1110.004 (Credential Stuffing)
severity: Medium
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CredentialAccess
  - InitialAccess
relevantTechniques:
  - T1110
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
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: UserPrincipalName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
customDetails:
  FailureCount: FailCount
  UniqueIPs: UniqueIPs
  Countries: Countries
  ErrorCodes: ErrorCodes
alertDetailsOverride:
  alertDisplayNameFormat: "Brute Force Attack - {{UserPrincipalName}} received {{FailCount}} failures from {{UniqueIPs}} IPs"
  alertDescriptionFormat: "Account {{UserPrincipalName}} received {{FailCount}} non-interactive sign-in failures from {{UniqueIPs}} distinct IP addresses. Matches a distributed brute force or credential stuffing pattern."
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AnyAlert
    groupByEntities:
      - Account
    groupByAlertDetails: []
    groupByCustomDetails: []

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

Actions