Dataverse - New non-interactive identity granted access
| Id | 682e230c-e5da-4085-8666-701d1f1be7de |
| Rulename | Dataverse - New non-interactive identity granted access |
| Description | Identifies API level access grants, either via the delegated permissions of a Microsoft Entra application or direct assignment within Dataverse as an application user. |
| Severity | Informational |
| Tactics | Persistence LateralMovement PrivilegeEscalation |
| Techniques | T1098 T0859 T1078 |
| Required data connectors | AzureActiveDirectory Dataverse |
| Kind | Scheduled |
| Query frequency | 1h |
| Query period | 14d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - New non-interactive identity granted access.yaml |
| Version | 3.2.0 |
| Arm template | 682e230c-e5da-4085-8666-701d1f1be7de.json |
let dataverse_app_id = "00000007-0000-0000-c000-000000000000";
let query_frequency = 1h;
let azure_ad_changes = AuditLogs
| where TimeGenerated >= ago(query_frequency)
| where OperationName =~ 'Update application'
| where TargetResources has dataverse_app_id
| extend TargetAppName = tostring(TargetResources[0].displayName)
| extend TargetAppId = tostring(TargetResources[0].id)
| extend UserId = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend ClientIp = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
| extend NewData = tostring(parse_json(tostring(parse_json(TargetResources)[0].modifiedProperties))[0].newValue)
| where NewData has dataverse_app_id;
let dataverse_changes = DataverseActivity
| where TimeGenerated >= ago(query_frequency)
| where (Message == "Create" and EntityName == "systemuser" and parse_json(Fields)[0].Name == "applicationid")
| extend TargetAppId = tostring(Fields[0].Value);
union azure_ad_changes, dataverse_changes
| extend
CloudAppId = int(32780),
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[1])
| project
TimeGenerated,
UserId,
ClientIp,
TargetAppName,
TargetAppId,
InstanceUrl,
CloudAppId,
AccountName,
UPNSuffix
id: 682e230c-e5da-4085-8666-701d1f1be7de
eventGroupingSettings:
aggregationKind: AlertPerResult
requiredDataConnectors:
- dataTypes:
- DataverseActivity
connectorId: Dataverse
- dataTypes:
- AuditLogs
connectorId: AzureActiveDirectory
name: Dataverse - New non-interactive identity granted access
version: 3.2.0
query: |
let dataverse_app_id = "00000007-0000-0000-c000-000000000000";
let query_frequency = 1h;
let azure_ad_changes = AuditLogs
| where TimeGenerated >= ago(query_frequency)
| where OperationName =~ 'Update application'
| where TargetResources has dataverse_app_id
| extend TargetAppName = tostring(TargetResources[0].displayName)
| extend TargetAppId = tostring(TargetResources[0].id)
| extend UserId = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
| extend ClientIp = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)
| extend NewData = tostring(parse_json(tostring(parse_json(TargetResources)[0].modifiedProperties))[0].newValue)
| where NewData has dataverse_app_id;
let dataverse_changes = DataverseActivity
| where TimeGenerated >= ago(query_frequency)
| where (Message == "Create" and EntityName == "systemuser" and parse_json(Fields)[0].Name == "applicationid")
| extend TargetAppId = tostring(Fields[0].Value);
union azure_ad_changes, dataverse_changes
| extend
CloudAppId = int(32780),
AccountName = tostring(split(UserId, '@')[0]),
UPNSuffix = tostring(split(UserId, '@')[1])
| project
TimeGenerated,
UserId,
ClientIp,
TargetAppName,
TargetAppId,
InstanceUrl,
CloudAppId,
AccountName,
UPNSuffix
entityMappings:
- fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: UPNSuffix
entityType: Account
- fieldMappings:
- identifier: AppId
columnName: CloudAppId
- identifier: InstanceName
columnName: InstanceUrl
entityType: CloudApplication
- fieldMappings:
- identifier: Address
columnName: ClientIp
entityType: IP
- fieldMappings:
- identifier: AadUserId
columnName: TargetAppId
entityType: Account
triggerThreshold: 0
alertDetailsOverride:
alertDescriptionFormat: '{{UserId}} granted access to an Azure AD app {{{TargetAppName}}. Check to validate this access was authorized.'
alertDisplayNameFormat: Dataverse - new non-interactive access granted
relevantTechniques:
- T1098
- T0859
- T1078
tactics:
- Persistence
- LateralMovement
- PrivilegeEscalation
kind: Scheduled
queryPeriod: 14d
queryFrequency: 1h
severity: Informational
triggerOperator: gt
status: Available
description: Identifies API level access grants, either via the delegated permissions of a Microsoft Entra application or direct assignment within Dataverse as an application user.
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - New non-interactive identity granted access.yaml