← Back to SOC feed Coverage →

Service principal credential addition followed by immediate sign-in

kql MEDIUM Azure-Sentinel
T1098.001T1528
AuditLogs
credential-thefthuntingmicrosoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-06-03T11:00:00Z · Confidence: medium

Hunt Hypothesis

A threat hunter should investigate service principal credential additions followed by immediate sign-ins, as this behavior aligns with post-compromise staging tactics used by adversaries to maintain persistence and access. Proactively hunting for this pattern in Azure Sentinel can help identify potential lateral movement or unauthorized access attempts in the environment.

KQL Query

let timeframe = 1d;
let correlationWindow = 30m;
let CredAdded =
    AuditLogs
    | where TimeGenerated >= ago(timeframe)
    | where OperationName in~ (
          "Add service principal credentials"
      )
    | where Result =~ "success"
    | project
        CredAddedTime      = TimeGenerated,
        SpId               = tostring(TargetResources[0].id),
        SpName             = tostring(TargetResources[0].displayName),
        ActorUpn           = tostring(InitiatedBy.user.userPrincipalName),
        ActorApp           = tostring(InitiatedBy.app.displayName),
        AuditCorrelationId = CorrelationId;
AADServicePrincipalSignInLogs
| where TimeGenerated >= ago(timeframe)
| where ResultType == 0
| join kind=inner CredAdded on $left.ServicePrincipalId == $right.SpId
| where TimeGenerated between (CredAddedTime .. (CredAddedTime + correlationWindow))
| extend Actor = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
| project
    TimeGenerated,
    ServicePrincipalId,
    ServicePrincipalName = SpName,
    AppId,
    IPAddress,
    Location,
    ResourceDisplayName,
    CredAddedTime,
    Actor,
    AuditCorrelationId,
    SignInCorrelationId  = CorrelationId
| sort by TimeGenerated desc

Analytic Rule Definition

id: 02a6931e-0a49-4f78-b535-1947273c5384
name: Service principal credential addition followed by immediate sign-in
description: |
  Identifies service principal sign-ins occurring within 30 minutes of a credential
  addition to the same service principal. The tight correlation is consistent with
  post-compromise staging where credentials are added and used immediately.
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
      - AADServicePrincipalSignInLogs
tactics:
  - Persistence
  - CredentialAccess
relevantTechniques:
  - T1098.001
  - T1528
query: |
  let timeframe = 1d;
  let correlationWindow = 30m;
  let CredAdded =
      AuditLogs
      | where TimeGenerated >= ago(timeframe)
      | where OperationName in~ (
            "Add service principal credentials"
        )
      | where Result =~ "success"
      | project
          CredAddedTime      = TimeGenerated,
          SpId               = tostring(TargetResources[0].id),
          SpName             = tostring(TargetResources[0].displayName),
          ActorUpn           = tostring(InitiatedBy.user.userPrincipalName),
          ActorApp           = tostring(InitiatedBy.app.displayName),
          AuditCorrelationId = CorrelationId;
  AADServicePrincipalSignInLogs
  | where TimeGenerated >= ago(timeframe)
  | where ResultType == 0
  | join kind=inner CredAdded on $left.ServicePrincipalId == $right.SpId
  | where TimeGenerated between (CredAddedTime .. (CredAddedTime + correlationWindow))
  | extend Actor = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
  | project
      TimeGenerated,
      ServicePrincipalId,
      ServicePrincipalName = SpName,
      AppId,
      IPAddress,
      Location,
      ResourceDisplayName,
      CredAddedTime,
      Actor,
      AuditCorrelationId,
      SignInCorrelationId  = CorrelationId
  | sort by TimeGenerated desc
entityMappings:
  - entityType: CloudApplication
    fieldMappings:
      - identifier: Name
        columnName: ServicePrincipalName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
version: 1.0.0
metadata:
    source:
        kind: Community
    author:
        name: descambiado
    support:
        tier: Community
    categories:
        domains: [ "Security - Threat Protection", "Identity" ]

Required Data Sources

Sentinel TableNotes
AuditLogsEnsure this data connector is enabled

MITRE ATT&CK Context

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Hunting Queries/MultipleDataSources/ServicePrincipalCredentialAddedThenSignedIn.yaml