Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Dataverse - Suspicious security role modifications

Back
Ide44a58b2-b63a-4eb9-92da-85660d73495c
RulenameDataverse - Suspicious security role modifications
DescriptionIdentifies an unusual pattern of events whereby a new role is created followed by the creator adding members to the role and subsequently removing the member or deleting the role after a short time period.
SeverityMedium
TacticsPrivilegeEscalation
TechniquesT1404
T1626
T1548
Required data connectorsDataverse
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Suspicious security role modifications.yaml
Version3.2.0
Arm templatee44a58b2-b63a-4eb9-92da-85660d73495c.json
Deploy To Azure
let role_create_watch_period = 2d;
let query_frequency = 1h;
let role_create_add_events= DataverseActivity
    | where Message == "Create" and EntityName == "role"
    | mv-expand Role = Fields
    | extend RoleName = Role.Value
    | where Role.Name == "name"
    | mv-expand Role = Fields
    | extend RoleCreateTime = TimeGenerated, RoleId = tostring(Role.Value)
    | where Role.Name == "roleid"
    | join kind=inner (
        DataverseActivity
        | where Message == "Associate" and EntityName == "systemuser"
        | mv-expand Role = Fields
        | where Role.Name == "role"
        | extend RoleMemberAddedTime = TimeGenerated, MemberAddedRoleId = tostring(Role.Value))
        on $left.RoleId == $right.MemberAddedRoleId, InstanceUrl, UserId
    | where RoleMemberAddedTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period));
let remove_role_member_events = DataverseActivity
    | where TimeGenerated >= ago(query_frequency)
    | where Message == "Disassociate" and EntityName == "systemuser"
    | mv-expand Role = Fields
    | where Role.Name == "role"
    | extend ActionTime = TimeGenerated, MemberRemovedRoleId = tostring(Role.Value);
let role_delete_events = DataverseActivity
    | where TimeGenerated >= ago(query_frequency)
    | where Message == "Delete" and EntityName == "role"
    | extend DeletedRoleID = EntityId, Action = "Role deleted within defined time window"
    | project Action, ActionTime = TimeGenerated, UserId, ClientIp, DeletedRoleID, InstanceUrl;
let role_member_removals = role_create_add_events
    | join kind=inner (remove_role_member_events) on $left.RoleId == $right.MemberRemovedRoleId
    | where ActionTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period))
    | extend Action = "Role membership removed within defined time window";
let role_deletions = role_create_add_events
    | join kind=inner (role_delete_events) on $left.RoleId == $right.DeletedRoleID
    | where ActionTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period));
union isfuzzy=true role_member_removals, role_deletions
| extend
    CloudAppId = int(32780),
    AccountName = tostring(split(UserId, '@')[0]),
    UPNSuffix = tostring(split(UserId, '@')[1])
| project
    UserId,
    InstanceUrl,
    ClientIp,
    Action,
    RoleCreateTime,
    RoleName,
    ActionTime,
    CloudAppId,
    AccountName,
    UPNSuffix
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: UPNSuffix
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: ClientIp
- entityType: CloudApplication
  fieldMappings:
  - identifier: AppId
    columnName: CloudAppId
  - identifier: InstanceName
    columnName: InstanceUrl
queryFrequency: 1h
name: Dataverse - Suspicious security role modifications
alertDetailsOverride:
  alertDisplayNameFormat: Dataverse - suspicious role modifications in {{InstanceUrl}}
  alertDescriptionFormat: 'The following action ocurred following role modifications changes in {{InstanceUrl}}: {{Action}}.'
  alertSeverityColumnName: Severity
kind: Scheduled
tactics:
- PrivilegeEscalation
triggerThreshold: 0
query: |
  let role_create_watch_period = 2d;
  let query_frequency = 1h;
  let role_create_add_events= DataverseActivity
      | where Message == "Create" and EntityName == "role"
      | mv-expand Role = Fields
      | extend RoleName = Role.Value
      | where Role.Name == "name"
      | mv-expand Role = Fields
      | extend RoleCreateTime = TimeGenerated, RoleId = tostring(Role.Value)
      | where Role.Name == "roleid"
      | join kind=inner (
          DataverseActivity
          | where Message == "Associate" and EntityName == "systemuser"
          | mv-expand Role = Fields
          | where Role.Name == "role"
          | extend RoleMemberAddedTime = TimeGenerated, MemberAddedRoleId = tostring(Role.Value))
          on $left.RoleId == $right.MemberAddedRoleId, InstanceUrl, UserId
      | where RoleMemberAddedTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period));
  let remove_role_member_events = DataverseActivity
      | where TimeGenerated >= ago(query_frequency)
      | where Message == "Disassociate" and EntityName == "systemuser"
      | mv-expand Role = Fields
      | where Role.Name == "role"
      | extend ActionTime = TimeGenerated, MemberRemovedRoleId = tostring(Role.Value);
  let role_delete_events = DataverseActivity
      | where TimeGenerated >= ago(query_frequency)
      | where Message == "Delete" and EntityName == "role"
      | extend DeletedRoleID = EntityId, Action = "Role deleted within defined time window"
      | project Action, ActionTime = TimeGenerated, UserId, ClientIp, DeletedRoleID, InstanceUrl;
  let role_member_removals = role_create_add_events
      | join kind=inner (remove_role_member_events) on $left.RoleId == $right.MemberRemovedRoleId
      | where ActionTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period))
      | extend Action = "Role membership removed within defined time window";
  let role_deletions = role_create_add_events
      | join kind=inner (role_delete_events) on $left.RoleId == $right.DeletedRoleID
      | where ActionTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period));
  union isfuzzy=true role_member_removals, role_deletions
  | extend
      CloudAppId = int(32780),
      AccountName = tostring(split(UserId, '@')[0]),
      UPNSuffix = tostring(split(UserId, '@')[1])
  | project
      UserId,
      InstanceUrl,
      ClientIp,
      Action,
      RoleCreateTime,
      RoleName,
      ActionTime,
      CloudAppId,
      AccountName,
      UPNSuffix  
relevantTechniques:
- T1404
- T1626
- T1548
triggerOperator: gt
queryPeriod: 14d
eventGroupingSettings:
  aggregationKind: AlertPerResult
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Suspicious security role modifications.yaml
severity: Medium
status: Available
id: e44a58b2-b63a-4eb9-92da-85660d73495c
requiredDataConnectors:
- connectorId: Dataverse
  dataTypes:
  - DataverseActivity
version: 3.2.0
description: Identifies an unusual pattern of events whereby a new role is created followed by the creator adding members to the role and subsequently removing the member or deleting the role after a short time period.
{
  "$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/e44a58b2-b63a-4eb9-92da-85660d73495c')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/e44a58b2-b63a-4eb9-92da-85660d73495c')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "The following action ocurred following role modifications changes in {{InstanceUrl}}: {{Action}}.",
          "alertDisplayNameFormat": "Dataverse - suspicious role modifications in {{InstanceUrl}}",
          "alertSeverityColumnName": "Severity"
        },
        "alertRuleTemplateName": "e44a58b2-b63a-4eb9-92da-85660d73495c",
        "customDetails": null,
        "description": "Identifies an unusual pattern of events whereby a new role is created followed by the creator adding members to the role and subsequently removing the member or deleting the role after a short time period.",
        "displayName": "Dataverse - Suspicious security role modifications",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountName",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIp",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "CloudApplication",
            "fieldMappings": [
              {
                "columnName": "CloudAppId",
                "identifier": "AppId"
              },
              {
                "columnName": "InstanceUrl",
                "identifier": "InstanceName"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "AlertPerResult"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Suspicious security role modifications.yaml",
        "query": "let role_create_watch_period = 2d;\nlet query_frequency = 1h;\nlet role_create_add_events= DataverseActivity\n    | where Message == \"Create\" and EntityName == \"role\"\n    | mv-expand Role = Fields\n    | extend RoleName = Role.Value\n    | where Role.Name == \"name\"\n    | mv-expand Role = Fields\n    | extend RoleCreateTime = TimeGenerated, RoleId = tostring(Role.Value)\n    | where Role.Name == \"roleid\"\n    | join kind=inner (\n        DataverseActivity\n        | where Message == \"Associate\" and EntityName == \"systemuser\"\n        | mv-expand Role = Fields\n        | where Role.Name == \"role\"\n        | extend RoleMemberAddedTime = TimeGenerated, MemberAddedRoleId = tostring(Role.Value))\n        on $left.RoleId == $right.MemberAddedRoleId, InstanceUrl, UserId\n    | where RoleMemberAddedTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period));\nlet remove_role_member_events = DataverseActivity\n    | where TimeGenerated >= ago(query_frequency)\n    | where Message == \"Disassociate\" and EntityName == \"systemuser\"\n    | mv-expand Role = Fields\n    | where Role.Name == \"role\"\n    | extend ActionTime = TimeGenerated, MemberRemovedRoleId = tostring(Role.Value);\nlet role_delete_events = DataverseActivity\n    | where TimeGenerated >= ago(query_frequency)\n    | where Message == \"Delete\" and EntityName == \"role\"\n    | extend DeletedRoleID = EntityId, Action = \"Role deleted within defined time window\"\n    | project Action, ActionTime = TimeGenerated, UserId, ClientIp, DeletedRoleID, InstanceUrl;\nlet role_member_removals = role_create_add_events\n    | join kind=inner (remove_role_member_events) on $left.RoleId == $right.MemberRemovedRoleId\n    | where ActionTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period))\n    | extend Action = \"Role membership removed within defined time window\";\nlet role_deletions = role_create_add_events\n    | join kind=inner (role_delete_events) on $left.RoleId == $right.DeletedRoleID\n    | where ActionTime between (RoleCreateTime .. (RoleCreateTime + role_create_watch_period));\nunion isfuzzy=true role_member_removals, role_deletions\n| extend\n    CloudAppId = int(32780),\n    AccountName = tostring(split(UserId, '@')[0]),\n    UPNSuffix = tostring(split(UserId, '@')[1])\n| project\n    UserId,\n    InstanceUrl,\n    ClientIp,\n    Action,\n    RoleCreateTime,\n    RoleName,\n    ActionTime,\n    CloudAppId,\n    AccountName,\n    UPNSuffix\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "PrivilegeEscalation"
        ],
        "techniques": [
          "T1548"
        ],
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}