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
TacticsImpact
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.1
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
kind: Scheduled
queryPeriod: 14d
description: |
    'Identifies a match in Palo Alto data in CommonSecurityLog table from any Domain IOC from TI'
tactics:
- Impact
id: ec21493c-2684-4acd-9bc2-696dbad72426
requiredDataConnectors:
- connectorId: PaloAltoNetworks
  dataTypes:
  - CommonSecurityLog
- connectorId: ThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
severity: Medium
version: 1.4.1
entityMappings:
- entityType: Host
  fieldMappings:
  - identifier: HostName
    columnName: DeviceName
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: SourceIP
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: PA_Url
name: TI map Domain entity to PaloAlto
triggerOperator: gt
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  
queryFrequency: 1h
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml
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": "2023-02-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",
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Impact"
        ],
        "templateVersion": "1.4.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}