Back
Id2d7b90c5-41ae-4f83-a6d2-9b1c5e3407fa
RulenameDatazag - retro-hunt historical DNS against impersonation indicators
DescriptionMatches Datazag impersonation indicators against historical ASIM-normalized DNS to surface domains resolved inside the estate before the feed was connected. Adjust dns_lookback to your DNS retention. Requires ASIM DNS parsers.
TacticsInitialAccess
CommandAndControl
TechniquesT1566
T1071
Required data connectorsThreatIntelligenceTaxii
KindHunting
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Datazag/Hunting%20Queries/DatazagRetroHunt_DNS.yaml
Version1.0.0
Arm template2d7b90c5-41ae-4f83-a6d2-9b1c5e3407fa.json
Deploy To Azure
let datazag_identity = "identity--55a5a448-c6f1-5128-bc71-4d85b719131e";
let dns_lookback = 90d;
let confidence_floor = 85;
let DatazagDomains =
    ThreatIntelIndicators
    | where tostring(Data.created_by_ref) == datazag_identity
    | where ObservableKey == "domain-name:value"
    | where isnotempty(ObservableValue)
    | summarize arg_max(TimeGenerated, *) by Id
    | where IsDeleted == false
    | where tostring(Data.revoked) != "true"
    | where Confidence >= confidence_floor
    | extend IndicatorDomain = tolower(trim_end(@"\.", ObservableValue))
    | project
        IndicatorDomain,
        DatazagAlertRef = tostring(Data.external_references[0].external_id),
        Confidence,
        IndicatorEvidence = tostring(Data.labels),
        IndicatorFirstPublished = todatetime(Data.created);
let DnsActivity =
    _Im_Dns
    | where TimeGenerated >= ago(dns_lookback)
    | where isnotempty(DnsQuery)
    | extend IndicatorDomain = tolower(trim_end(@"\.", DnsQuery))
    | project
        DnsTime         = TimeGenerated,
        IndicatorDomain,
        SrcIpAddr       = column_ifexists("SrcIpAddr", ""),
        SrcHostname     = column_ifexists("SrcHostname", ""),
        SrcUsername     = column_ifexists("SrcUsername", ""),
        SrcUsernameType = column_ifexists("SrcUsernameType", "");
DatazagDomains
| join kind=innerunique DnsActivity on IndicatorDomain
| summarize
    FirstResolved = min(DnsTime),
    LastResolved  = max(DnsTime),
    QueryCount    = count(),
    SourceIps     = make_set(SrcIpAddr, 100),
    SourceHosts   = make_set(SrcHostname, 100),
    Upns          = make_set_if(SrcUsername, SrcUsernameType == "UPN", 100)
    by IndicatorDomain, DatazagAlertRef, Confidence, IndicatorEvidence, IndicatorFirstPublished
| extend
    SourceIp      = tostring(SourceIps[0]),
    SourceHost    = tostring(SourceHosts[0]),
    AccountUpn    = tostring(Upns[0]),
    HostsAffected = array_length(SourceHosts),
    DaysBeforeIndicator = datetime_diff('day', IndicatorFirstPublished, FirstResolved)
| order by FirstResolved asc
id: 2d7b90c5-41ae-4f83-a6d2-9b1c5e3407fa
requiredDataConnectors:
- connectorId: ThreatIntelligenceTaxii
  dataTypes:
  - ThreatIntelIndicators
description: |
  Matches Datazag impersonation indicators against historical ASIM-normalized DNS to surface domains resolved inside the estate before the feed was connected. Adjust dns_lookback to your DNS retention. Requires ASIM DNS parsers.
name: Datazag - retro-hunt historical DNS against impersonation indicators
version: 1.0.0
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Datazag/Hunting%20Queries/DatazagRetroHunt_DNS.yaml
entityMappings:
- fieldMappings:
  - identifier: DomainName
    columnName: IndicatorDomain
  entityType: DNS
- fieldMappings:
  - identifier: Address
    columnName: SourceIp
  entityType: IP
- fieldMappings:
  - identifier: HostName
    columnName: SourceHost
  entityType: Host
- fieldMappings:
  - identifier: FullName
    columnName: AccountUpn
  entityType: Account
tactics:
- InitialAccess
- CommandAndControl
kind: Hunting
relevantTechniques:
- T1566
- T1071
query: |
  let datazag_identity = "identity--55a5a448-c6f1-5128-bc71-4d85b719131e";
  let dns_lookback = 90d;
  let confidence_floor = 85;
  let DatazagDomains =
      ThreatIntelIndicators
      | where tostring(Data.created_by_ref) == datazag_identity
      | where ObservableKey == "domain-name:value"
      | where isnotempty(ObservableValue)
      | summarize arg_max(TimeGenerated, *) by Id
      | where IsDeleted == false
      | where tostring(Data.revoked) != "true"
      | where Confidence >= confidence_floor
      | extend IndicatorDomain = tolower(trim_end(@"\.", ObservableValue))
      | project
          IndicatorDomain,
          DatazagAlertRef = tostring(Data.external_references[0].external_id),
          Confidence,
          IndicatorEvidence = tostring(Data.labels),
          IndicatorFirstPublished = todatetime(Data.created);
  let DnsActivity =
      _Im_Dns
      | where TimeGenerated >= ago(dns_lookback)
      | where isnotempty(DnsQuery)
      | extend IndicatorDomain = tolower(trim_end(@"\.", DnsQuery))
      | project
          DnsTime         = TimeGenerated,
          IndicatorDomain,
          SrcIpAddr       = column_ifexists("SrcIpAddr", ""),
          SrcHostname     = column_ifexists("SrcHostname", ""),
          SrcUsername     = column_ifexists("SrcUsername", ""),
          SrcUsernameType = column_ifexists("SrcUsernameType", "");
  DatazagDomains
  | join kind=innerunique DnsActivity on IndicatorDomain
  | summarize
      FirstResolved = min(DnsTime),
      LastResolved  = max(DnsTime),
      QueryCount    = count(),
      SourceIps     = make_set(SrcIpAddr, 100),
      SourceHosts   = make_set(SrcHostname, 100),
      Upns          = make_set_if(SrcUsername, SrcUsernameType == "UPN", 100)
      by IndicatorDomain, DatazagAlertRef, Confidence, IndicatorEvidence, IndicatorFirstPublished
  | extend
      SourceIp      = tostring(SourceIps[0]),
      SourceHost    = tostring(SourceHosts[0]),
      AccountUpn    = tostring(Upns[0]),
      HostsAffected = array_length(SourceHosts),
      DaysBeforeIndicator = datetime_diff('day', IndicatorFirstPublished, FirstResolved)
  | order by FirstResolved asc
{
  "$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/2d7b90c5-41ae-4f83-a6d2-9b1c5e3407fa')]",
      "kind": "Hunting",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/2d7b90c5-41ae-4f83-a6d2-9b1c5e3407fa')]",
      "properties": {
        "alertRuleTemplateName": "2d7b90c5-41ae-4f83-a6d2-9b1c5e3407fa",
        "customDetails": null,
        "description": "Matches Datazag impersonation indicators against historical ASIM-normalized DNS to surface domains resolved inside the estate before the feed was connected. Adjust dns_lookback to your DNS retention. Requires ASIM DNS parsers.\n",
        "displayName": "Datazag - retro-hunt historical DNS against impersonation indicators",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "DNS",
            "fieldMappings": [
              {
                "columnName": "IndicatorDomain",
                "identifier": "DomainName"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SourceIp",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "SourceHost",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "AccountUpn",
                "identifier": "FullName"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Datazag/Hunting%20Queries/DatazagRetroHunt_DNS.yaml",
        "query": "let datazag_identity = \"identity--55a5a448-c6f1-5128-bc71-4d85b719131e\";\nlet dns_lookback = 90d;\nlet confidence_floor = 85;\nlet DatazagDomains =\n    ThreatIntelIndicators\n    | where tostring(Data.created_by_ref) == datazag_identity\n    | where ObservableKey == \"domain-name:value\"\n    | where isnotempty(ObservableValue)\n    | summarize arg_max(TimeGenerated, *) by Id\n    | where IsDeleted == false\n    | where tostring(Data.revoked) != \"true\"\n    | where Confidence >= confidence_floor\n    | extend IndicatorDomain = tolower(trim_end(@\"\\.\", ObservableValue))\n    | project\n        IndicatorDomain,\n        DatazagAlertRef = tostring(Data.external_references[0].external_id),\n        Confidence,\n        IndicatorEvidence = tostring(Data.labels),\n        IndicatorFirstPublished = todatetime(Data.created);\nlet DnsActivity =\n    _Im_Dns\n    | where TimeGenerated >= ago(dns_lookback)\n    | where isnotempty(DnsQuery)\n    | extend IndicatorDomain = tolower(trim_end(@\"\\.\", DnsQuery))\n    | project\n        DnsTime         = TimeGenerated,\n        IndicatorDomain,\n        SrcIpAddr       = column_ifexists(\"SrcIpAddr\", \"\"),\n        SrcHostname     = column_ifexists(\"SrcHostname\", \"\"),\n        SrcUsername     = column_ifexists(\"SrcUsername\", \"\"),\n        SrcUsernameType = column_ifexists(\"SrcUsernameType\", \"\");\nDatazagDomains\n| join kind=innerunique DnsActivity on IndicatorDomain\n| summarize\n    FirstResolved = min(DnsTime),\n    LastResolved  = max(DnsTime),\n    QueryCount    = count(),\n    SourceIps     = make_set(SrcIpAddr, 100),\n    SourceHosts   = make_set(SrcHostname, 100),\n    Upns          = make_set_if(SrcUsername, SrcUsernameType == \"UPN\", 100)\n    by IndicatorDomain, DatazagAlertRef, Confidence, IndicatorEvidence, IndicatorFirstPublished\n| extend\n    SourceIp      = tostring(SourceIps[0]),\n    SourceHost    = tostring(SourceHosts[0]),\n    AccountUpn    = tostring(Upns[0]),\n    HostsAffected = array_length(SourceHosts),\n    DaysBeforeIndicator = datetime_diff('day', IndicatorFirstPublished, FirstResolved)\n| order by FirstResolved asc\n",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl",
          "InitialAccess"
        ],
        "techniques": [
          "T1071",
          "T1566"
        ],
        "templateVersion": "1.0.0"
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}