Adversaries may update credentials for dormant service principals to re-enable them and gain unauthorized access to Azure resources. SOC teams should proactively hunt for this behavior as it indicates potential credential reuse or persistence tactics by threat actors.
KQL Query
let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let lookback = endtime - 14d;
let sp_active_users = AADServicePrincipalSignInLogs
| where TimeGenerated between(lookback..starttime)
| where ResultType == 0
| summarize by ServicePrincipalId;
AuditLogs
| where TimeGenerated between(starttime..endtime)
// Looking for new creds added to an SP rather than MFA
| where OperationName in ("Add service principal credentials", "Update application - Certificates and secrets management")
| extend ServicePrincipalId = tostring(TargetResources[0].id)
| where ServicePrincipalId !in (sp_active_users)
| join kind=inner (SigninLogs | where TimeGenerated between(starttime..endtime) | where ResultType == 0) on ServicePrincipalId
| extend AccountCustomEntity = ServicePrincipalId, IPCustomEntity = IPAddress
id: e7cdfacc-d112-45c7-9e8f-2b52948d075c
name: Dormant Service Principal Update Creds and Logs In
description: |
'This query look for Service Principal accounts that are no longer used where a user has added or updated credentials for them before logging in with the Service Principal.
Threat actors may look to re-activate dormant accounts and use them for access in the hope that changes to such dormant accounts may go un-noticed.'
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
- AADServicePrincipalSignInLogs
tactics:
- Persistence
relevantTechniques:
- T1098
query: |
let starttime = todatetime('{{StartTimeISO}}');
let endtime = todatetime('{{EndTimeISO}}');
let lookback = endtime - 14d;
let sp_active_users = AADServicePrincipalSignInLogs
| where TimeGenerated between(lookback..starttime)
| where ResultType == 0
| summarize by ServicePrincipalId;
AuditLogs
| where TimeGenerated between(starttime..endtime)
// Looking for new creds added to an SP rather than MFA
| where OperationName in ("Add service principal credentials", "Update application - Certificates and secrets management")
| extend ServicePrincipalId = tostring(TargetResources[0].id)
| where ServicePrincipalId !in (sp_active_users)
| join kind=inner (SigninLogs | where TimeGenerated between(starttime..endtime) | where ResultType == 0) on ServicePrincipalId
| extend AccountCustomEntity = ServicePrincipalId, IPCustomEntity = IPAddress
entityMappings:
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: AccountCustomEntity
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPCustomEntity
| Sentinel Table | Notes |
|---|---|
AuditLogs | Ensure this data connector is enabled |
SigninLogs | Ensure this data connector is enabled |
Scenario: Scheduled Job Credential Rotation
Description: A system administrator updates the credentials for a Service Principal used by a scheduled job (e.g., Azure DevOps pipeline or SQL Agent job) as part of routine maintenance.
Filter/Exclusion: where AccountName not in ('<ScheduledJobServicePrincipal>') or check for CredentialChangeReason = 'ScheduledRotation'
Scenario: Azure AD Password Sync Configuration Update
Description: An admin updates the password for a Service Principal used in Azure AD password sync (e.g., Azure AD Connect) to ensure synchronization continues without interruption.
Filter/Exclusion: where ServicePrincipalName != 'AzureADPasswordSync' or check for OperationType = 'PasswordSyncConfigUpdate'
Scenario: Temporary Service Principal for Debugging
Description: A developer creates a temporary Service Principal with temporary credentials to debug an application, then logs in using those credentials.
Filter/Exclusion: where ServicePrincipalName contains 'Debug' or 'Temp' or check for CreatedBy = '<DevOpsUser>'
Scenario: Credential Rotation via Azure CLI or PowerShell
Description: An admin uses Azure CLI or PowerShell to rotate credentials for a Service Principal that is used by an automation tool (e.g., Azure DevOps, Terraform).
Filter/Exclusion: where Caller not in ('AzureCLI', 'PowerShell') or check for Command = 'az ad sp credential reset'
Scenario: Service Principal Used for Backup Tools
Description: A backup tool (e.g., Veeam, Commvault) uses a Service Principal with updated credentials to access cloud storage or databases.
Filter/Exclusion: where ServicePrincipalName contains 'Backup' or 'Veeam' or check for `ToolName = ‘Veeam