A user successfully logs into one application and fails to log into another within one minute, potentially indicating an adversary attempting to access restricted applications through credential reuse or brute force. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential credential compromise or unauthorized access attempts to sensitive applications.
KQL Query
let logonDiff = 1m;
let Success = SigninLogs
| where ResultType == "0"
| where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online", "Office 365 SharePoint Online")
| project SuccessLogonTime = TimeGenerated, UserPrincipalName, IPAddress , SuccessAppDisplayName = AppDisplayName;
let Fail = SigninLogs
| where ResultType !in ("0", "50140")
| where ResultDescription !~ "Other"
| where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online", "Office 365 SharePoint Online")
| project FailedLogonTime = TimeGenerated, UserPrincipalName, IPAddress , FailedAppDisplayName = AppDisplayName, ResultType, ResultDescription;
let InitialDataSet =
Success | join kind= inner (
Fail
) on UserPrincipalName, IPAddress
| where isnotempty(FailedAppDisplayName)
| where SuccessLogonTime < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and SuccessAppDisplayName != FailedAppDisplayName;
let InitialHits =
InitialDataSet
| summarize FailedLogonTime = min(FailedLogonTime), SuccessLogonTime = min(SuccessLogonTime)
by UserPrincipalName, SuccessAppDisplayName, FailedAppDisplayName, IPAddress, ResultType, ResultDescription;
// Only take hits where there is 5 or less distinct AppDisplayNames on the success side as this limits highly active applications where failures occur more regularly
let Distribution =
InitialDataSet
| summarize count_SuccessAppDisplayName = count() by SuccessAppDisplayName, ResultType
| where count_SuccessAppDisplayName <= 5;
InitialHits | join (
Distribution
) on SuccessAppDisplayName, ResultType
| project UserPrincipalName, SuccessLogonTime, IPAddress, SuccessAppDisplayName, FailedLogonTime, FailedAppDisplayName, ResultType, ResultDescription
| extend timestamp = SuccessLogonTime, AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress
id: bc17381e-07ee-48a2-931f-06a3d9e149c9
name: Same User - Successful logon for a given App and failure on another App within 1m and low distribution
description: |
'This identifies when a user account successfully logs onto a given App and within 1 minute fails to logon to a different App.
This may indicate a malicious attempt at accessing disallowed Apps for discovery or potential lateral movement'
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
tactics:
- Discovery
- LateralMovement
relevantTechniques:
- T1087
- T1021
query: |
let logonDiff = 1m;
let Success = SigninLogs
| where ResultType == "0"
| where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online", "Office 365 SharePoint Online")
| project SuccessLogonTime = TimeGenerated, UserPrincipalName, IPAddress , SuccessAppDisplayName = AppDisplayName;
let Fail = SigninLogs
| where ResultType !in ("0", "50140")
| where ResultDescription !~ "Other"
| where AppDisplayName !in ("Office 365 Exchange Online", "Skype for Business Online", "Office 365 SharePoint Online")
| project FailedLogonTime = TimeGenerated, UserPrincipalName, IPAddress , FailedAppDisplayName = AppDisplayName, ResultType, ResultDescription;
let InitialDataSet =
Success | join kind= inner (
Fail
) on UserPrincipalName, IPAddress
| where isnotempty(FailedAppDisplayName)
| where SuccessLogonTime < FailedLogonTime and FailedLogonTime - SuccessLogonTime <= logonDiff and SuccessAppDisplayName != FailedAppDisplayName;
let InitialHits =
InitialDataSet
| summarize FailedLogonTime = min(FailedLogonTime), SuccessLogonTime = min(SuccessLogonTime)
by UserPrincipalName, SuccessAppDisplayName, FailedAppDisplayName, IPAddress, ResultType, ResultDescription;
// Only take hits where there is 5 or less distinct AppDisplayNames on the success side as this limits highly active applications where failures occur more regularly
let Distribution =
InitialDataSet
| summarize count_SuccessAppDisplayName = count() by SuccessAppDisplayName, ResultType
| where count_SuccessAppDisplayName <= 5;
InitialHits | join (
Distribution
) on SuccessAppDisplayName, ResultType
| project UserPrincipalName, SuccessLogonTime, IPAddress, SuccessAppDisplayName, FailedLogonTime, FailedAppDisplayName, ResultType, ResultDescription
| extend timestamp = SuccessLogonTime, AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: AccountCustomEntity
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
version: 1.0.1
metadata:
source:
kind: Community
author:
name: Shain
support:
tier: Community
categories:
domains: [ "Security - Other", "Identity" ]
| Sentinel Table | Notes |
|---|---|
SigninLogs | Ensure this data connector is enabled |
Scenario: A user successfully logs into a legitimate application (e.g., Microsoft Exchange Online) and within 1 minute fails to log into another application (e.g., Azure DevOps) due to incorrect credentials.
Filter/Exclusion: Exclude logon failures for Azure DevOps when the user is known to be attempting to access it during scheduled maintenance or after a password reset.
Scenario: A system administrator successfully logs into a monitoring tool (e.g., SolarWinds) and within 1 minute fails to log into a configuration management tool (e.g., Ansible Tower) due to a temporary network outage.
Filter/Exclusion: Exclude logon failures for Ansible Tower if the event is associated with a known network maintenance window or scheduled job execution.
Scenario: A user successfully logs into a business intelligence tool (e.g., Power BI) and within 1 minute fails to log into a file server (e.g., Windows File Server) due to a misconfigured password.
Filter/Exclusion: Exclude logon failures for the file server if the user is performing a password change or if the event is related to a password policy enforcement.
Scenario: A user successfully logs into a cloud storage service (e.g., OneDrive) and within 1 minute fails to log into a backup application (e.g., Veeam Backup & Replication) due to a temporary authentication token expiration.
Filter/Exclusion: Exclude logon failures for Veeam if the event is associated with a scheduled backup job or token refresh process.
Scenario: A user successfully logs into a helpdesk application (e.g., ServiceNow) and within 1 minute fails to log into a ticketing system (e.g., Zendesk) due to a misconfigured SSO token.
Filter/Exclusion: Exclude logon failures for Zendesk if the event is related to a user attempting