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

TI map Domain entity to PaloAlto

Back
Idec21493c-2684-4acd-9bc2-696dbad72426
RulenameTI map Domain entity to PaloAlto
DescriptionIdentifies a match in Palo Alto data in CommonSecurityLog table from any Domain IOC from TI
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsMicrosoftDefenderThreatIntelligence
PaloAltoNetworks
ThreatIntelligence
ThreatIntelligenceTaxii
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml
Version1.4.2
Arm templateec21493c-2684-4acd-9bc2-696dbad72426.json
Deploy To Azure
let dt_lookBack = 1h;  // Duration to look back for recent logs (1 hour)
let ioc_lookBack = 14d;  // Duration to look back for recent threat intelligence indicators (14 days)
// Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains
let list_tlds = 
    ThreatIntelligenceIndicator
    | where isnotempty(DomainName)
    | where TimeGenerated >= ago(ioc_lookBack)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | where Active == true and ExpirationDateTime > now()
    | extend DomainName = tolower(DomainName)
    | extend parts = split(DomainName, '.')
    | extend tld = parts[(array_length(parts)-1)]
    | summarize count() by tostring(tld)
    | summarize make_list(tld);
let Domain_Indicators = 
    ThreatIntelligenceIndicator
    // Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)
    | where isnotempty(DomainName)
    | where TimeGenerated >= ago(ioc_lookBack)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | where Active == true and ExpirationDateTime > now()
    | extend TI_DomainEntity = DomainName;
Domain_Indicators
    // Join with CommonSecurityLog to find potential malicious activity
    | join kind=innerunique (
        CommonSecurityLog
        | extend IngestionTime = ingestion_time()
        | where IngestionTime > ago(dt_lookBack)
        | where DeviceVendor =~ 'Palo Alto Networks'
        | where DeviceEventClassID =~ 'url'
        // Uncomment the line below to only alert on allowed connections
        // | where DeviceAction !~ "block-url"
        // Extract domain from RequestURL, if not present, extract it from AdditionalExtensions
        | extend PA_Url = coalesce(RequestURL, "None")
        | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith "PanOS", extract("([^\"]+)", 1, tolower(AdditionalExtensions)), trim('"', PA_Url))
        | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith "http://" and PA_Url !startswith "https://" and ApplicationProtocol !~ "ssl", strcat('http://', PA_Url), PA_Url)
        | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith "https://" and ApplicationProtocol =~ "ssl", strcat('https://', PA_Url), PA_Url)
        | extend Domain = trim(@"""", tostring(parse_url(PA_Url).Host))
        | where isnotempty(Domain)
        | extend Domain = tolower(Domain)
        | extend parts = split(Domain, '.')
        // Split out the top-level domain (TLD) for the purpose of checking if we have any TI indicators with this TLD to match on
        | extend tld = parts[(array_length(parts)-1)]
        // Validate parsed domain by checking TLD against TLDs from the threat feed and drop domains where there is no chance of a match
        | where tld in~ (list_tlds)
        | extend CommonSecurityLog_TimeGenerated = TimeGenerated
    ) on $left.TI_DomainEntity == $right.Domain
    | where CommonSecurityLog_TimeGenerated < ExpirationDateTime
    // Group the results by IndicatorId and Domain and keep only the latest CommonSecurityLog_TimeGenerated
    | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, Domain
    // Select the desired fields for the final result set
    | project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity
    // Add a new field 'timestamp' for convenience, using the CommonSecurityLog_TimeGenerated as its value
    | extend timestamp = CommonSecurityLog_TimeGenerated
entityMappings:
- entityType: Host
  fieldMappings:
  - identifier: HostName
    columnName: DeviceName
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SourceIP
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: PA_Url
queryFrequency: 1h
name: TI map Domain entity to PaloAlto
severity: Medium
kind: Scheduled
tactics:
- CommandAndControl
triggerThreshold: 0
query: |
  let dt_lookBack = 1h;  // Duration to look back for recent logs (1 hour)
  let ioc_lookBack = 14d;  // Duration to look back for recent threat intelligence indicators (14 days)
  // Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains
  let list_tlds = 
      ThreatIntelligenceIndicator
      | where isnotempty(DomainName)
      | where TimeGenerated >= ago(ioc_lookBack)
      | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
      | where Active == true and ExpirationDateTime > now()
      | extend DomainName = tolower(DomainName)
      | extend parts = split(DomainName, '.')
      | extend tld = parts[(array_length(parts)-1)]
      | summarize count() by tostring(tld)
      | summarize make_list(tld);
  let Domain_Indicators = 
      ThreatIntelligenceIndicator
      // Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)
      | where isnotempty(DomainName)
      | where TimeGenerated >= ago(ioc_lookBack)
      | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
      | where Active == true and ExpirationDateTime > now()
      | extend TI_DomainEntity = DomainName;
  Domain_Indicators
      // Join with CommonSecurityLog to find potential malicious activity
      | join kind=innerunique (
          CommonSecurityLog
          | extend IngestionTime = ingestion_time()
          | where IngestionTime > ago(dt_lookBack)
          | where DeviceVendor =~ 'Palo Alto Networks'
          | where DeviceEventClassID =~ 'url'
          // Uncomment the line below to only alert on allowed connections
          // | where DeviceAction !~ "block-url"
          // Extract domain from RequestURL, if not present, extract it from AdditionalExtensions
          | extend PA_Url = coalesce(RequestURL, "None")
          | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith "PanOS", extract("([^\"]+)", 1, tolower(AdditionalExtensions)), trim('"', PA_Url))
          | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith "http://" and PA_Url !startswith "https://" and ApplicationProtocol !~ "ssl", strcat('http://', PA_Url), PA_Url)
          | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith "https://" and ApplicationProtocol =~ "ssl", strcat('https://', PA_Url), PA_Url)
          | extend Domain = trim(@"""", tostring(parse_url(PA_Url).Host))
          | where isnotempty(Domain)
          | extend Domain = tolower(Domain)
          | extend parts = split(Domain, '.')
          // Split out the top-level domain (TLD) for the purpose of checking if we have any TI indicators with this TLD to match on
          | extend tld = parts[(array_length(parts)-1)]
          // Validate parsed domain by checking TLD against TLDs from the threat feed and drop domains where there is no chance of a match
          | where tld in~ (list_tlds)
          | extend CommonSecurityLog_TimeGenerated = TimeGenerated
      ) on $left.TI_DomainEntity == $right.Domain
      | where CommonSecurityLog_TimeGenerated < ExpirationDateTime
      // Group the results by IndicatorId and Domain and keep only the latest CommonSecurityLog_TimeGenerated
      | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, Domain
      // Select the desired fields for the final result set
      | project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity
      // Add a new field 'timestamp' for convenience, using the CommonSecurityLog_TimeGenerated as its value
      | extend timestamp = CommonSecurityLog_TimeGenerated  
triggerOperator: gt
queryPeriod: 14d
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml
relevantTechniques:
- T1071
id: ec21493c-2684-4acd-9bc2-696dbad72426
requiredDataConnectors:
- connectorId: PaloAltoNetworks
  dataTypes:
  - CommonSecurityLog
- connectorId: ThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
version: 1.4.2
description: |
    'Identifies a match in Palo Alto data in CommonSecurityLog table from any Domain IOC from TI'
{
  "$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/ec21493c-2684-4acd-9bc2-696dbad72426')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/ec21493c-2684-4acd-9bc2-696dbad72426')]",
      "properties": {
        "alertRuleTemplateName": "ec21493c-2684-4acd-9bc2-696dbad72426",
        "customDetails": null,
        "description": "'Identifies a match in Palo Alto data in CommonSecurityLog table from any Domain IOC from TI'\n",
        "displayName": "TI map Domain entity to PaloAlto",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DeviceName",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIP",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "PA_Url",
                "identifier": "Url"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml",
        "query": "let dt_lookBack = 1h;  // Duration to look back for recent logs (1 hour)\nlet ioc_lookBack = 14d;  // Duration to look back for recent threat intelligence indicators (14 days)\n// Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains\nlet list_tlds = \n    ThreatIntelligenceIndicator\n    | where isnotempty(DomainName)\n    | where TimeGenerated >= ago(ioc_lookBack)\n    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n    | where Active == true and ExpirationDateTime > now()\n    | extend DomainName = tolower(DomainName)\n    | extend parts = split(DomainName, '.')\n    | extend tld = parts[(array_length(parts)-1)]\n    | summarize count() by tostring(tld)\n    | summarize make_list(tld);\nlet Domain_Indicators = \n    ThreatIntelligenceIndicator\n    // Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)\n    | where isnotempty(DomainName)\n    | where TimeGenerated >= ago(ioc_lookBack)\n    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n    | where Active == true and ExpirationDateTime > now()\n    | extend TI_DomainEntity = DomainName;\nDomain_Indicators\n    // Join with CommonSecurityLog to find potential malicious activity\n    | join kind=innerunique (\n        CommonSecurityLog\n        | extend IngestionTime = ingestion_time()\n        | where IngestionTime > ago(dt_lookBack)\n        | where DeviceVendor =~ 'Palo Alto Networks'\n        | where DeviceEventClassID =~ 'url'\n        // Uncomment the line below to only alert on allowed connections\n        // | where DeviceAction !~ \"block-url\"\n        // Extract domain from RequestURL, if not present, extract it from AdditionalExtensions\n        | extend PA_Url = coalesce(RequestURL, \"None\")\n        | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith \"PanOS\", extract(\"([^\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n        | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith \"http://\" and PA_Url !startswith \"https://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), PA_Url)\n        | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url)\n        | extend Domain = trim(@\"\"\"\", tostring(parse_url(PA_Url).Host))\n        | where isnotempty(Domain)\n        | extend Domain = tolower(Domain)\n        | extend parts = split(Domain, '.')\n        // Split out the top-level domain (TLD) for the purpose of checking if we have any TI indicators with this TLD to match on\n        | extend tld = parts[(array_length(parts)-1)]\n        // Validate parsed domain by checking TLD against TLDs from the threat feed and drop domains where there is no chance of a match\n        | where tld in~ (list_tlds)\n        | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n    ) on $left.TI_DomainEntity == $right.Domain\n    | where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n    // Group the results by IndicatorId and Domain and keep only the latest CommonSecurityLog_TimeGenerated\n    | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, Domain\n    // Select the desired fields for the final result set\n    | project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity\n    // Add a new field 'timestamp' for convenience, using the CommonSecurityLog_TimeGenerated as its value\n    | extend timestamp = CommonSecurityLog_TimeGenerated\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.4.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}