← Back to SOC feed Coverage →

Suspected Brute force attack Investigation

kql MEDIUM Azure-Sentinel
T1110
AADNonInteractiveUserSignInLogsSigninLogs
huntingmicrosoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-06-04T11:00:00Z · Confidence: medium

Hunt Hypothesis

Users attempting to brute force Azure AD credentials by generating excessive authentication failure events may indicate a coordinated attack effort, and proactive hunting for such high-volume failure patterns helps identify potential credential compromise before account lockouts or lateral movement occur. This behavior aligns with T1110 and is critical to detect early in Azure Sentinel to mitigate unauthorized access risks.

KQL Query

let successCodes = dynamic(["0", "50125", "50140", "70043", "70044"]);
let aadFunc = (tableName:string){
  table(tableName)
 | extend FailureOrSuccess = iff(ResultType in (successCodes), "Success", "Failure")
 | summarize FailureCount = countif(FailureOrSuccess=="Failure"), SuccessCount = countif(FailureOrSuccess=="Success") by bin(TimeGenerated, 1h),UserPrincipalName, UserDisplayName, IPAddress
 | where FailureCount > 100
 | where SuccessCount > 0
 | order by UserPrincipalName, TimeGenerated asc
 | extend AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt

Analytic Rule Definition

id: 056ceb9b-8f07-42b3-853e-ef3779de222e
name: Suspected Brute force attack Investigation
description: |
  'Summarize all the failures and success events for all users in the last 24 hours, 
  only identify users with more than 100 failures in the set period'
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - SigninLogs
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
tactics:
  - CredentialAccess
relevantTechniques:
  - T1110
query: |
    let successCodes = dynamic(["0", "50125", "50140", "70043", "70044"]);
    let aadFunc = (tableName:string){
      table(tableName)
     | extend FailureOrSuccess = iff(ResultType in (successCodes), "Success", "Failure")
     | summarize FailureCount = countif(FailureOrSuccess=="Failure"), SuccessCount = countif(FailureOrSuccess=="Success") by bin(TimeGenerated, 1h),UserPrincipalName, UserDisplayName, IPAddress
     | where FailureCount > 100
     | where SuccessCount > 0
     | order by UserPrincipalName, TimeGenerated asc
     | extend AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress
    };
    let aadSignin = aadFunc("SigninLogs");
    let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
    union isfuzzy=true aadSignin, aadNonInt
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountCustomEntity
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity  

Required Data Sources

Sentinel TableNotes
AADNonInteractiveUserSignInLogsEnsure this data connector is enabled
SigninLogsEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Hunting Queries/SigninLogs/AADSuspectedBruteForce.yaml