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

Dataverse - Suspicious use of TDS endpoint

Back
Idd875af10-6bb9-4d6a-a6e4-78439a98bf4b
RulenameDataverse - Suspicious use of TDS endpoint
DescriptionIdentifies Dataverse TDS (Tabular Data Stream) protocol based queries where the source user or IP address has recent security alerts and the TDS protocol has not been used previously in the target environment.
SeverityLow
TacticsExfiltration
InitialAccess
TechniquesT1048
T1190
Required data connectorsAzureActiveDirectoryIdentityProtection
Dataverse
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 use of TDS endpoint.yaml
Version3.2.0
Arm templated875af10-6bb9-4d6a-a6e4-78439a98bf4b.json
Deploy To Azure
let query_frequency = 1h;
let query_lookback = 14d;
DataverseActivity
| where TimeGenerated >= ago(query_frequency)
| where Message == 'ExecutePowerBISql'
| summarize FirstEvent = min(TimeGenerated) by UserId, ClientIp, InstanceUrl
| join kind=inner(
    DataverseActivity
    | where TimeGenerated >= ago(query_lookback)
    | where Message == 'ExecutePowerBISql'
    | summarize UniqueUsers = dcount(UserId, 4) by InstanceUrl)
    on InstanceUrl
| where UniqueUsers == 1
| join kind=inner (
    SecurityAlert
    | where Entities has ('"Type":"ip"')
    | project AlertName, SystemAlertId, Entities
    | mv-expand todynamic(Entities)
    | where Entities.Type == "ip"
    | extend IPAddress = tostring(Entities.Address)
    | summarize SystemAlerts = make_set(SystemAlertId, 100), Alerts = make_set(AlertName, 100) by IPAddress)
    on $left.ClientIp == $right.IPAddress
| extend
    CloudAppId = int(32780),
    AccountName = tostring(split(UserId, '@')[0]),
    UPNSuffix = tostring(split(UserId, '@')[1])
| join kind = inner (
    SecurityAlert
    | where Entities has ('Type":"account"')
    | project AlertName, SystemAlertId, Entities
    | mv-expand todynamic(Entities)
    | where Entities.Type == "account"
    | extend
        UPNSuffix = tostring(Entities.UPNSuffix),
        AccountName = tostring(Entities.Name)
    | summarize SystemAlerts = make_set(SystemAlertId, 100), Alerts = make_set(AlertName, 100) by AccountName, UPNSuffix
    | where isnotempty(AccountName) and isnotempty(UPNSuffix))
    on AccountName, UPNSuffix
| summarize SystemAlerts = make_set(SystemAlerts, 100), Alerts = make_set(Alerts, 100) by FirstEvent, UserId, ClientIp, InstanceUrl, AccountName, UPNSuffix
| extend CloudAppId = int(32780)
| project
    FirstEvent,
    UserId,
    ClientIp,
    InstanceUrl,
    Alerts,
    SystemAlerts,
    CloudAppId,
    AccountName,
    UPNSuffix
queryFrequency: 1h
eventGroupingSettings:
  aggregationKind: AlertPerResult
requiredDataConnectors:
- connectorId: Dataverse
  dataTypes:
  - DataverseActivity
- connectorId: AzureActiveDirectoryIdentityProtection
  dataTypes:
  - SecurityAlert
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Suspicious use of TDS endpoint.yaml
query: |
  let query_frequency = 1h;
  let query_lookback = 14d;
  DataverseActivity
  | where TimeGenerated >= ago(query_frequency)
  | where Message == 'ExecutePowerBISql'
  | summarize FirstEvent = min(TimeGenerated) by UserId, ClientIp, InstanceUrl
  | join kind=inner(
      DataverseActivity
      | where TimeGenerated >= ago(query_lookback)
      | where Message == 'ExecutePowerBISql'
      | summarize UniqueUsers = dcount(UserId, 4) by InstanceUrl)
      on InstanceUrl
  | where UniqueUsers == 1
  | join kind=inner (
      SecurityAlert
      | where Entities has ('"Type":"ip"')
      | project AlertName, SystemAlertId, Entities
      | mv-expand todynamic(Entities)
      | where Entities.Type == "ip"
      | extend IPAddress = tostring(Entities.Address)
      | summarize SystemAlerts = make_set(SystemAlertId, 100), Alerts = make_set(AlertName, 100) by IPAddress)
      on $left.ClientIp == $right.IPAddress
  | extend
      CloudAppId = int(32780),
      AccountName = tostring(split(UserId, '@')[0]),
      UPNSuffix = tostring(split(UserId, '@')[1])
  | join kind = inner (
      SecurityAlert
      | where Entities has ('Type":"account"')
      | project AlertName, SystemAlertId, Entities
      | mv-expand todynamic(Entities)
      | where Entities.Type == "account"
      | extend
          UPNSuffix = tostring(Entities.UPNSuffix),
          AccountName = tostring(Entities.Name)
      | summarize SystemAlerts = make_set(SystemAlertId, 100), Alerts = make_set(AlertName, 100) by AccountName, UPNSuffix
      | where isnotempty(AccountName) and isnotempty(UPNSuffix))
      on AccountName, UPNSuffix
  | summarize SystemAlerts = make_set(SystemAlerts, 100), Alerts = make_set(Alerts, 100) by FirstEvent, UserId, ClientIp, InstanceUrl, AccountName, UPNSuffix
  | extend CloudAppId = int(32780)
  | project
      FirstEvent,
      UserId,
      ClientIp,
      InstanceUrl,
      Alerts,
      SystemAlerts,
      CloudAppId,
      AccountName,
      UPNSuffix  
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: Name
    columnName: AccountName
  - identifier: UPNSuffix
    columnName: UPNSuffix
- entityType: CloudApplication
  fieldMappings:
  - identifier: AppId
    columnName: CloudAppId
  - identifier: InstanceName
    columnName: InstanceUrl
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: ClientIp
relevantTechniques:
- T1048
- T1190
name: Dataverse - Suspicious use of TDS endpoint
description: Identifies Dataverse TDS (Tabular Data Stream) protocol based queries where the source user or IP address has recent security alerts and the TDS protocol has not been used previously in the target environment.
severity: Low
queryPeriod: 14d
alertDetailsOverride:
  alertDescriptionFormat: 'The TDS endpoint was used to query Dataverse instance {{InstanceUrl}} . The use of this protocol was not seen previously and the following alerts were associated with the caller: {{Alerts}}'
  alertDisplayNameFormat: 'Dataverse - Suspicious use of TDS endpoint in {{InstanceUrl}} '
triggerOperator: gt
kind: Scheduled
status: Available
tactics:
- Exfiltration
- InitialAccess
id: d875af10-6bb9-4d6a-a6e4-78439a98bf4b
version: 3.2.0
triggerThreshold: 0
{
  "$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/d875af10-6bb9-4d6a-a6e4-78439a98bf4b')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/d875af10-6bb9-4d6a-a6e4-78439a98bf4b')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "The TDS endpoint was used to query Dataverse instance {{InstanceUrl}} . The use of this protocol was not seen previously and the following alerts were associated with the caller: {{Alerts}}",
          "alertDisplayNameFormat": "Dataverse - Suspicious use of TDS endpoint in {{InstanceUrl}} "
        },
        "alertRuleTemplateName": "d875af10-6bb9-4d6a-a6e4-78439a98bf4b",
        "customDetails": null,
        "description": "Identifies Dataverse TDS (Tabular Data Stream) protocol based queries where the source user or IP address has recent security alerts and the TDS protocol has not been used previously in the target environment.",
        "displayName": "Dataverse - Suspicious use of TDS endpoint",
        "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"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "AlertPerResult"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft Business Applications/Analytic Rules/Dataverse - Suspicious use of TDS endpoint.yaml",
        "query": "let query_frequency = 1h;\nlet query_lookback = 14d;\nDataverseActivity\n| where TimeGenerated >= ago(query_frequency)\n| where Message == 'ExecutePowerBISql'\n| summarize FirstEvent = min(TimeGenerated) by UserId, ClientIp, InstanceUrl\n| join kind=inner(\n    DataverseActivity\n    | where TimeGenerated >= ago(query_lookback)\n    | where Message == 'ExecutePowerBISql'\n    | summarize UniqueUsers = dcount(UserId, 4) by InstanceUrl)\n    on InstanceUrl\n| where UniqueUsers == 1\n| join kind=inner (\n    SecurityAlert\n    | where Entities has ('\"Type\":\"ip\"')\n    | project AlertName, SystemAlertId, Entities\n    | mv-expand todynamic(Entities)\n    | where Entities.Type == \"ip\"\n    | extend IPAddress = tostring(Entities.Address)\n    | summarize SystemAlerts = make_set(SystemAlertId, 100), Alerts = make_set(AlertName, 100) by IPAddress)\n    on $left.ClientIp == $right.IPAddress\n| extend\n    CloudAppId = int(32780),\n    AccountName = tostring(split(UserId, '@')[0]),\n    UPNSuffix = tostring(split(UserId, '@')[1])\n| join kind = inner (\n    SecurityAlert\n    | where Entities has ('Type\":\"account\"')\n    | project AlertName, SystemAlertId, Entities\n    | mv-expand todynamic(Entities)\n    | where Entities.Type == \"account\"\n    | extend\n        UPNSuffix = tostring(Entities.UPNSuffix),\n        AccountName = tostring(Entities.Name)\n    | summarize SystemAlerts = make_set(SystemAlertId, 100), Alerts = make_set(AlertName, 100) by AccountName, UPNSuffix\n    | where isnotempty(AccountName) and isnotempty(UPNSuffix))\n    on AccountName, UPNSuffix\n| summarize SystemAlerts = make_set(SystemAlerts, 100), Alerts = make_set(Alerts, 100) by FirstEvent, UserId, ClientIp, InstanceUrl, AccountName, UPNSuffix\n| extend CloudAppId = int(32780)\n| project\n    FirstEvent,\n    UserId,\n    ClientIp,\n    InstanceUrl,\n    Alerts,\n    SystemAlerts,\n    CloudAppId,\n    AccountName,\n    UPNSuffix\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Low",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Exfiltration",
          "InitialAccess"
        ],
        "techniques": [
          "T1048",
          "T1190"
        ],
        "templateVersion": "3.2.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}