Adversaries may modify an Application ID URI to impersonate legitimate services or redirect users to malicious endpoints. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential unauthorized access or credential theft attempts.
KQL Query
AuditLogs
| where Category == "ApplicationManagement"
| where OperationName has_any ("Update Application", "Update Service principal")
| where TargetResources has "AppIdentifierUri"
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend mod_props = TargetResources[0].modifiedProperties
| extend TargetAppName = tostring(TargetResources[0].displayName)
| mv-expand mod_props
| where mod_props.displayName has "AppIdentifierUri"
| extend OldURI = tostring(mod_props.oldValue)
| extend NewURI = tostring(mod_props.newValue)
| extend UpdatedBy = iif(isnotempty(InitiatingAppName), InitiatingAppName, InitiatingUserPrincipalName)
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| project-reorder TimeGenerated, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingAadUserId, InitiatingUserPrincipalName, InitiatingIPAddress
id: 9fb2ee72-959f-4c2b-bc38-483affc539e4
name: Application ID URI Changed
description: |
'Detects changes to an Application ID URI.
Monitor these changes to make sure that they were authorized.
Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-applications#appid-uri-added-modified-or-removed'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- Persistence
- PrivilegeEscalation
relevantTechniques:
- T1078.004
tags:
- AADSecOpsGuide
query: |
AuditLogs
| where Category == "ApplicationManagement"
| where OperationName has_any ("Update Application", "Update Service principal")
| where TargetResources has "AppIdentifierUri"
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIPAddress = tostring(InitiatedBy.user.ipAddress)
| extend mod_props = TargetResources[0].modifiedProperties
| extend TargetAppName = tostring(TargetResources[0].displayName)
| mv-expand mod_props
| where mod_props.displayName has "AppIdentifierUri"
| extend OldURI = tostring(mod_props.oldValue)
| extend NewURI = tostring(mod_props.newValue)
| extend UpdatedBy = iif(isnotempty(InitiatingAppName), InitiatingAppName, InitiatingUserPrincipalName)
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| project-reorder TimeGenerated, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingAadUserId, InitiatingUserPrincipalName, InitiatingIPAddress
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: InitiatingUserPrincipalName
- identifier: Name
columnName: InitiatingAccountName
- identifier: UPNSuffix
columnName: InitiatingAccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: InitiatingAadUserId
- entityType: URL
fieldMappings:
- identifier: Url
columnName: OldURI
- entityType: URL
fieldMappings:
- identifier: Url
columnName: NewURI
- entityType: IP
fieldMappings:
- identifier: Address
columnName: InitiatingIPAddress
version: 1.1.1
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others" ]
| Sentinel Table | Notes |
|---|---|
AuditLogs | Ensure this data connector is enabled |
Scenario: A system administrator updates the Application ID URI for a service principal during routine maintenance using Azure CLI or Azure Portal.
Filter/Exclusion: Exclude events where the change is initiated by a known admin user (e.g., userPrincipalName matches an admin group) or when the change is logged via Azure Activity Log with a known maintenance task.
Scenario: A scheduled job runs to rotate the Application ID URI for a third-party integration tool like Salesforce or SAP using PowerShell or Azure Automation.
Filter/Exclusion: Exclude events where the change is associated with a known automation account or job name, or where the caller IP matches the IP range of the automation service.
Scenario: A developer manually updates the Application ID URI in Azure AD via the Azure Portal to test a new integration.
Filter/Exclusion: Exclude events where the userPrincipalName is associated with a developer role or where the change reason includes a test or development note.
Scenario: A security tool like Microsoft Defender for Identity or Azure Sentinel automatically updates the Application ID URI during a security policy sync.
Filter/Exclusion: Exclude events where the source system is a known security tool or where the change is initiated by a system service account (e.g., svc-azure-security).
Scenario: A DevOps pipeline, such as Azure DevOps or GitHub Actions, updates the Application ID URI as part of a CI/CD deployment.
Filter/Exclusion: Exclude events where the caller is a known CI/CD service (e.g., azure-pipelines@windows or github-actions@v3) or where the change is logged under a deployment pipeline context.