↳ Source GitHubRègle analytiqueMedium

Credential added after admin consented to Application

Description

'This query will identify instances where Service Principal credentials were added to an application by one user after the application was granted admin consent rights by another user. If a threat actor obtains access to an account with sufficient privileges and adds the alternate authentication material triggering this event, the threat actor can now authenticate as the Application or Service Principal using this credential. Additional information on OAuth Credential Grants can be found in RFC 6749 Section 4.4 or https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow. For further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities'
Type de règle
Scheduled
Version
1.1.1
Statut déclaré
Available
Fréquence
1d
Période analysée
2d
Déclenchement
gt 0

Couverture MITRE déclarée

Sources déclarées

Métadonnées du fichier source. Aucune dépendance déduite du KQL.

Connecteurs

Types de données

Requête KQL

Requête originale, sans modification.

let auditLookbackStart = 2d;
let auditLookbackEnd = 1d;
AuditLogs
| where TimeGenerated >= ago(auditLookbackStart)
| where OperationName =~ "Consent to application" 
| where Result =~ "success"
| mv-apply TargetResource = TargetResources on 
  (
      where TargetResource.type =~ "ServicePrincipal"
      | extend targetResourceName = tostring(TargetResource.displayName),
               targetResourceID = tostring(TargetResource.id),
               targetResourceType = tostring(TargetResource.type),
               targetModifiedProp = TargetResource.modifiedProperties
  )
| mv-apply Property = targetModifiedProp on 
  (
      where Property.displayName =~ "ConsentContext.IsAdminConsent"
      | extend isAdminConsent = trim(@'"',tostring(Property.newValue))
  )
| mv-apply Property = targetModifiedProp on 
  (
      where Property.displayName =~ "ConsentAction.Permissions"
      | extend Consent_TargetPermissions = trim(@'"',tostring(Property.newValue))
  )
| mv-apply Property = targetModifiedProp on 
  (
      where Property.displayName =~ "TargetId.ServicePrincipalNames"
      | extend Consent_TargetServicePrincipalNames = tostring(extract_all(@"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})",trim(@'"',tostring(Property.newValue)))[0])
  )
| extend Consent_InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
| extend Consent_InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend Consent_InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend Consent_InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend Consent_InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend Consent_InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
| join kind=inner ( 
AuditLogs
| where TimeGenerated  >= ago(auditLookbackEnd)
| where OperationName =~ "Add service principal credentials"
| where Result =~ "success"
| mv-apply TargetResource = TargetResources on 
  (
      where TargetResource.type =~ "ServicePrincipal"
      | extend targetResourceName = tostring(TargetResource.displayName),
               targetResourceID = tostring(TargetResource.id),
               targetModifiedProp = TargetResource.modifiedProperties
  )
| mv-apply Property = targetModifiedProp on 
  (
      where Property.displayName =~ "KeyDescription"
      | extend Credential_TargetKeyDescription = trim(@'"',tostring(Property.newValue))
  )
| mv-apply Property = targetModifiedProp on 
  (
      where Property.displayName =~ "Included Updated Properties"
      | extend UpdatedProperties = trim(@'"',tostring(Property.newValue))
  )
| mv-apply Property = targetModifiedProp on 
  (
      where Property.displayName =~ "TargetId.ServicePrincipalNames"
      | extend Credential_TargetServicePrincipalNames = tostring(extract_all(@"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})",trim(@'"',tostring(Property.newValue)))[0])
  )
| extend Credential_InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
| extend Credential_InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend Credential_InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend Credential_InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend Credential_InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend Credential_InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
) on targetResourceName, targetResourceID
| extend TimeConsent = TimeGenerated, TimeCred = TimeGenerated1
| where TimeConsent < TimeCred 
| project TimeConsent, TimeCred, targetResourceName, targetResourceType, isAdminConsent, 
Consent_InitiatingUserOrApp, Consent_TargetServicePrincipalNames, Consent_TargetPermissions,
Consent_InitiatingAppName, Consent_InitiatingAppServicePrincipalId, Consent_InitiatingUserPrincipalName, Consent_InitiatingAadUserId, Consent_InitiatingIpAddress,
Credential_InitiatingUserOrApp, Credential_TargetServicePrincipalNames, Credential_TargetKeyDescription,
Credential_InitiatingAppName, Credential_InitiatingAppServicePrincipalId, Credential_InitiatingUserPrincipalName, Credential_InitiatingAadUserId, Credential_InitiatingIpAddress
| extend Consent_AccountName = tostring(split(Consent_InitiatingUserPrincipalName, "@")[0]), Consent_UPNSuffix = tostring(split(Consent_InitiatingUserPrincipalName, "@")[1])
| extend Credential_AccountName = tostring(split(Credential_InitiatingUserPrincipalName, "@")[0]), Credential_UPNSuffix = tostring(split(Credential_InitiatingUserPrincipalName, "@")[1])

Entités déclarées

AccountIP

Contenus associés

Liens établis à partir des identifiants déclarés et des manifests des solutions.

Traçabilité de la source

GitHub

Les valeurs affichées proviennent des fichiers du dépôt Azure/Azure-Sentinel. Elles décrivent le modèle publié, pas la configuration de votre workspace.

Identifiant source
707494a5-8e44-486b-90f8-155d1797a8eb
Autres fichiers source 3Solutions/Microsoft Entra ID/Analytic Rules/CredentialAddedAfterAdminConsent.yamlsource ↗Detections/AuditLogs/CredentialAddedAfterAdminConsent.yamlmigration-note ↗Solutions/Microsoft Entra ID/Data/Solution_AAD.jsonsolution-membership ↗
GSTEP / SUIVI DU CATALOGUE

Ajouté au catalogue : 16 sept. 2026 · 05:49 UTC
Dernier changement observé : 16 sept. 2026 · 05:49 UTC

Dates de synchronisation GSTEP, distinctes des dates de publication du contenu source.