← Back to SOC feed Coverage →

Potential DGA detected (ASIM DNS Schema)

kql MEDIUM Azure-Sentinel
T1568T1008
DnsEvents
backdoormicrosoftofficial
This detection content is auto-generated from open-source rule repositories and enriched with AI analysis. Always validate rules in a test environment before deploying to production Sentinel workspaces.
View original rule at Azure-Sentinel →
Retrieved: 2026-03-19T03:46:59Z · Confidence: medium

Hunt Hypothesis

‘Identifies clients with a high NXDomain count which could be indicative of a DGA (cycling through possible C2 domains where most C2s are not live). Alert is generated when a new IP address is seen (b

KQL Query

let referencestarttime = 10d;
let referenceendtime = 1d;
let threshold = 100;
let nxDomainDnsEvents = (stime:datetime, etime:datetime) 
  {_Im_Dns(responsecodename='NXDOMAIN', starttime=stime, endtime=etime)
  | where DnsQueryTypeName in ("A", "AAAA")
  | where ipv4_is_match("127.0.0.1", SrcIpAddr) == False
  | where DnsQuery !contains "/" and  DnsQuery contains "."};
nxDomainDnsEvents (stime=ago(referenceendtime) ,etime=now())
  | extend sld = tostring(split(DnsQuery, ".")[-2])
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), dcount(sld) by SrcIpAddr
  | where dcount_sld > threshold
  // Filter out previously seen IPs
  | join kind=leftanti (nxDomainDnsEvents (stime=ago(referencestarttime), etime=ago(referenceendtime))
    | extend sld = tostring(split(DnsQuery, ".")[-2])
    | summarize dcount(sld) by SrcIpAddr
    | where dcount_sld > threshold ) on SrcIpAddr
// Pull out sample NXDomain responses for those remaining potentially infected IPs
| join kind = inner (nxDomainDnsEvents (stime=ago(referencestarttime), etime=now()) | summarize by DnsQuery, SrcIpAddr) on SrcIpAddr
| summarize StartTime = min(StartTime), EndTime = max(EndTime), sampleNXDomainList=make_list(DnsQuery, 100)  by SrcIpAddr, dcount_sld

Analytic Rule Definition

id: 983a6922-894d-413c-9f04-d7add0ecc307
name: Potential DGA detected (ASIM DNS Schema)
description: |
  'Identifies clients with a high NXDomain count which could be indicative of a DGA (cycling through possible C2 domains where most C2s are not live). Alert is generated when a new IP address is seen (based on not being seen associated with 
  NXDomain records in prior 10-day baseline period).
  This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema'
severity: Medium
requiredDataConnectors:
  - connectorId: DNS
    dataTypes:
      - DnsEvents
  - connectorId: AzureFirewall
    dataTypes: 
      - AzureDiagnostics
  - connectorId: Zscaler
    dataTypes:
      - CommonSecurityLog
  - connectorId: InfobloxNIOS
    dataTypes: 
      - Syslog
  - connectorId: GCPDNSDataConnector
    dataTypes: 
      - GCP_DNS_CL
  - connectorId: NXLogDnsLogs
    dataTypes: 
      - NXLog_DNS_Server_CL
  - connectorId: CiscoUmbrellaDataConnector
    dataTypes: 
      - Cisco_Umbrella_dns_CL
  - connectorId: Corelight
    dataTypes: 
      - Corelight_CL

queryFrequency: 1d
queryPeriod: 10d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - CommandAndControl
relevantTechniques:
  - T1568
  - T1008
tags:
  - ParentAlert: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/DnsEvents/DNS_HighNXDomainCount_detection.yaml
    version: 1.0.0
  - Schema: ASIMDns
    SchemaVersion: 0.1.1
query: |
  let referencestarttime = 10d;
  let referenceendtime = 1d;
  let threshold = 100;
  let nxDomainDnsEvents = (stime:datetime, etime:datetime) 
    {_Im_Dns(responsecodename='NXDOMAIN', starttime=stime, endtime=etime)
    | where DnsQueryTypeName in ("A", "AAAA")
    | where ipv4_is_match("127.0.0.1", SrcIpAddr) == False
    | where DnsQuery !contains "/" and  DnsQuery contains "."};
  nxDomainDnsEvents (stime=ago(referenceendtime) ,etime=now())
    | extend sld = tostring(split(DnsQuery, ".")[-2])
    | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), dcount(sld) by SrcIpAddr
    | where dcount_sld > threshold
    // Filter out previously seen IPs
    | join kind=leftanti (nxDomainDnsEvents (stime=ago(referencestarttime), etime=ago(referenceendtime))
      | extend sld = tostring(split(DnsQuery, ".")[-2])
      | summarize dcount(sld) by SrcIpAddr
      | where dcount_sld > threshold ) on SrcIpAddr
  // Pull out sample NXDomain responses for those remaining potentially infected IPs
  | join kind = inner (nxDomainDnsEvents (stime=ago(referencestarttime), etime=now()) | summarize by DnsQuery, SrcIpAddr) on SrcIpAddr
  | summarize StartTime = min(StartTime), EndTime = max(EndTime), sampleNXDomainList=make_list(DnsQuery, 100)  by SrcIpAddr, dcount_sld
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: SrcIpAddr
version: 1.3.4
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Yaron
    

Required Data Sources

Sentinel TableNotes
DnsEventsEnsure this data connector is enabled

MITRE ATT&CK Context

References

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Detections/ASimDNS/imDns_HighNXDomainCount_detection.yaml