Query Details

Suspicious SSPR Activity

Query

id: b23d4f94-39e8-4796-8759-42373c3697bd
name: Suspicious activity from unknown or risky IP addresses to Azure AD SSPR
description: |
  'Identifies IPs from which the user did not log on without a sign in risk in the last 14 days but now attempts to reset their password from (by Azure AD SSPR).'
severity: Medium
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - SigninLogs
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AADNonInteractiveUserSignInLogs
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - CredentialAccess
relevantTechniques:
  - T1078
  - T1110
query: |
  let SignInLookback = 14d;
  let SSPRLookback = 1d;
  let maxTimeBetweenSSPRandSigninInMinutes=7*24*60; // per Default max. difference is set to 7 Days
  AuditLogs
  | where TimeGenerated >= ago(SSPRLookback)
  | where LoggedByService == "Self-service Password Management" and ResultDescription == "User submitted their user ID"
  | extend AccountType = tostring(TargetResources[0].type), UserPrincipalName = tostring(TargetResources[0].userPrincipalName),
    TargetResourceName = tolower(tostring(TargetResources[0].displayName)), SSPRSourceIP = tostring(InitiatedBy.user.ipAddress)
  | project UserPrincipalName, SSPRSourceIP, SSPRAttemptTime = TimeGenerated, CorrelationId
  | join kind= leftouter (
      union AADNonInteractiveUserSignInLogs, SigninLogs
      | where datetime_add('minute',maxTimeBetweenSSPRandSigninInMinutes,TimeGenerated) >= ago(SignInLookback)
      | where ResultType == "0"
      | where RiskLevelAggregated == "none" or RiskLevelDuringSignIn == "none"
      | extend TrustedIP = tostring(IPAddress)
      | project UserPrincipalName, TrustedIP, SignInTime = TimeGenerated
  ) on UserPrincipalName
  | where SSPRAttemptTime > SignInTime
  | extend TimeDifferenceInMinutes= iif(SSPRSourceIP==TrustedIP,datetime_diff("Minute",SignInTime,SSPRAttemptTime), 0), Match=SSPRSourceIP==TrustedIP
  | where TimeDifferenceInMinutes >= -maxTimeBetweenSSPRandSigninInMinutes
  | summarize  SignInsFromTheSameIP=countif(Match), min(TimeDifferenceInMinutes) by UserPrincipalName, CorrelationId, SSPRAttemptTime, SSPRSourceIP   //SignInsFromTheSameIP=0 if no sign in came from the IP used for SSPR in the last maxTimeBetweenSSPRandSigninInMinutes
  | where SignInsFromTheSameIP == "0"
  | project timestamp = SSPRAttemptTime, AccountCustomEntity = UserPrincipalName, IPCustomEntity = SSPRSourceIP
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountCustomEntity
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPCustomEntity
version: 1.0.1
kind: Scheduled

Explanation

This query identifies suspicious activity where a user attempts to reset their password from an unknown or risky IP address in Azure AD SSPR. It looks for IPs from which the user did not log on without a sign-in risk in the last 14 days but now attempts to reset their password. The query checks for specific conditions and joins relevant logs to identify these suspicious activities. The severity of this activity is considered medium. The query is scheduled to run daily and looks back 14 days for data. It is relevant to the Initial Access and Credential Access tactics and maps to techniques T1078 and T1110. The query outputs the timestamp, user account, and IP address associated with the suspicious activity.

Details

Thomas Naunheim profile picture

Thomas Naunheim

Released: August 23, 2023

Tables

AuditLogs AADNonInteractiveUserSignInLogs SigninLogs

Keywords

Keywords:AzureADSSPR,IPs,SigninLogs,AADNonInteractiveUserSignInLogs,AuditLogs,Self-servicePasswordManagement,ResultDescription,TargetResources,AccountType,UserPrincipalName,TargetResourceName,SSPRSourceIP,InitiatedBy.user.ipAddress,CorrelationId,SignInTime,RiskLevelAggregated,RiskLevelDuringSignIn,TrustedIP,TimeDifferenceInMinutes,Match,SignInsFromTheSameIP,timestamp,AccountCustomEntity,IPCustomEntity,FullName,Address

Operators

whereextendprojectjoinuniondatetime_addagowhereextendprojectwherewhereextendprojectonwhereextendwheresummarizewhereproject

Actions