T1568.001

Fast Flux DNS

Adversaries may use Fast Flux DNS to hide a command and control channel behind an array of rapidly changing IP addresses linked to a single domain resolution. This technique uses a fully qualified domain name with multiple IP addresses assigned to it, swapped with high frequency using a combination of round-robin IP addressing and short Time-To-Live (TTL) DNS records. The simplest 'single-flux' method involves registering and de-registering addresses as part of the DNS A record list, with an average lifespan of five minutes per IP. The 'double-flux' method additionally rotates the DNS Name Server (NS) records for the zone, providing additional resilience by allowing additional hosts to act as proxies to the true C2 host. Real-world users of this technique include Amadey malware, TA505, gh0st RAT operators, njRAT, menuPass (APT10), and Gamaredon Group.

Microsoft Sentinel / Defender
kusto
// Fast Flux DNS Detection — Azure DNS Server Logs (DnsEvents)
// Detects domains resolving to an unusually high number of unique public IPs within a 1-hour window
let lookbackWindow = 1h;
let minUniqueIPThreshold = 5;
let minQueryCount = 3;
let KnownCDNDomains = dynamic([
  ".akamaiedge.net", ".akamaitechnologies.com", ".cloudfront.net",
  ".fastly.net", ".cloudflare.net", ".edgesuite.net",
  ".azureedge.net", ".trafficmanager.net", ".amazonaws.com",
  ".googleusercontent.com", ".gstatic.com"
]);
DnsEvents
| where TimeGenerated > ago(lookbackWindow)
| where SubType == "LookupQuery"
| where QueryType == "A" or QueryType == "AAAA"
| where ResultCode == 0
| where isnotempty(IPAddresses)
// Exclude known CDN domains by suffix
| where not(Name has_any (KnownCDNDomains))
// Exclude internal/trusted domains
| where not(Name matches regex @"\.(local|internal|corp|lan|home|arpa)$")
// Exclude Microsoft cloud services
| where not(Name endswith ".microsoft.com")
    and not(Name endswith ".windows.com")
    and not(Name endswith ".office.com")
    and not(Name endswith ".azure.com")
    and not(Name endswith ".live.com")
| mv-expand IPAddress = split(IPAddresses, ";")
| extend IPAddress = trim(" ", tostring(IPAddress))
| where isnotempty(IPAddress)
// Filter RFC1918 private and loopback addresses
| where not(IPAddress matches regex @"^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.|::1|0\.0\.0\.0)")
| summarize
    UniqueIPCount = dcount(IPAddress),
    IPAddressList = make_set(IPAddress, 100),
    QueryCount = count(),
    UniqueClients = dcount(ClientIP),
    ClientList = make_set(ClientIP, 20),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by Name
| where UniqueIPCount >= minUniqueIPThreshold
| where QueryCount >= minQueryCount
| extend ObservationMinutes = max_of(datetime_diff('minute', LastSeen, FirstSeen), 1)
| extend IPChurnRate = round(todouble(UniqueIPCount) / todouble(ObservationMinutes), 4)
| extend DomainParts = split(Name, ".")
| extend TLD = tostring(DomainParts[array_length(DomainParts) - 1])
| extend SLD = tostring(DomainParts[array_length(DomainParts) - 2])
| extend SuspiciousTLD = TLD in~ ("tk", "pw", "cc", "ws", "top", "xyz", "ru", "cn", "info", "online", "click", "link", "gq", "ml", "cf")
| extend ShortSLD = strlen(SLD) <= 8
| extend SuspicionScore = toint(SuspiciousTLD) + toint(ShortSLD) + iif(UniqueIPCount >= 10, 1, 0) + iif(UniqueClients >= 5, 1, 0)
| project
    DetectionTime = LastSeen,
    DomainName = Name,
    UniqueIPCount,
    IPChurnRate,
    QueryCount,
    UniqueClients,
    ClientList,
    IPAddressList,
    ObservationMinutes,
    TLD,
    SuspiciousTLD,
    ShortSLD,
    SuspicionScore,
    FirstSeen
| sort by UniqueIPCount desc, IPChurnRate desc
high severity medium confidence

Data Sources

Network Traffic: DNS Resolution Network Traffic: Network Traffic Flow Azure DNS Server Logs

Required Tables

DnsEvents

False Positives

  • Content Delivery Networks (Cloudflare, Akamai, AWS CloudFront, Fastly, Azure CDN) legitimately return many different IPs via anycast geo-routing — filter by known CDN domain suffixes or IP ranges
  • Global load-balanced SaaS services (Microsoft 365, Google Workspace, Zoom, Salesforce) return different IPs per geographic region — allowlist by domain suffix
  • Active/passive DNS failover configurations tested during disaster recovery drills — coordinate with network operations for change window exclusions
  • Internal DNS round-robin for on-premises load-balanced applications with multiple backend nodes — document and allowlist by internal domain name
  • Security research sinkholes — multiple decommissioned botnet C2 domains may resolve to sinkhole IPs operated by different vendors, appearing as high IP diversity

Unlock Pro Content

Get the full detection package for T1568.001 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections