Skip to content
HackInvasionCybersecurity Knowledge Hub

Hunting DNS Tunneling and Data Exfiltration Over DNS

Cosmic illustration of a wireframe globe with swirling purple and orange particle streams forming tunnels, symbolizing DNS tunneling data exfiltration

Case file: the channel nobody watches

DNS is the most trusted protocol on the network. Firewalls let it through, proxies often ignore it, and almost nobody inspects the content of queries — which is exactly why attackers love it. DNS tunneling encodes stolen data inside subdomain labels (aGVsbG8td29ybGQtZGF0YQ.evil.example) or TXT record responses, turning every lookup into a tiny exfiltration packet. Tools from dnscat2 and iodine to custom malware beacons have used this channel for command-and-control and data theft for over a decade.

The investigative challenge is volume: a busy network generates millions of DNS queries a day, and the malicious ones hide inside them. This hunt doesn't look for known-bad domains — it looks for behavioral anomalies: query names that are too long, too random, too frequent, or pointed at record types (TXT, NULL) that legitimate clients rarely request. It maps to T1048.003 (Exfiltration Over Unencrypted Non-C2 Protocol) and T1071.004 (DNS C2).

The hypothesis

If a host is exfiltrating data or beaconing over DNS tunneling, then its DNS traffic will deviate from baseline: unusually long query names, high-entropy subdomain labels, abnormal query volume to a single domain, or heavy use of TXT/NULL record types — patterns not seen from that host's normal resolver behavior.

Data you'll need

Log sourceTable / indexWhat it gives you
Microsoft Defender for EndpointDeviceNetworkEventsPer-host DNS queries (RemoteUrl) on UDP/53
DNS server / firewall logsindex=dns or network data modelFull query names, query types, response sizes
Proxy / NetFlowZeek dns.log, CorelightQuery/response pairs, timing, periodicity analysis

Hunting with KQL

This query hunts the three strongest tunneling signals in Defender network telemetry: long query names, TXT/NULL record abuse, and high query volume concentrated on one domain.

// Hunt: DNS tunneling indicators in Defender network events
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemotePort == 53 and ActionType == "DnsQuery"
| where isnotempty(RemoteUrl)
| extend QueryLen = strlen(RemoteUrl),
         LabelCount = countof(RemoteUrl, "."),
         // crude entropy proxy: ratio of unique chars to length
         UniqueChars = array_length(set_union(split(RemoteUrl, ""))),
         HasLongLabel = RemoteUrl matches regex @"[A-Za-z0-9+/=]{40,}"
| extend SuspicionScore = (iff(QueryLen > 60, 2, 0)
    + iff(LabelCount > 5, 1, 0) + iff(HasLongLabel, 2, 0))
| summarize QueryCount = count(),
            AvgLen = avg(QueryLen),
            MaxLen = max(QueryLen),
            SampleQuery = take_any(RemoteUrl),
            MaxScore = max(SuspicionScore)
    by DeviceName, bin(TimeGenerated, 1h),
       Domain = tostring(split(RemoteUrl, ".")[-2])
| where QueryCount > 200 or MaxLen > 100 or MaxScore >= 3
| order by MaxScore desc, QueryCount desc

What this does: it aggregates DNS queries per host, per hour, per parent domain, then flags aggregates with high volume (200+ queries/hour to one domain suggests beaconing or bulk exfil), extreme query length, or long Base64-looking labels. The SampleQuery column gives you the smoking gun to eyeball.

Don't forget the record-type angle. Legitimate clients overwhelmingly query A/AAAA records. A host suddenly issuing TXT or NULL queries is worth a dedicated look:

// Hunt: rare DNS query types often abused for tunneling
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where RemotePort == 53
| where RemoteUrl has_any ("TXT", "NULL")  // adjust to your schema's query-type field
| summarize count() by DeviceName, RemoteUrl
| order by count_ desc
Example: what a true-positive result row looks like
DeviceNameWS-HR-0093
Domaintunnel-example.net (registered 6 days ago, no web presence)
QueryCount4,812 queries in one hour — steady ~1.3/sec cadence
SampleQueryd2VsY29tZS10by10aGUtanVuZ2xlLWJ1aWxkaW5nLWJsb2I.dat.tunnel-example.net (63-char label, valid Base64)
Why it's maliciousHigh-entropy labels that decode to structured data, metronomic timing, and a days-old domain — the classic signature of an active exfiltration tunnel, not browsing.

Hunting with Splunk

With full DNS logs (Zeek dns.log or Windows DNS debug logging), you can measure what Defender summaries can't — response sizes and true query-type distributions:

index=dns earliest=-7d
| eval qlen=len(query), labels=mvcount(split(query, "."))
| where qlen > 60 OR labels > 5 OR qtype IN ("TXT", "NULL", "CNAME")
| stats count as queries, avg(qlen) as avg_len, max(qlen) as max_len,
    values(qtype) as qtypes, earliest(_time) as first, latest(_time) as last
    by src_ip, query_suffix
| eval duration_min=round((last-first)/60, 1),
       rate_per_min=round(queries/duration_min, 1)
| where queries > 200 OR max_len > 100
| sort - queries

What this does: it filters to anomalous queries first (long names, deep label stacks, suspicious record types), then aggregates by source IP and domain suffix, computing duration and query rate. A steady rate over hours — rather than bursty human browsing — is the beaconing tell.

Example hit: src_ip=10.4.2.93 issues 4,812 queries to *.tunnel-example.net over 60 minutes at a near-constant 1.3 queries/second, all TXT type, with 63-character labels that decode from Base64 to structured chunks. No browser on that host ever visited the domain — the queries originate from a background service installed two days earlier. That's not name resolution; that's a data pipe wearing a DNS costume.

Validating the hit

  1. Decode the labels. Extract several query labels and Base64/hex-decode them in your analysis environment. Structured or compressible content (file fragments, keystrokes, hostnames) confirms exfiltration; random-looking session tokens suggest C2 beaconing.
  2. Profile the domain. Check WHOIS age, passive DNS history, and whether the domain resolves to anything via normal means. Tunneling domains are typically young, have no legitimate web presence, and are authoritative for their own NS records.
  3. Find the tunneling process. On the host, identify which process is generating the queries (Defender's InitiatingProcessFileName, or Sysmon DNS query events / EDR network telemetry). Look for recently installed services, scheduled tasks, or injected threads in legitimate processes.
  4. Measure the damage. Estimate total bytes moved: query count × average label size gives a rough exfiltration volume. Check DLP and file-access logs for what data the compromised account could reach.

Tuning out false positives

  • Antivirus and software telemetry: many AV products (and Chrome's Safe Browsing) issue long, hash-like DNS queries for reputation lookups. These go to well-known vendor domains at predictable patterns — whitelist the vendor domains, not the pattern.
  • DNS-based blocklists and SPF: mail servers generate heavy TXT traffic legitimately. Scope exclusions to your mail infrastructure hosts.
  • CDN and service-discovery names: long CNAME chains from CDNs and service meshes look odd but resolve to known providers. Baseline your top talkers before the hunt so anomalies stand out.

What to do next

Confirmed DNS tunneling means data is actively leaving — speed matters more than completeness at first. Block the tunneling domain at the DNS layer (sinkhole or RPZ) and at the firewall, then isolate the host. Identify and remove the tunneling implant, and rotate credentials for the affected user and any accounts whose data was in scope. Because DNS exfiltration is slow by design, assume a longer dwell time: pull DNS logs back 60–90 days and look for when the pattern started. Finally, treat this as a detection gap — consider DNS query logging on all resolvers and an analytics rule on the query-length/volume/volume-per-domain signals in this article, so the next tunnel trips an alert instead of a hunt.

Next in this series: Kerberoasting — hunting RC4 ticket requests that betray the attacker.


EmoticonEmoticon