Adversaries may leverage federated identity credentials to compromise Entra ID service principals and gain unauthorized access to cloud resources without requiring traditional secrets. SOC teams should proactively hunt for this behavior to detect potential abuse of workload identity federation and prevent unauthorized access to sensitive systems.
KQL Query
let timeframe = 1d;
AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName in~ ("Update service principal")
| where Result =~ "success"
| mv-expand ModProp = TargetResources[0].modifiedProperties
| where tostring(ModProp.displayName) =~ "FederatedIdentityCredentials"
| extend OldCreds = tostring(ModProp.oldValue)
| extend NewCreds = tostring(ModProp.newValue)
| extend TargetSpName = tostring(TargetResources[0].displayName)
| extend TargetSpId = tostring(TargetResources[0].id)
| 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(ActorUpn has "@",
tostring(split(ActorUpn, "@")[0]), Actor)
| extend AccountUPNSuffix = iff(ActorUpn has "@",
tostring(split(ActorUpn, "@")[1]), "")
| project
TimeGenerated,
TargetSpName,
TargetSpId,
OldCreds,
NewCreds,
Actor,
AccountName,
AccountUPNSuffix,
ActorIp,
CorrelationId
| sort by TimeGenerated desc
id: 2a7c50a9-5172-4ea3-8a59-b89e8117fc2c
name: Federated identity credential added to Entra ID service principal
description: Identifies federated identity credential additions to Entra ID service principals. Workload identity federation allows external OIDC workloads to authenticate as the SP without secrets, which if abused enables supply chain or CI/CD pipeline compromise.
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
tactics:
- Persistence
relevantTechniques:
- T1098.001
query: |
let timeframe = 1d;
AuditLogs
| where TimeGenerated >= ago(timeframe)
| where OperationName in~ ("Update service principal")
| where Result =~ "success"
| mv-expand ModProp = TargetResources[0].modifiedProperties
| where tostring(ModProp.displayName) =~ "FederatedIdentityCredentials"
| extend OldCreds = tostring(ModProp.oldValue)
| extend NewCreds = tostring(ModProp.newValue)
| extend TargetSpName = tostring(TargetResources[0].displayName)
| extend TargetSpId = tostring(TargetResources[0].id)
| 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(ActorUpn has "@",
tostring(split(ActorUpn, "@")[0]), Actor)
| extend AccountUPNSuffix = iff(ActorUpn has "@",
tostring(split(ActorUpn, "@")[1]), "")
| project
TimeGenerated,
TargetSpName,
TargetSpId,
OldCreds,
NewCreds,
Actor,
AccountName,
AccountUPNSuffix,
ActorIp,
CorrelationId
| sort by TimeGenerated desc
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: Actor
- 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" ]
| Sentinel Table | Notes |
|---|---|
AuditLogs | Ensure this data connector is enabled |
Scenario: A DevOps team deploys a CI/CD pipeline that programmatically adds federated identity credentials to Entra ID service principals as part of infrastructure provisioning.
Filter/Exclusion: Check for userAgent containing “Azure CLI” or “Azure DevOps” and filter by service principal names associated with CI/CD tools like Azure DevOps, Jenkins, or GitHub Actions.
Scenario: An administrator manually configures a federated identity credential for a service principal to enable secure access to a cloud service, such as Azure Kubernetes Service (AKS) or Azure SQL.
Filter/Exclusion: Include userPrincipalName matching the admin’s account and check for operationName like “Add Federated Identity Credential” or “Update Service Principal”.
Scenario: A scheduled job runs to rotate credentials for a service principal using Azure Automation or Azure PowerShell, which may trigger the rule during credential update.
Filter/Exclusion: Filter by caller or callerIpAddress associated with Azure Automation or Azure PowerShell, and check for operationName indicating credential rotation.
Scenario: A third-party SaaS application registers a service principal and adds a federated identity credential as part of its integration with Azure, such as Salesforce or ServiceNow.
Filter/Exclusion: Use servicePrincipalNames or appId that match known third-party SaaS applications, and filter by caller associated with the SaaS provider’s integration tools.
Scenario: A security tool or SIEM solution (e.g., Azure Sentinel, Splunk, or IBM QRadar) uses a service principal to authenticate and send logs to Azure, which may trigger the rule when the credential is added.
Filter/Exclusion: Filter by caller or callerIpAddress associated with the SIEM tool, and check for operationName related to log ingestion or monitoring.