← Back to SOC feed Coverage →

New owner added to Entra ID service principal

kql MEDIUM Azure-Sentinel
T1098.001
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-05-29T11:00:00Z · Confidence: medium

Hunt Hypothesis

A threat actor may add themselves as an owner to an Entra ID service principal to gain full credential management privileges and deploy malicious credentials. SOC teams should proactively hunt for this behavior to detect potential credential compromise and unauthorized access in their Azure Sentinel environment.

KQL Query

let timeframe = 1d;
AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName =~ "Add owner to service principal"
| where Result =~ "success"
| mv-apply T = TargetResources on (
      summarize
          TargetSpName = take_anyif(tostring(T.displayName), tostring(T.type) =~ "ServicePrincipal"),
          TargetSpId   = take_anyif(tostring(T.id), tostring(T.type) =~ "ServicePrincipal"),
          NewOwnerUpn  = take_anyif(tostring(T.userPrincipalName), tostring(T.type) =~ "User"),
          NewOwnerId   = take_anyif(tostring(T.id), tostring(T.type) =~ "User")
  )
| extend ActorUpn     = tostring(InitiatedBy.user.userPrincipalName)
| extend ActorApp     = tostring(InitiatedBy.app.displayName)
| extend Actor        = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
| extend ActorIp      = iff(
      isnotempty(tostring(InitiatedBy.user.ipAddress)),
      tostring(InitiatedBy.user.ipAddress),
      tostring(InitiatedBy.app.ipAddress))
| extend AccountName      = iff(NewOwnerUpn has "@",
      tostring(split(NewOwnerUpn, "@")[0]), NewOwnerUpn)
| extend AccountUPNSuffix = iff(NewOwnerUpn has "@",
      tostring(split(NewOwnerUpn, "@")[1]), "")
| project
    TimeGenerated,
    TargetSpName,
    TargetSpId,
    NewOwnerUpn,
    AccountName,
    AccountUPNSuffix,
    NewOwnerId,
    Actor,
    ActorIp,
    CorrelationId
| sort by TimeGenerated desc

Analytic Rule Definition

id: a15c8f25-9e6c-4d1f-b685-b5113fe58307
name: New owner added to Entra ID service principal
description: Identifies additions of new owners to Entra ID service principals. SP ownership grants full credential management capability; an attacker who adds themselves as owner can subsequently add credentials and authenticate as the SP.
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
tactics:
  - Persistence
relevantTechniques:
  - T1098.001
query: |
  let timeframe = 1d;
  AuditLogs
  | where TimeGenerated >= ago(timeframe)
  | where OperationName =~ "Add owner to service principal"
  | where Result =~ "success"
  | mv-apply T = TargetResources on (
        summarize
            TargetSpName = take_anyif(tostring(T.displayName), tostring(T.type) =~ "ServicePrincipal"),
            TargetSpId   = take_anyif(tostring(T.id), tostring(T.type) =~ "ServicePrincipal"),
            NewOwnerUpn  = take_anyif(tostring(T.userPrincipalName), tostring(T.type) =~ "User"),
            NewOwnerId   = take_anyif(tostring(T.id), tostring(T.type) =~ "User")
    )
  | extend ActorUpn     = tostring(InitiatedBy.user.userPrincipalName)
  | extend ActorApp     = tostring(InitiatedBy.app.displayName)
  | extend Actor        = iff(isnotempty(ActorUpn), ActorUpn, ActorApp)
  | extend ActorIp      = iff(
        isnotempty(tostring(InitiatedBy.user.ipAddress)),
        tostring(InitiatedBy.user.ipAddress),
        tostring(InitiatedBy.app.ipAddress))
  | extend AccountName      = iff(NewOwnerUpn has "@",
        tostring(split(NewOwnerUpn, "@")[0]), NewOwnerUpn)
  | extend AccountUPNSuffix = iff(NewOwnerUpn has "@",
        tostring(split(NewOwnerUpn, "@")[1]), "")
  | project
      TimeGenerated,
      TargetSpName,
      TargetSpId,
      NewOwnerUpn,
      AccountName,
      AccountUPNSuffix,
      NewOwnerId,
      Actor,
      ActorIp,
      CorrelationId
  | sort by TimeGenerated desc
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: NewOwnerUpn
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountUPNSuffix
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: ActorIp
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/AuditLogs/ServicePrincipalOwnerAdded.yaml