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
relevantTechniques:
- T1098
- T0859
- T1078
name: Dataverse - New non-interactive identity granted access
queryPeriod: 14d
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
id: 682e230c-e5da-4085-8666-701d1f1be7de
eventGroupingSettings:
aggregationKind: AlertPerResult
severity: Informational
requiredDataConnectors:
- dataTypes:
- DataverseActivity
connectorId: Dataverse
- dataTypes:
- AuditLogs
connectorId: AzureActiveDirectory
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.
version: 3.2.0
status: Available
entityMappings:
- entityType: Account
fieldMappings:
- columnName: AccountName
identifier: Name
- columnName: UPNSuffix
identifier: UPNSuffix
- entityType: CloudApplication
fieldMappings:
- columnName: CloudAppId
identifier: AppId
- columnName: InstanceUrl
identifier: InstanceName
- entityType: IP
fieldMappings:
- columnName: ClientIp
identifier: Address
- entityType: Account
fieldMappings:
- columnName: TargetAppId
identifier: AadUserId
tactics:
- Persistence
- LateralMovement
- PrivilegeEscalation
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
kind: Scheduled
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - New non-interactive identity granted access.yaml
queryFrequency: 1h
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/682e230c-e5da-4085-8666-701d1f1be7de')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/682e230c-e5da-4085-8666-701d1f1be7de')]",
"properties": {
"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"
},
"alertRuleTemplateName": "682e230c-e5da-4085-8666-701d1f1be7de",
"customDetails": null,
"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.",
"displayName": "Dataverse - New non-interactive identity granted access",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "UPNSuffix",
"identifier": "UPNSuffix"
}
]
},
{
"entityType": "CloudApplication",
"fieldMappings": [
{
"columnName": "CloudAppId",
"identifier": "AppId"
},
{
"columnName": "InstanceUrl",
"identifier": "InstanceName"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "ClientIp",
"identifier": "Address"
}
]
},
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "TargetAppId",
"identifier": "AadUserId"
}
]
}
],
"eventGroupingSettings": {
"aggregationKind": "AlertPerResult"
},
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - New non-interactive identity granted access.yaml",
"query": "let dataverse_app_id = \"00000007-0000-0000-c000-000000000000\";\nlet query_frequency = 1h;\nlet azure_ad_changes = AuditLogs\n | where TimeGenerated >= ago(query_frequency)\n | where OperationName =~ 'Update application'\n | where TargetResources has dataverse_app_id\n | extend TargetAppName = tostring(TargetResources[0].displayName)\n | extend TargetAppId = tostring(TargetResources[0].id)\n | extend UserId = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)\n | extend ClientIp = tostring(parse_json(tostring(InitiatedBy.user)).ipAddress)\n | extend NewData = tostring(parse_json(tostring(parse_json(TargetResources)[0].modifiedProperties))[0].newValue)\n | where NewData has dataverse_app_id;\nlet dataverse_changes = DataverseActivity\n | where TimeGenerated >= ago(query_frequency)\n | where (Message == \"Create\" and EntityName == \"systemuser\" and parse_json(Fields)[0].Name == \"applicationid\")\n | extend TargetAppId = tostring(Fields[0].Value);\nunion azure_ad_changes, dataverse_changes\n| extend\n CloudAppId = int(32780),\n AccountName = tostring(split(UserId, '@')[0]),\n UPNSuffix = tostring(split(UserId, '@')[1])\n| project\n TimeGenerated,\n UserId,\n ClientIp,\n TargetAppName,\n TargetAppId,\n InstanceUrl,\n CloudAppId,\n AccountName,\n UPNSuffix\n",
"queryFrequency": "PT1H",
"queryPeriod": "P14D",
"severity": "Informational",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"LateralMovement",
"Persistence",
"PrivilegeEscalation"
],
"techniques": [
"T1078",
"T1098"
],
"templateVersion": "3.2.0",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}