Oauth Trackeventsonserviceprincipals
KQL detection rule by reprise99 · MIT
Tracks privileged post creation events on your Azure AD service principals, such as secrets being generated, permissions being added or an admin consenting.
//Tracks privileged post creation events on your Azure AD service principals, such as secrets being generated, permissions being added or an admin consenting.
//Data connector required for this query - Azure Active Directory - Audit Logs
//Events are then summarized by operation and time. Add a specific Application ID to track events for that one app.
let timeframe=60d;
let AppAdded=
AuditLogs
| where TimeGenerated > ago (timeframe)
| where OperationName == "Add service principal"
| extend AppId = tostring(AdditionalDetails[1].value)
| extend ServicePrincipalId = tostring(TargetResources[0].id)
// Optionally add a specific Application ID
//| where AppId == "id"
| extend AppName = tostring(TargetResources[0].displayName)
| where isnotempty(AppId)
| project TimeGenerated, OperationName, AppId, AppName, ServicePrincipalId;
let AppSecretAdded=
AuditLogs
| where OperationName contains 'Update application – Certificates and secrets management'
| extend AppId = tostring(AdditionalDetails[1].value)
| project TimeGenerated, AppId, OperationName
| join kind=inner AppAdded on AppId
| project TimeGenerated, OperationName, AppId, AppName;
let AppApplicationAccess=
AuditLogs
| where OperationName == "Add app role assignment to service principal"
| extend AppId = tostring(TargetResources[1].displayName)
| project TimeGenerated, AppId, OperationName
| join kind=inner AppAdded on AppId
| project TimeGenerated, OperationName, AppId, AppName;
let AppDelegatedAccess=
AuditLogs
| where OperationName == "Add delegated permission grant"
| extend ServicePrincipalId = tostring(TargetResources[1].id)
| project TimeGenerated, ServicePrincipalId, OperationName
| join kind=inner AppAdded on ServicePrincipalId
| project TimeGenerated, OperationName, AppId, AppName;
let AppConsentGiven=
AuditLogs
| where OperationName == "Consent to application"
| extend AppId = tostring(AdditionalDetails[1].value)
| project TimeGenerated, AppId, OperationName
| join kind=inner AppAdded on AppId
| project TimeGenerated, OperationName, AppId, AppName;
let AppDeleted=
AuditLogs
| where OperationName == "Delete application"
| extend AppId = tostring(AdditionalDetails[1].value)
| project TimeGenerated, AppId, OperationName
| join kind=inner AppAdded on AppId
| project TimeGenerated, OperationName, AppId, AppName;
AppAdded
| union
AppSecretAdded,
AppApplicationAccess,
AppConsentGiven,
AppDelegatedAccess,
AppDeleted
| sort by TimeGenerated asc
| summarize
AppOperations=(make_list(OperationName)),
AppOperationTime=(make_list(TimeGenerated))
by AppId, AppName