Query Details

24 ROPC Credential Stuffing

Query

id: a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d
name: ROPC Credential Stuffing - Failed Password Grant Spray
version: 1.0.0
kind: Scheduled
description: |
  Detects credential-stuffing patterns over the ROPC (Resource Owner Password Credential)
  grant: large numbers of failed password-grant attempts from a single IP across many
  distinct user accounts. ROPC is the preferred protocol for command-line credential
  stuffing tools because it bypasses MFA and avoids interactive prompts.

  Trigger:
    >= 15 ROPC failures (50126 / 50053 / 50056 / 50055 / 50064) AND
    >= 5 distinct UPNs targeted from the same source IP in 1 hour.

  Tuning:
    - Edit LegitRopcApps to suppress known-good ROPC clients before counting.
    - Allowlist IPs are stripped via ExcludeAllowlistedIPs_AADNI().
  MITRE ATT&CK: T1110.003 (Password Spraying), T1078 (Valid Accounts)
severity: High
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CredentialAccess
relevantTechniques:
  - T1110
  - T1078
query: |
  let LegitRopcApps = dynamic([
      "Microsoft Authentication Broker",
      "Microsoft Intune Company Portal",
      "Azure AD Connect",
      "Microsoft Office",
      "Microsoft Office Authentication Broker"
  ]);
  let SprayErrors = dynamic(["50126","50053","50056","50055","50064"]);
  AADNonInteractiveUserSignInLogs
  | invoke ExcludeAllowlistedIPs_AADNI()
  | where TimeGenerated > ago(1h)
  | where AuthenticationProtocol =~ "ropc"
  | where ResultType in (SprayErrors)
  | where AppDisplayName !in~ (LegitRopcApps)
  | summarize
      FailCount = count(),
      Users     = dcount(UserPrincipalName),
      UserList  = make_set(UserPrincipalName, 50),
      Apps      = make_set(AppDisplayName),
      Errors    = make_set(ResultType),
      FirstSeen = min(TimeGenerated),
      LastSeen  = max(TimeGenerated)
    by IPAddress, Location
  | where FailCount >= 15 and Users >= 5
  | order by FailCount desc
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
customDetails:
  FailCount: FailCount
  TargetedUsers: Users
  UserList: UserList
  ErrorCodes: Errors
alertDetailsOverride:
  alertDisplayNameFormat: "ROPC Credential Stuffing from {{IPAddress}} ({{Users}} users, {{FailCount}} failures)"
  alertDescriptionFormat: "Source IP {{IPAddress}} ({{Location}}) attempted {{FailCount}} ROPC password grants against {{Users}} distinct user accounts. ROPC is favoured by credential-stuffing tools as it bypasses MFA."
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AnyAlert
    groupByEntities:
      - IP
    groupByAlertDetails: []
    groupByCustomDetails: []

Explanation

This query is designed to detect suspicious activity that indicates credential-stuffing attacks using the ROPC (Resource Owner Password Credential) method. Here's a simple breakdown:

  1. Purpose: The query identifies patterns where a single IP address makes numerous failed login attempts using the ROPC protocol across multiple user accounts. This is often a sign of credential-stuffing attacks, which try to guess passwords by bypassing multi-factor authentication (MFA).

  2. Trigger Conditions: An alert is triggered if there are 15 or more failed login attempts (specific error codes) from the same IP address targeting at least 5 different user accounts within an hour.

  3. Exclusions: Known legitimate applications using ROPC are excluded from the analysis to reduce false positives. Additionally, IP addresses on an allowlist are ignored.

  4. Severity and Techniques: The alert is marked as high severity and relates to MITRE ATT&CK techniques for password spraying and using valid accounts.

  5. Data Source: The query uses logs from Azure Active Directory, specifically non-interactive user sign-in logs.

  6. Output: The query summarizes the number of failed attempts, distinct users targeted, and other details like the first and last time the activity was seen. It orders results by the number of failures.

  7. Alert Details: If the conditions are met, an alert is generated with details about the IP address, number of users targeted, and failure count. This alert can be grouped into incidents for further investigation.

Overall, this query helps security teams identify and respond to potential credential-stuffing attacks by monitoring failed login attempts using the ROPC protocol.

Details

David Alonso profile picture

David Alonso

Released: May 29, 2026

Tables

AADNonInteractiveUserSignInLogs

Keywords

AzureActiveDirectoryAADNonInteractiveUserSignInLogsIPAddressUserPrincipalNameAppDisplayNameResultTypeTimeGeneratedLocationMicrosoftAuthenticationBrokerMicrosoftIntuneCompanyPortalAzureADConnectMicrosoftOfficeMicrosoftOfficeAuthenticationBroker

Operators

letdynamicinvokeago=~in!in~summarizecountdcountmake_setminmaxbywhereorder bydesc

Actions