Query Details

26 ROPC New Country Or ASN

Query

id: c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f
name: ROPC Sign-In from New Country or ASN for User
version: 1.0.0
kind: Scheduled
description: |
  Detects a successful ROPC sign-in whose (Country, ASN) pair has not been observed for
  that user in the prior 30 days of SigninLogs or AADNonInteractiveUserSignInLogs.
  Because ROPC bypasses MFA / Conditional Access, a first-seen-location signal is one of
  the few remaining indicators that a stolen credential is being replayed from a new
  attacker location.

  Trigger: any successful ROPC sign-in (ResultType == 0) where the {UPN, Location, ASN}
  combination is unseen in the last 30 days.

  Tuning:
    - LegitRopcApps suppresses known-good ROPC clients.
    - Allowlist IPs are stripped via ExcludeAllowlistedIPs_AADNI().
  MITRE ATT&CK: T1078 (Valid Accounts), T1550 (Use Alternate Auth Material)
severity: Medium
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
      - SigninLogs
queryFrequency: 1h
queryPeriod: 30d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - CredentialAccess
relevantTechniques:
  - T1078
  - T1550
query: |
  let LegitRopcApps = dynamic([
      "Microsoft Authentication Broker",
      "Microsoft Intune Company Portal",
      "Azure AD Connect",
      "Microsoft Office",
      "Microsoft Office Authentication Broker"
  ]);
  let Lookback = 30d;
  let Window   = 1h;
  let Baseline =
      union isfuzzy=true
          (SigninLogs
              | where TimeGenerated between (ago(Lookback) .. ago(Window))),
          (AADNonInteractiveUserSignInLogs
              | where TimeGenerated between (ago(Lookback) .. ago(Window)))
      | where ResultType == 0
      | extend Upn = tolower(UserPrincipalName),
               Pair = strcat(Location, "|", tostring(AutonomousSystemNumber))
      | summarize KnownPairs = make_set(Pair) by Upn;
  AADNonInteractiveUserSignInLogs
  | invoke ExcludeAllowlistedIPs_AADNI()
  | where TimeGenerated > ago(Window)
  | where AuthenticationProtocol =~ "ropc"
  | where ResultType == 0
  | where AppDisplayName !in~ (LegitRopcApps)
  | extend Upn = tolower(UserPrincipalName),
           Pair = strcat(Location, "|", tostring(AutonomousSystemNumber))
  | join kind=leftouter Baseline on Upn
  | where isnull(KnownPairs) or not(set_has_element(KnownPairs, Pair))
  | summarize
      Count     = count(),
      IPs       = make_set(IPAddress),
      Countries = make_set(Location),
      ASNs      = make_set(AutonomousSystemNumber),
      Apps      = make_set(AppDisplayName),
      FirstSeen = min(TimeGenerated),
      LastSeen  = max(TimeGenerated)
    by UserPrincipalName
  | extend IPAddress = tostring(IPs[0])
  | order by Count desc
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: UserPrincipalName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
customDetails:
  SignInCount: Count
  Countries: Countries
  ASNs: ASNs
  Apps: Apps
alertDetailsOverride:
  alertDisplayNameFormat: "ROPC from new country/ASN for {{UserPrincipalName}}"
  alertDescriptionFormat: "User {{UserPrincipalName}} authenticated via ROPC from a country/ASN combination ({{Countries}}, ASN {{ASNs}}) not seen in the prior 30 days. ROPC bypasses MFA - treat as suspected credential replay."
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AnyAlert
    groupByEntities:
      - Account
    groupByAlertDetails: []
    groupByCustomDetails: []

Explanation

This query is designed to detect potentially suspicious sign-in activities in an organization's Azure Active Directory. Here's a simplified explanation:

  1. Purpose: The query identifies successful sign-ins using the Resource Owner Password Credentials (ROPC) method from a new country or Autonomous System Number (ASN) for a user. ROPC is a method that bypasses Multi-Factor Authentication (MFA), making it a potential security risk if credentials are stolen and used from a new location.

  2. How it Works:

    • It checks sign-in logs from the past 30 days to see if the combination of user, country, and ASN has been seen before.
    • If a new combination is detected, it raises an alert, as this could indicate that a user's credentials are being used from a new, potentially unauthorized location.
  3. Exclusions and Filters:

    • Known legitimate ROPC applications are excluded to reduce false positives.
    • IP addresses on an allowlist are also excluded.
    • The query focuses on successful sign-ins (ResultType == 0).
  4. Alert Details:

    • If a new combination is found, it summarizes the number of occurrences, the IP addresses, countries, ASNs, and applications involved.
    • It also notes the first and last time this activity was seen.
  5. Severity and Response:

    • The severity of the alert is set to "Medium."
    • An incident is created for further investigation, and alerts are grouped by user account to manage related activities together.
  6. MITRE ATT&CK Techniques:

    • The query is associated with techniques T1078 (Valid Accounts) and T1550 (Use Alternate Authentication Material), indicating it relates to credential access and misuse.

In essence, this query helps security teams monitor for unusual sign-in patterns that could suggest compromised credentials being used from new locations, allowing them to take action to secure the affected accounts.

Details

David Alonso profile picture

David Alonso

Released: May 29, 2026

Tables

AADNonInteractiveUserSignInLogsSigninLogs

Keywords

UserDevicesIntuneAzureActiveDirectorySigninLogsAADNonInteractiveUserSignInLogsAccountIPAddressLocationAutonomousSystemNumberAppDisplayNameUserPrincipalName

Operators

letdynamicagounionisfuzzybetweenwhereextendtolowerstrcattostringsummarizemake_setinvokejoinkindleftouterisnullnotset_has_elementcountminmaxbyorderdesctostringin!in=~

Actions