Query Details

ADFS Brute Force - Single Account Targeted by Multiple IPs

04 ADFS Brute Force Single User

Query

let BruteForceErrors = dynamic(["50126", "50055", "50056", "50064",
                                  "50053", "50034", "50057", "396083"]);
ADFSSignInLogs
| where TimeGenerated > ago(1d)
| 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
| order by FailCount desc

Explanation

This query is designed to detect potential brute force attacks on Active Directory Federation Services (ADFS) by identifying situations where multiple distinct IP addresses are attempting to log into a single user account and failing. Here's a simple breakdown of what the query does:

  • Purpose: It aims to identify coordinated brute force attacks, possibly using a botnet, where more than 20 failed login attempts are made against one ADFS user account from different IP addresses within a day. This suggests an attempt to bypass per-IP rate limiting.

  • Error Codes: The query looks for specific error codes that indicate failed login attempts due to reasons like invalid credentials, wrong passwords, locked accounts, user not found, sign-in blocked, and ADFS extranet lockout.

  • Data Source: It uses data from Azure Active Directory, specifically the ADFSSignInLogs.

  • Frequency and Period: The query runs every 4 hours and checks data from the past day.

  • Detection Logic:

    • It filters login attempts from the past day that resulted in specific error codes.
    • It counts the number of failed attempts (FailCount) and the number of unique IP addresses (UniqueIPs) involved.
    • It collects information about the IP addresses, countries, and error codes associated with these attempts.
    • It identifies user accounts with more than 20 failed attempts and sorts them by the number of failures.
  • Alerting:

    • If such an attack is detected, an alert is generated with details like the user account targeted, the number of failures, and the number of unique IPs involved.
    • The alert is classified with a medium severity level and linked to MITRE ATT&CK techniques for brute force and valid accounts.
  • Incident Management:

    • An incident is created for each detected attack, and similar alerts are grouped together based on the user account involved.
    • Incidents are not reopened once closed, and the system looks back 12 hours to group related alerts.

Overall, this query helps in identifying and alerting on potential brute force attacks on ADFS, allowing security teams to take appropriate actions to protect user accounts.

Details

David Alonso profile picture

David Alonso

Released: March 24, 2026

Tables

ADFSSignInLogs

Keywords

ADFSIPsAccountUserADFSSignInLogsTimeGeneratedErrorCodeIPAddressLocationUserPrincipalName

Operators

letdynamicADFSSignInLogswhereagoextendtostringinsummarizecountdcountmake_setminmaxbyorder bydesc

Severity

Medium

Tactics

CredentialAccessInitialAccess

MITRE Techniques

Frequency: 4h

Period: 1d

Actions

GitHub