TI map Domain entity to Cloud App Events
| Id | a7d2b1e4-dd9c-40fd-9651-1a136eb8f0df | 
| Rulename | TI map Domain entity to Cloud App Events | 
| Description | Identifies compromises and attacks and detect malicious activities in one’s domain entity from TI. | 
| Severity | Medium | 
| Tactics | CommandAndControl | 
| Techniques | T1071 | 
| Required data connectors | MicrosoftDefenderThreatIntelligence MicrosoftThreatProtection  | 
| 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/Threat Intelligence (NEW)/Analytic Rules/DomainEntity_CloudAppEvents_Updated.yaml | 
| Version | 1.0.6 | 
| Arm template | a7d2b1e4-dd9c-40fd-9651-1a136eb8f0df.json | 
let dt_lookBack = 1h;
let ioc_lookBack = 14d; 
let list_tlds =
  ThreatIntelIndicators
    | where TimeGenerated >= ago(ioc_lookBack)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
    | where IsActive and (ValidUntil > now() or isempty(ValidUntil))
    //extract key part of kv pair
    | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
    | where IndicatorType == "domain-name"
    | extend DomainName = tolower(IndicatorType)
    | extend parts = split(DomainName, '.')
    | extend tld = parts[(array_length(parts) - 1)]
    | extend IndicatorId = tostring(split(Id, "--")[2])
    | summarize count() by tostring(tld)
    | summarize make_set(tld);
let Domain_Indicators =
  ThreatIntelIndicators
    | where TimeGenerated >= ago(ioc_lookBack)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
    | where IsActive and (ValidUntil > now() or isempty(ValidUntil))
    | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
    | where IndicatorType == "domain-name"
    | extend DomainName = tolower(ObservableValue)
    | extend IndicatorId = tostring(split(Id, "--")[2])
    | project-reorder *, IndicatorType, DomainName, Type;
  Domain_Indicators
    | join kind=innerunique (
  CloudAppEvents
    | extend IngestionTime = ingestion_time()
    | where IngestionTime > ago(dt_lookBack)
    | extend PAUrl = columnifexists("RequestURL", "None")
    | extend Domain = tolower(trim('"', tostring(parseurl(PAUrl).Host)))
    | extend parts = split(Domain, '.')
    | extend tld = parts[(array_length(parts) - 1)]
    | extend CloudAppEvents_TimeGenerated = TimeGenerated) on $left.DomainName == $right.Domain
    | where CloudAppEvents_TimeGenerated < ValidUntil
    | summarize CloudAppEvents_TimeGenerated = argmax(CloudAppEvents_TimeGenerated, *) by IndicatorId
    | extend 
          Description = tostring(parse_json(max_CloudAppEvents_TimeGenerated_Data).description),
          ActivityGroupNames = column_ifexists("max_CloudAppEvents_TimeGenerated_ActivityGroupNames", ""),
          ThreatType = column_ifexists("max_CloudAppEvents_TimeGenerated_ThreatType", ""),
          ExpirationDateTime = column_ifexists("max_CloudAppEvents_TimeGenerated_ExpirationDateTime", ""),
          ConfidenceScore = column_ifexists("max_CloudAppEvents_TimeGenerated_ConfidenceScore", ""),
          DomainName = column_ifexists("max_CloudAppEvents_TimeGenerated_DomainName", ""),
          ProviderName = column_ifexists("max_CloudAppEvents_TimeGenerated_IndicatorProvider", ""),
          AlertSeverity = column_ifexists("max_CloudAppEvents_TimeGenerated_ThreatSeverity", ""),
          IPAddress = column_ifexists("max_CloudAppEvents_TimeGenerated_IPAddress", "")
    | project CloudAppEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, ProviderName, AlertSeverity, IPAddress
kind: Scheduled
entityMappings:
- entityType: DNS
  fieldMappings:
  - columnName: DomainName
    identifier: DomainName
- entityType: IP
  fieldMappings:
  - columnName: IPAddress
    identifier: Address
description: |
    'Identifies compromises and attacks and detect malicious activities in one's domain entity from TI.'
severity: Medium
queryFrequency: 1h
triggerThreshold: 0
relevantTechniques:
- T1071
tactics:
- CommandAndControl
name: TI map Domain entity to Cloud App Events
id: a7d2b1e4-dd9c-40fd-9651-1a136eb8f0df
query: |
  let dt_lookBack = 1h;
  let ioc_lookBack = 14d; 
  let list_tlds =
    ThreatIntelIndicators
      | where TimeGenerated >= ago(ioc_lookBack)
      | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
      | where IsActive and (ValidUntil > now() or isempty(ValidUntil))
      //extract key part of kv pair
      | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
      | where IndicatorType == "domain-name"
      | extend DomainName = tolower(IndicatorType)
      | extend parts = split(DomainName, '.')
      | extend tld = parts[(array_length(parts) - 1)]
      | extend IndicatorId = tostring(split(Id, "--")[2])
      | summarize count() by tostring(tld)
      | summarize make_set(tld);
  let Domain_Indicators =
    ThreatIntelIndicators
      | where TimeGenerated >= ago(ioc_lookBack)
      | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue
      | where IsActive and (ValidUntil > now() or isempty(ValidUntil))
      | extend IndicatorType = replace(@"\[|\]|\""", "", tostring(split(ObservableKey, ":", 0)))
      | where IndicatorType == "domain-name"
      | extend DomainName = tolower(ObservableValue)
      | extend IndicatorId = tostring(split(Id, "--")[2])
      | project-reorder *, IndicatorType, DomainName, Type;
    Domain_Indicators
      | join kind=innerunique (
    CloudAppEvents
      | extend IngestionTime = ingestion_time()
      | where IngestionTime > ago(dt_lookBack)
      | extend PAUrl = columnifexists("RequestURL", "None")
      | extend Domain = tolower(trim('"', tostring(parseurl(PAUrl).Host)))
      | extend parts = split(Domain, '.')
      | extend tld = parts[(array_length(parts) - 1)]
      | extend CloudAppEvents_TimeGenerated = TimeGenerated) on $left.DomainName == $right.Domain
      | where CloudAppEvents_TimeGenerated < ValidUntil
      | summarize CloudAppEvents_TimeGenerated = argmax(CloudAppEvents_TimeGenerated, *) by IndicatorId
      | extend 
            Description = tostring(parse_json(max_CloudAppEvents_TimeGenerated_Data).description),
            ActivityGroupNames = column_ifexists("max_CloudAppEvents_TimeGenerated_ActivityGroupNames", ""),
            ThreatType = column_ifexists("max_CloudAppEvents_TimeGenerated_ThreatType", ""),
            ExpirationDateTime = column_ifexists("max_CloudAppEvents_TimeGenerated_ExpirationDateTime", ""),
            ConfidenceScore = column_ifexists("max_CloudAppEvents_TimeGenerated_ConfidenceScore", ""),
            DomainName = column_ifexists("max_CloudAppEvents_TimeGenerated_DomainName", ""),
            ProviderName = column_ifexists("max_CloudAppEvents_TimeGenerated_IndicatorProvider", ""),
            AlertSeverity = column_ifexists("max_CloudAppEvents_TimeGenerated_ThreatSeverity", ""),
            IPAddress = column_ifexists("max_CloudAppEvents_TimeGenerated_IPAddress", "")
      | project CloudAppEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, ProviderName, AlertSeverity, IPAddress  
requiredDataConnectors:
- dataTypes:
  - CloudAppEvents
  connectorId: MicrosoftThreatProtection
- dataTypes:
  - ThreatIntelIndicators
  connectorId: MicrosoftDefenderThreatIntelligence
version: 1.0.6
triggerOperator: gt
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/DomainEntity_CloudAppEvents_Updated.yaml
queryPeriod: 14d
{
  "$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/a7d2b1e4-dd9c-40fd-9651-1a136eb8f0df')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/a7d2b1e4-dd9c-40fd-9651-1a136eb8f0df')]",
      "properties": {
        "alertRuleTemplateName": "a7d2b1e4-dd9c-40fd-9651-1a136eb8f0df",
        "customDetails": null,
        "description": "'Identifies compromises and attacks and detect malicious activities in one's domain entity from TI.'\n",
        "displayName": "TI map Domain entity to Cloud App Events",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "DNS",
            "fieldMappings": [
              {
                "columnName": "DomainName",
                "identifier": "DomainName"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "IPAddress",
                "identifier": "Address"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence (NEW)/Analytic Rules/DomainEntity_CloudAppEvents_Updated.yaml",
        "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d; \nlet list_tlds =\n  ThreatIntelIndicators\n    | where TimeGenerated >= ago(ioc_lookBack)\n    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue\n    | where IsActive and (ValidUntil > now() or isempty(ValidUntil))\n    //extract key part of kv pair\n    | extend IndicatorType = replace(@\"\\[|\\]|\\\"\"\", \"\", tostring(split(ObservableKey, \":\", 0)))\n    | where IndicatorType == \"domain-name\"\n    | extend DomainName = tolower(IndicatorType)\n    | extend parts = split(DomainName, '.')\n    | extend tld = parts[(array_length(parts) - 1)]\n    | extend IndicatorId = tostring(split(Id, \"--\")[2])\n    | summarize count() by tostring(tld)\n    | summarize make_set(tld);\nlet Domain_Indicators =\n  ThreatIntelIndicators\n    | where TimeGenerated >= ago(ioc_lookBack)\n    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by Id, ObservableValue\n    | where IsActive and (ValidUntil > now() or isempty(ValidUntil))\n    | extend IndicatorType = replace(@\"\\[|\\]|\\\"\"\", \"\", tostring(split(ObservableKey, \":\", 0)))\n    | where IndicatorType == \"domain-name\"\n    | extend DomainName = tolower(ObservableValue)\n    | extend IndicatorId = tostring(split(Id, \"--\")[2])\n    | project-reorder *, IndicatorType, DomainName, Type;\n  Domain_Indicators\n    | join kind=innerunique (\n  CloudAppEvents\n    | extend IngestionTime = ingestion_time()\n    | where IngestionTime > ago(dt_lookBack)\n    | extend PAUrl = columnifexists(\"RequestURL\", \"None\")\n    | extend Domain = tolower(trim('\"', tostring(parseurl(PAUrl).Host)))\n    | extend parts = split(Domain, '.')\n    | extend tld = parts[(array_length(parts) - 1)]\n    | extend CloudAppEvents_TimeGenerated = TimeGenerated) on $left.DomainName == $right.Domain\n    | where CloudAppEvents_TimeGenerated < ValidUntil\n    | summarize CloudAppEvents_TimeGenerated = argmax(CloudAppEvents_TimeGenerated, *) by IndicatorId\n    | extend \n          Description = tostring(parse_json(max_CloudAppEvents_TimeGenerated_Data).description),\n          ActivityGroupNames = column_ifexists(\"max_CloudAppEvents_TimeGenerated_ActivityGroupNames\", \"\"),\n          ThreatType = column_ifexists(\"max_CloudAppEvents_TimeGenerated_ThreatType\", \"\"),\n          ExpirationDateTime = column_ifexists(\"max_CloudAppEvents_TimeGenerated_ExpirationDateTime\", \"\"),\n          ConfidenceScore = column_ifexists(\"max_CloudAppEvents_TimeGenerated_ConfidenceScore\", \"\"),\n          DomainName = column_ifexists(\"max_CloudAppEvents_TimeGenerated_DomainName\", \"\"),\n          ProviderName = column_ifexists(\"max_CloudAppEvents_TimeGenerated_IndicatorProvider\", \"\"),\n          AlertSeverity = column_ifexists(\"max_CloudAppEvents_TimeGenerated_ThreatSeverity\", \"\"),\n          IPAddress = column_ifexists(\"max_CloudAppEvents_TimeGenerated_IPAddress\", \"\")\n    | project CloudAppEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, ProviderName, AlertSeverity, IPAddress\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}