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

Threat Connect TI map Domain entity to DnsEvents

Back
Idf8960f1c-07d2-512b-9c41-952772d40c84
RulenameThreat Connect TI map Domain entity to DnsEvents
DescriptionIdentifies a match in DnsEvents from any ThreatConnect Domain IOC from TI
SeverityMedium
TacticsCommandAndControl
TechniquesT1071
Required data connectorsASimDnsActivityLogs
DNS
MicrosoftDefenderThreatIntelligence
ThreatIntelligence
ThreatIntelligenceTaxii
KindScheduled
Query frequency1h
Query period7d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/ThreatConnect/Analytic Rules/ThreatConnect_DomainEntity_DnsEvents.yaml
Version1.0.2
Arm templatef8960f1c-07d2-512b-9c41-952772d40c84.json
Deploy To Azure
// Define the lookback periods for time-based filters
let dt_lookBack = 1h; // Look back 1 hour for DNS events
let ioc_lookBack = 7d; // Look back 7 days for threat intelligence indicators
// Fetch threat intelligence indicators related to domains
let Domain_Indicators = ThreatIntelligenceIndicator
  | where TimeGenerated >= ago(ioc_lookBack)
  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
  | where ExpirationDateTime > now() and Active == true
  // Filter out non ThreatConnect TI Sources
  | where SourceSystem startswith "ThreatConnect-"
  // Filter out indicators without domain names
  | where isnotempty(DomainName)
  | extend TI_DomainEntity = DomainName;
// Create a list of TLDs in our threat feed for later validation
let maxListSize = 100000; // Define the maximum allowed size for each list
let list_tlds = Domain_Indicators
  | extend parts = split(DomainName, '.')
  | extend tld = parts[(array_length(parts)-1)]
  | summarize count() by tostring(tld)
  | project tld
  | summarize make_list(tld, maxListSize);
// Perform a join between domain indicators and DNS events to identify potential malicious activity
Domain_Indicators
  // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
  | join kind=innerunique (
    DnsEvents
    | where TimeGenerated > ago(dt_lookBack)
    // Extract domain patterns from syslog message
    | where isnotempty(Name)
    | extend parts = split(Name, '.')
    | extend tld = parts[(array_length(parts)-1)]
    // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed
    | where tld in~ (list_tlds)
    | extend DNS_TimeGenerated = TimeGenerated
  ) on $left.TI_DomainEntity==$right.Name
  // Filter out DNS events that occurred after the expiration of the corresponding indicator
  | where DNS_TimeGenerated < ExpirationDateTime
  // Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp
  | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name
  // Select the desired output fields
  | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, Computer, ClientIP, Name, QueryType, Type, TI_DomainEntity
  // Extract hostname and DNS domain from the Computer field
  | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))
  // Rename the timestamp field
  | extend timestamp = DNS_TimeGenerated
entityMappings:
- entityType: Host
  fieldMappings:
  - identifier: HostName
    columnName: HostName
  - identifier: DnsDomain
    columnName: DnsDomain
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: ClientIP
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: Url
name: Threat Connect TI map Domain entity to DnsEvents
tactics:
- CommandAndControl
severity: Medium
triggerThreshold: 0
relevantTechniques:
- T1071
id: f8960f1c-07d2-512b-9c41-952772d40c84
version: 1.0.2
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/ThreatConnect/Analytic Rules/ThreatConnect_DomainEntity_DnsEvents.yaml
queryFrequency: 1h
triggerOperator: gt
query: |
  // Define the lookback periods for time-based filters
  let dt_lookBack = 1h; // Look back 1 hour for DNS events
  let ioc_lookBack = 7d; // Look back 7 days for threat intelligence indicators
  // Fetch threat intelligence indicators related to domains
  let Domain_Indicators = ThreatIntelligenceIndicator
    | where TimeGenerated >= ago(ioc_lookBack)
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | where ExpirationDateTime > now() and Active == true
    // Filter out non ThreatConnect TI Sources
    | where SourceSystem startswith "ThreatConnect-"
    // Filter out indicators without domain names
    | where isnotempty(DomainName)
    | extend TI_DomainEntity = DomainName;
  // Create a list of TLDs in our threat feed for later validation
  let maxListSize = 100000; // Define the maximum allowed size for each list
  let list_tlds = Domain_Indicators
    | extend parts = split(DomainName, '.')
    | extend tld = parts[(array_length(parts)-1)]
    | summarize count() by tostring(tld)
    | project tld
    | summarize make_list(tld, maxListSize);
  // Perform a join between domain indicators and DNS events to identify potential malicious activity
  Domain_Indicators
    // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation
    | join kind=innerunique (
      DnsEvents
      | where TimeGenerated > ago(dt_lookBack)
      // Extract domain patterns from syslog message
      | where isnotempty(Name)
      | extend parts = split(Name, '.')
      | extend tld = parts[(array_length(parts)-1)]
      // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed
      | where tld in~ (list_tlds)
      | extend DNS_TimeGenerated = TimeGenerated
    ) on $left.TI_DomainEntity==$right.Name
    // Filter out DNS events that occurred after the expiration of the corresponding indicator
    | where DNS_TimeGenerated < ExpirationDateTime
    // Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp
    | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name
    // Select the desired output fields
    | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, Computer, ClientIP, Name, QueryType, Type, TI_DomainEntity
    // Extract hostname and DNS domain from the Computer field
    | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))
    // Rename the timestamp field
    | extend timestamp = DNS_TimeGenerated  
description: |
    Identifies a match in DnsEvents from any ThreatConnect Domain IOC from TI
requiredDataConnectors:
- connectorId: DNS
  dataTypes:
  - DnsEvents
- connectorId: ASimDnsActivityLogs
  dataTypes:
  - DnsEvents
- connectorId: ThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: ThreatIntelligenceTaxii
  dataTypes:
  - ThreatIntelligenceIndicator
- connectorId: MicrosoftDefenderThreatIntelligence
  dataTypes:
  - ThreatIntelligenceIndicator
queryPeriod: 7d
kind: Scheduled
{
  "$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/f8960f1c-07d2-512b-9c41-952772d40c84')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/f8960f1c-07d2-512b-9c41-952772d40c84')]",
      "properties": {
        "alertRuleTemplateName": "f8960f1c-07d2-512b-9c41-952772d40c84",
        "customDetails": null,
        "description": "Identifies a match in DnsEvents from any ThreatConnect Domain IOC from TI\n",
        "displayName": "Threat Connect TI map Domain entity to DnsEvents",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "HostName",
                "identifier": "HostName"
              },
              {
                "columnName": "DnsDomain",
                "identifier": "DnsDomain"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "ClientIP",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "Url",
                "identifier": "Url"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/ThreatConnect/Analytic Rules/ThreatConnect_DomainEntity_DnsEvents.yaml",
        "query": "// Define the lookback periods for time-based filters\nlet dt_lookBack = 1h; // Look back 1 hour for DNS events\nlet ioc_lookBack = 7d; // Look back 7 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to domains\nlet Domain_Indicators = ThreatIntelligenceIndicator\n  | where TimeGenerated >= ago(ioc_lookBack)\n  | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n  | where ExpirationDateTime > now() and Active == true\n  // Filter out non ThreatConnect TI Sources\n  | where SourceSystem startswith \"ThreatConnect-\"\n  // Filter out indicators without domain names\n  | where isnotempty(DomainName)\n  | extend TI_DomainEntity = DomainName;\n// Create a list of TLDs in our threat feed for later validation\nlet maxListSize = 100000; // Define the maximum allowed size for each list\nlet list_tlds = Domain_Indicators\n  | extend parts = split(DomainName, '.')\n  | extend tld = parts[(array_length(parts)-1)]\n  | summarize count() by tostring(tld)\n  | project tld\n  | summarize make_list(tld, maxListSize);\n// Perform a join between domain indicators and DNS events to identify potential malicious activity\nDomain_Indicators\n  // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n  | join kind=innerunique (\n    DnsEvents\n    | where TimeGenerated > ago(dt_lookBack)\n    // Extract domain patterns from syslog message\n    | where isnotempty(Name)\n    | extend parts = split(Name, '.')\n    | extend tld = parts[(array_length(parts)-1)]\n    // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n    | where tld in~ (list_tlds)\n    | extend DNS_TimeGenerated = TimeGenerated\n  ) on $left.TI_DomainEntity==$right.Name\n  // Filter out DNS events that occurred after the expiration of the corresponding indicator\n  | where DNS_TimeGenerated < ExpirationDateTime\n  // Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp\n  | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name\n  // Select the desired output fields\n  | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, Computer, ClientIP, Name, QueryType, Type, TI_DomainEntity\n  // Extract hostname and DNS domain from the Computer field\n  | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n  // Rename the timestamp field\n  | extend timestamp = DNS_TimeGenerated\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P7D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.2",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}