Query Details

ADFS Low-and-Slow Password Spray - Rate-Evasion Pattern

03 ADFS Low And Slow Spray

Query

let SprayErrors = dynamic(["50126", "50034", "50053", "396083"]);
ADFSSignInLogs
| where TimeGenerated > ago(1d)
| extend ErrorCode = tostring(ResultType)
| where ErrorCode in (SprayErrors)
| summarize
    FailsPerHour = count(),
    UniqueUsers  = dcount(UserPrincipalName)
  by IPAddress, bin(TimeGenerated, 1h)
| where FailsPerHour between (2 .. 15)
   and  UniqueUsers > 5
| summarize
    SprayHours    = count(),
    TotalAttempts = sum(FailsPerHour),
    TotalUsers    = sum(UniqueUsers)
  by IPAddress
| where SprayHours >= 3
| order by SprayHours desc

Explanation

This query is designed to detect a specific type of cyber attack known as a "low-and-slow" password spray against Active Directory Federation Services (ADFS). Here's a simple breakdown of what it does:

  1. Purpose: It identifies IP addresses that are attempting to guess passwords by making a small number of login attempts (2 to 15 failures per hour) across more than 5 different user accounts. This method is used to avoid triggering account lockouts and bypass ADFS rate limits.

  2. Data Source: The query uses data from ADFS sign-in logs, specifically looking for certain error codes that indicate failed login attempts.

  3. Detection Criteria:

    • It examines login attempts over the past day.
    • It counts the number of failed attempts per hour and the number of unique user accounts targeted.
    • It flags IP addresses that have at least 3 hours of such activity within the day.
  4. Alerting: If an IP address meets these criteria, it triggers an alert. The alert includes details like the number of hours the activity was observed, the total number of failed attempts, and the number of unique users targeted.

  5. Severity and Tactics: The severity of the alert is set to medium, and it aligns with tactics like Credential Access and Initial Access as per the MITRE ATT&CK framework.

  6. Incident Management: The query is scheduled to run every 6 hours and will create an incident if the conditions are met. It groups incidents by IP address to manage related alerts together.

Overall, this query helps security teams identify and respond to stealthy password spray attacks that might otherwise go unnoticed due to their low volume and slow pace.

Details

David Alonso profile picture

David Alonso

Released: March 24, 2026

Tables

ADFSSignInLogs

Keywords

ADFSAzureActiveDirectoryIPAddressUserPrincipalNameTimeGeneratedResultType

Operators

letdynamicwhereagoextendtostringinsummarizecountdcountbybinbetweenandorder bydesc

Severity

Medium

Tactics

CredentialAccessInitialAccess

MITRE Techniques

Frequency: 6h

Period: 1d

Actions

GitHub