Query Details

HUNT 10 ADFS Risky Or Disabled User Active Auth 7d

Query

id: a1f00010-0010-4010-9010-adfs00000010
name: HUNT-10 ADFS Active Auth from Risky / Disabled Users (7d)
description: |
  Finds ADFS sign-ins (any ResultType) in the last 7 days for accounts that
  are currently disabled or flagged risky in Azure AD. Surfaces dormant or
  off-boarded identities that still receive auth traffic - high signal of
  persistence or credential reuse.
severity: High
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - ADFSSignInLogs
      - IdentityInfo
tactics:
  - Persistence
relevantTechniques:
  - T1078
query: |
  let RiskyOrDisabled = IdentityInfo
    | summarize arg_max(TimeGenerated, *) by AccountUPN
    | where (isnotempty(RiskLevel) and RiskLevel !~ "none")
         or IsAccountEnabled == false
    | project AccountUPN, RiskLevel, IsAccountEnabled, JobTitle, Department;
  ADFSSignInLogs
  | invoke ExcludeAllowlistedIPs()
  | where TimeGenerated > ago(7d)
  | join kind=inner (RiskyOrDisabled) on $left.UserPrincipalName == $right.AccountUPN
  | summarize
      Attempts        = count(),
      SuccessfulAuth  = countif(ResultType == 0),
      UniqueIPs       = dcount(IPAddress),
      IPs             = make_set(IPAddress, 25),
      Countries       = make_set(Location, 10),
      Apps            = make_set(AppDisplayName, 10),
      FirstSeen       = min(TimeGenerated),
      LastSeen        = max(TimeGenerated)
    by UserPrincipalName, RiskLevel, IsAccountEnabled
  | order by SuccessfulAuth desc, Attempts desc

Explanation

This query is designed to identify potentially suspicious activity related to ADFS (Active Directory Federation Services) sign-ins over the past seven days. It focuses on accounts that are either disabled or marked as risky in Azure Active Directory. Here's a simplified breakdown:

  1. Purpose: The query aims to detect sign-ins from accounts that are either disabled or flagged as risky, which could indicate unauthorized access or credential misuse.

  2. Data Sources: It uses data from Azure Active Directory, specifically the ADFSSignInLogs and IdentityInfo.

  3. Process:

    • Identify Risky or Disabled Accounts: It first identifies accounts that are either disabled or have a non-empty risk level (excluding "none").
    • Filter Sign-In Logs: It then filters ADFS sign-in logs from the last seven days, excluding any IPs that are on an allowlist.
    • Join Data: The query joins the filtered sign-in logs with the list of risky or disabled accounts.
    • Summarize Activity: For each account, it summarizes the number of sign-in attempts, successful authentications, unique IP addresses, and other details like countries, applications used, and the first and last time the account was seen.
  4. Output: The results are ordered by the number of successful authentications and total attempts, highlighting accounts with potentially unauthorized access.

  5. Severity and Tactics: The query is marked with high severity and is associated with the persistence tactic, specifically related to the technique T1078, which involves valid accounts being used for unauthorized purposes.

Details

David Alonso profile picture

David Alonso

Released: May 13, 2026

Tables

ADFSSignInLogsIdentityInfo

Keywords

ADFSAzureActiveDirectoryIdentityInfoAccountsUsersAuthTrafficPersistenceCredentialReuseRiskyDisabledSignInsLogsIPsCountriesApps

Operators

letsummarizearg_maxbywhereisnotemptyand!~or==projectinvokeExcludeAllowlistedIPs>agojoinkindoncountcountifdcountmake_setminmaxorder bydesc

Actions