Query Details

18 SIGNIN Legacy Auth First Appearance

Query

id: b8c9d0e1-f2a3-4b4c-5d6e-7f8a9b0c1d2e
name: "SigninLogs — Legacy Auth First Appearance for Modern-Only Account"
version: 1.0.0
kind: Scheduled
description: |
  Detects accounts that used exclusively modern auth for the past 14 days but then suddenly appear using legacy protocols (IMAP4, POP3, SMTP Auth, Exchange ActiveSync). Legacy auth bypasses Conditional Access and MFA — this is a high-fidelity signal of credential theft or policy evasion. MITRE ATT&CK: T1550 (Use Alternate Auth Material), T1078 (Valid Accounts).
severity: High
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - SigninLogs
queryFrequency: PT6H
queryPeriod: P14D
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
  - CredentialAccess
relevantTechniques:
  - T1550
  - T1078
query: |

    // ---- Network Allowlist (exclude trusted IPs / CIDR / ranges) --------------
    let _allow = materialize(union isfuzzy=true (print R="" | take 0), (_GetWatchlist('NetworkAllowlist') | project R = tostring(IPOrRange)) | where isnotempty(R));
    let _allowCIDR  = toscalar(_allow | where not(R matches regex @'^\d+\.\d+\.\d+\.\d+-\d+\.\d+\.\d+\.\d+$') | extend R = iff(R has '/', R, strcat(R, '/32')) | summarize make_list(R));
    let _allowRange = toscalar(_allow | where R matches regex @'^\d+\.\d+\.\d+\.\d+-\d+\.\d+\.\d+\.\d+$' | summarize make_list(R));
    let _ExcludeAllowlistedIPs = (T:(IPAddress:string)) {
        T
        | extend IPAddress = tostring(IPAddress)
        | where array_length(_allowCIDR) == 0 or isnull(ipv4_is_in_any_range(IPAddress, _allowCIDR)) or not(ipv4_is_in_any_range(IPAddress, _allowCIDR))
        | mv-apply _r = _allowRange to typeof(string) on (
            extend _lo = tostring(split(_r,'-')[0]), _hi = tostring(split(_r,'-')[1])
            | extend _inRange = ipv4_compare(IPAddress, _lo) >= 0 and ipv4_compare(IPAddress, _hi) <= 0
            | summarize _anyInRange = max(toint(_inRange)))
        | where isnull(_anyInRange) or _anyInRange == 0
        | project-away _anyInRange
    };
    // ---------------------------------------------------------------------------
    let lookback       = 1d;
    let baselinePeriod = 14d;
    let legacyClients  = dynamic([
        "Exchange ActiveSync", "IMAP4", "POP3",
        "Authenticated SMTP", "MAPI over HTTP",
        "Other clients; IMAP", "Other clients; POP",
        "Other clients; SMTP"
    ]);
    let ModernOnlyAccounts =
        SigninLogs
        | invoke _ExcludeAllowlistedIPs()
        | where TimeGenerated between (ago(baselinePeriod) .. ago(lookback))
        | where ResultType == "0"
        | summarize LegacyCount = countif(ClientAppUsed has_any (legacyClients))
            by UserPrincipalName
        | where LegacyCount == 0
        | project UserPrincipalName;
    SigninLogs
    | invoke _ExcludeAllowlistedIPs()
    | where TimeGenerated > ago(lookback)
    | where ResultType == "0"
    | where ClientAppUsed has_any (legacyClients)
    | where isnotempty(UserPrincipalName)
    | join kind=inner ModernOnlyAccounts on UserPrincipalName
    | project
        TimeGenerated, UserPrincipalName,
        IPAddress, Location,
        ClientAppUsed, AppDisplayName,
        RiskLevelDuringSignIn, ConditionalAccessStatus
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: UserPrincipalName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
customDetails:
  ClientAppUsed: ClientAppUsed
  AppDisplayName: AppDisplayName
alertDetailsOverride:
  alertDisplayNameFormat: "Legacy Auth First Appearance — {{UserPrincipalName}} using {{ClientAppUsed}}"
  alertDescriptionFormat: "Account {{UserPrincipalName}} authenticated via {{ClientAppUsed}} from {{IPAddress}} — account exclusively used modern auth in the prior 14 days. Possible CA bypass."
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT6H
    matchingMethod: AllEntities
    groupByEntities:
  - Account
  - IP



Explanation

This query is designed to detect suspicious activity in user accounts within an organization. Specifically, it identifies accounts that have been using only modern authentication methods for the past 14 days but suddenly start using legacy authentication protocols like IMAP4, POP3, SMTP Auth, or Exchange ActiveSync. These legacy protocols can bypass security measures such as Conditional Access and Multi-Factor Authentication (MFA), making them potential indicators of credential theft or attempts to evade security policies.

Here's a simplified breakdown of the query:

  1. Network Allowlist: The query first defines a list of trusted IP addresses or ranges to exclude from the analysis, ensuring that only untrusted or suspicious IPs are considered.

  2. Baseline and Lookback Periods: It sets a baseline period of 14 days to establish which accounts have been using only modern authentication methods. The lookback period is set to 1 day to check for any recent use of legacy protocols.

  3. Identify Modern-Only Accounts: The query identifies accounts that have not used any legacy authentication methods during the baseline period.

  4. Detect Legacy Auth Usage: It then checks if any of these modern-only accounts have used legacy authentication methods in the past day.

  5. Alert Generation: If such activity is detected, an alert is generated with details like the time of the event, user account, IP address, location, client app used, and risk level. This alert is considered high severity due to the potential security risk.

  6. Incident Management: The query is configured to create incidents for detected activities, grouping them by account and IP address if multiple related events occur.

Overall, this query helps security teams identify potential security breaches or policy violations by monitoring for unexpected changes in authentication behavior.

Details

David Alonso profile picture

David Alonso

Released: April 20, 2026

Tables

SigninLogs

Keywords

SigninLogsAzureActiveDirectoryUserPrincipalNameIPAddressLocationClientAppUsedAppDisplayNameRiskLevelDuringSignInConditionalAccessStatusAccountIP

Operators

letmaterializeunionisfuzzyprinttakeprojecttostringwhereisnotemptymatchesregextoscalarextendiffhasstrcatsummarizemake_listnotarray_lengthisnullipv4_is_in_any_rangemv-applytotypeofonsplitipv4_comparemaxtointproject-awaydynamicbetweenagocountifhas_anyjoinkindinnerproject

Actions