Skip to main content
skill CX Codex

analyzing-dns-logs-for-exfiltration — Claude Code skill: catch DNS

Reads DNS query logs and hunts for tunneling, DGA domains and covert C2 channels. Useful when traffic slips past firewalls and proxies.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill analyzing-dns-logs-for-exfiltration -a claude-code
Open on GitHub

What analyzing-dns-logs-for-exfiltration does

The skill hands your agent ready-made Splunk queries plus a Python snippet that computes Shannon entropy over a domain or subdomain. High entropy together with long labels usually means data is packed into the subdomain. Query volume per host is scored too: a z-score above 3 or more than 5000 queries in an hour lands in the report.

Four steps run in order. Subdomain length analysis comes first, then DGA detection by vowel and digit ratios, then volume anomalies and TXT record abuse. The last step matches signatures of tools like dnscat and iodine, and flags traffic to public resolvers on port 443 — that pattern points to DoH bypassing local DNS.

It will not run on its own. You need DNS query logging turned on (Windows DNS Server, Bind, Infoblox or Cisco Umbrella), those logs ingested into a SIEM with the stream:dns sourcetype, passive DNS data and a baseline of normal behaviour. Entropy calculation needs Python with math and collections. Skip the baseline and thresholds like 50 characters in a subdomain will flood you with noise from legitimate services.

What it helps with

  • find the host leaking data out over a DNS tunnel
  • filter DGA domains by entropy and digit ratio
  • catch a DNS query spike from a single machine
  • check for TXT record abuse
  • spot DoH traffic to public resolvers bypassing local DNS

Example prompts for the agent

  • check the last 24 hours of DNS logs for tunneling
  • score subdomain entropy in these queries and list the suspicious ones
  • are there any dnscat or iodine lookups in the logs

How to install analyzing-dns-logs-for-exfiltration

1Skills CLI (Vercel)

npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill analyzing-dns-logs-for-exfiltration -a claude-code

2Manually: put the files in place

~/.claude/skills/analyzing-dns-logs-for-exfiltration/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/analyzing-dns-logs-for-exfiltration/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about analyzing-dns-logs-for-exfiltration

How do I install analyzing-dns-logs-for-exfiltration in Claude?

Run npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill analyzing-dns-logs-for-exfiltration -a claude-code. The skill file then sits at ~/.claude/skills/analyzing-dns-logs-for-exfiltration/SKILL.md.

What does analyzing-dns-logs-for-exfiltration do?

It analyzes DNS query logs for data exfiltration through tunneling, algorithmically generated domains and covert command-and-control channels. Detection leans on entropy, query volume anomalies and subdomain length.

What do I need before running it?

DNS query logging and ingestion into a SIEM with the stream:dns sourcetype, passive DNS data and a baseline of normal DNS behaviour. Entropy scoring needs Python with the math and collections libraries.

Source text

SKILL.md · Apache-2.0
---
name: analyzing-dns-logs-for-exfiltration
description: 'Analyzes DNS query logs to detect data exfiltration via DNS tunneling,
  DGA domain communication, and covert C2 channels using entropy analysis, query volume
  anomalies, and subdomain length detection in SIEM platforms. Use when SOC teams
  need to identify DNS-based threats that bypass traditional network security controls.

  '
domain: cybersecurity
subdomain: soc-operations
tags:
- soc
- dns
- exfiltration
- dns-tunneling
- dga
- c2-detection
- splunk
- threat-detection
version: '1.0'
author: mahipal
license: Apache-2.0
atlas_techniques:
- AML.T0024
- AML.T0056
- AML.T0086
nist_csf:
- DE.CM-01
- DE.AE-02
- RS.MA-01
- DE.AE-06
mitre_attack:
- T1048.003
- T1071.004
- T1567
---
# Analyzing DNS Logs for Exfiltration

## When to Use

Use this skill when:
- SOC teams suspect data exfiltration through DNS tunneling to bypass firewall/proxy controls
- Threat intelligence indicates adversaries using DNS-based C2 channels (e.g., Cobalt Strike DNS beacon)
- UEBA detects anomalous DNS query volumes from specific hosts
- Malware analysis reveals DNS-over-HTTPS (DoH) or DNS tunneling capabilities

**Do not use** for standard DNS troubleshooting or availability monitoring — this skill focuses on security-relevant DNS abuse detection.

## Prerequisites

- DNS query logging enabled (Windows DNS Server, Bind, Infoblox, or Cisco Umbrella)
- DNS logs ingested into SIEM (Splunk with `Stream:DNS`, `dns` sourcetype, or Zeek DNS logs)
- Passive DNS data for historical domain resolution analysis
- Baseline of normal DNS behavior (query volume, domain distribution, TXT record frequency)
- Python with `math` and `collections` libraries for entropy calculation

## Workflow

### Step 1: Detect DNS Tunneling via Subdomain Length Analysis

DNS tunneling encodes data in subdomain labels, creating unusually long queries:

```spl
index=dns sourcetype="stream:dns" query_type IN ("A", "AAAA", "TXT", "CNAME", "MX")
| eval domain_parts = split(query, ".")
| eval subdomain = mvindex(domain_parts, 0, mvcount(domain_parts)-3)
| eval subdomain_str = mvjoin(subdomain, ".")
| eval subdomain_len = len(subdomain_str)
| eval tld = mvindex(domain_parts, -1)
| eval registered_domain = mvindex(domain_parts, -2).".".tld
| where subdomain_len > 50
| stats count AS queries, dc(query) AS unique_queries,
        avg(subdomain_len) AS avg_subdomain_len,
        max(subdomain_len) AS max_subdomain_len,
        values(src_ip) AS sources
  by registered_domain
| where queries > 20
| sort - avg_subdomain_len
| table registered_domain, queries, unique_queries, avg_subdomain_len, max_subdomain_len, sources
```

### Step 2: Detect High-Entropy Domain Queries (DGA Detection)

Domain Generation Algorithms produce random-looking domains:

```spl
index=dns sourcetype="stream:dns"
| eval domain_parts = split(query, ".")
| eval sld = mvindex(domain_parts, -2)
| eval sld_len = len(sld)
| eval char_count = sld_len
| eval vowels = len(replace(sld, "[^aeiou]", ""))
| eval consonants = len(replace(sld, "[^bcdfghjklmnpqrstvwxyz]", ""))
| eval digits = len(replace(sld, "[^0-9]", ""))
| eval vowel_ratio = if(char_count > 0, vowels / char_count, 0)
| eval digit_ratio = if(char_count > 0, digits / char_count, 0)
| where sld_len > 12 AND (vowel_ratio < 0.2 OR digit_ratio > 0.3)
| stats count AS queries, dc(query) AS unique_domains, values(src_ip) AS sources
  by query
| where unique_domains > 10
| sort - queries
```

**Python-based Shannon Entropy Calculation for DNS queries:**

```python
import math
from collections import Counter

def shannon_entropy(text):
    """Calculate Shannon entropy of a string"""
    if not text:
        return 0
    counter = Counter(text.lower())
    length = len(text)
    entropy = -sum(
        (count / length) * math.log2(count / length)
        for count in counter.values()
    )
    return round(entropy, 4)

# Test with examples
normal_domain = "google"           # Low entropy
dga_domain = "x8kj2m9p4qw7n"      # High entropy
tunnel_subdomain = "aGVsbG8gd29ybGQ.evil.com"  # Base64 encoded data

print(f"Normal: {shannon_entropy(normal_domain)}")     # ~2.25
print(f"DGA:    {shannon_entropy(dga_domain)}")         # ~3.70
print(f"Tunnel: {shannon_entropy(tunnel_subdomain)}")   # ~3.50

# Threshold: entropy > 3.5 for subdomain = likely tunneling/DGA
```

**Splunk implementation of entropy scoring:**

```spl
index=dns sourcetype="stream:dns"
| eval domain_parts = split(query, ".")
| eval check_string = mvindex(domain_parts, 0)
| eval check_len = len(check_string)
| where check_len > 8
| eval chars = split(check_string, "")
| stats count AS total_chars, dc(chars) AS unique_chars by query, src_ip, check_string, check_len
| eval entropy_estimate = log(unique_chars, 2) * (unique_chars / check_len)
| where entropy_estimate > 3.5
| stats count AS high_entropy_queries, dc(query) AS unique_queries by src_ip
| where high_entropy_queries > 50
| sort - high_entropy_queries
```

### Step 3: Detect Anomalous DNS Query Volume

Identify hosts generating abnormal DNS traffic:

```spl
index=dns sourcetype="stream:dns" earliest=-24h
| bin _time span=1h
| stats count AS queries, dc(query) AS unique_domains by src_ip, _time
| eventstats avg(queries) AS avg_queries, stdev(queries) AS stdev_queries by src_ip
| eval z_score = (queries - avg_queries) / stdev_queries
| where z_score > 3 OR queries > 5000
| sort - z_score
| table _time, src_ip, queries, unique_domains, avg_queries, z_score
```

**Detect TXT record abuse (common tunneling method):**

```spl
index=dns sourcetype="stream:dns" query_type="TXT"
| stats count AS txt_queries, dc(query) AS unique_txt_domains,
        values(query) AS domains by src_ip
| where txt_queries > 100
| eval suspicion = case(
    txt_queries > 1000, "CRITICAL — Likely DNS tunneling",
    txt_queries > 500, "HIGH — Possible DNS tunneling",
    txt_queries > 100, "MEDIUM — Unusual TXT volume"
  )
| sort - txt_queries
| table src_ip, txt_queries, unique_txt_domains, suspicion
```

### Step 4: Detect Known DNS Tunneling Tools

Search for signatures of common DNS tunneling tools:

```spl
index=dns sourcetype="stream:dns"
| eval query_lower = lower(query)
| where (
    match(query_lower, "\.dnscat\.") OR
    match(query_lower, "\.dns2tcp\.") OR
    match(query_lower, "\.iodine\.") OR
    match(query_lower, "\.dnscapy\.") OR
    match(query_lower, "\.cobalt.*\.beacon") OR
    query_type="NULL" OR
    (query_type="TXT" AND len(query) > 100)
  )
| stats count by src_ip, query, query_type
| sort - count
```

**Detect DNS over HTTPS (DoH) bypassing local DNS:**

```spl
index=proxy OR index=firewall
dest IN ("1.1.1.1", "1.0.0.1", "8.8.8.8", "8.8.4.4",
         "9.9.9.9", "149.112.112.112", "208.67.222.222")
dest_port=443
| stats sum(bytes_out) AS total_bytes, count AS connections by src_ip, dest
| where connections > 100 OR total_bytes > 10485760
| eval alert = "Possible DoH bypass — DNS queries sent over HTTPS to public resolver"
| sort - total_bytes
```

### Step 5: Correlate DNS Findings with Endpoint Data

Cross-reference suspicious DNS with process data:

```spl
index=dns src_ip="192.168.1.105" query="*.evil-tunnel.com" earliest=-24h
| stats count AS dns_queries, earliest(_time) AS first_query, latest(_time) AS last_query
  by src_ip, query
| join src_ip [
    search index=sysmon EventCode=3 DestinationPort=53 Computer="WORKSTATION-042"
    | stats count AS connections, values(Image) AS processes by SourceIp
    | rename SourceIp AS src_ip
  ]
| table src_ip, query, dns_queries, first_query, last_query, processes
```

### Step 6: Calculate Data Exfiltration Volume Estimate

Estimate data volume encoded in DNS queries:

```spl
index=dns src_ip="192.168.1.105" query="*.evil-tunnel.com" earliest=-24h
| eval domain_parts = split(query, ".")
| eval encoded_data = mvindex(domain_parts, 0)
| eval encoded_bytes = len(encoded_data)
| eval decoded_bytes = encoded_bytes * 0.75  -- Base64 decoding factor
| stats sum(decoded_bytes) AS total_bytes_estimated, count AS total_queries,
        earliest(_time) AS first_seen, latest(_time) AS last_seen
| eval estimated_kb = round(total_bytes_estimated / 1024, 1)
| eval estimated_mb = round(total_bytes_estimated / 1048576, 2)
| eval duration_hours = round((last_seen - first_seen) / 3600, 1)
| eval rate_kbps = round(estimated_kb / (duration_hours * 3600) * 8, 2)
| table total_queries, estimated_mb, duration_hours, rate_kbps, first_seen, last_seen
```

## Key Concepts

| Term | Definition |
|------|-----------|
| **DNS Tunneling** | Technique encoding data within DNS queries/responses to exfiltrate data or establish C2 channels through DNS |
| **DGA** | Domain Generation Algorithm — malware technique generating pseudo-random domain names for C2 resilience |
| **Shannon Entropy** | Mathematical measure of randomness in a string — high entropy (>3.5) in domain names indicates DGA or tunneling |
| **TXT Record Abuse** | Using DNS TXT records (designed for text data) as a high-bandwidth channel for data tunneling |
| **DNS over HTTPS (DoH)** | DNS queries encrypted over HTTPS (port 443), bypassing traditional DNS monitoring |
| **Passive DNS** | Historical record of DNS resolutions showing which IPs a domain resolved to over time |

## Tools & Systems

- **Splunk Stream**: Network traffic capture add-on providing parsed DNS query data for SIEM analysis
- **Zeek (Bro)**: Network security monitor generating detailed DNS transaction logs for analysis
- **Cisco Umbrella (OpenDNS)**: Cloud DNS security platform blocking malicious domains and logging query data
- **Infoblox DNS Firewall**: DNS-layer security providing RPZ-based blocking and detailed query logging
- **Farsight DNSDB**: Passive DNS database for historical domain resolution lookups and infrastructure mapping

## Common Scenarios

- **Cobalt Strike DNS Beacon**: Detect periodic TXT queries with encoded payloads to C2 domain
- **Data Exfiltration**: Large volumes of unique subdomain queries encoding stolen data in Base64/hex
- **DGA Malware**: Detect DNS queries to algorithmically generated domains (high entropy, no web content)
- **DNS-over-HTTPS Bypass**: Employee using DoH to bypass corporate DNS filtering and monitoring
- **Slow Drip Exfiltration**: Low-volume DNS tunneling staying below threshold alerts (requires baseline comparison)

## Output Format

```
DNS EXFILTRATION ANALYSIS — WORKSTATION-042
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Period:       2024-03-14 to 2024-03-15
Source:       192.168.1.105 (WORKSTATION-042, Finance Dept)

Findings:
  [CRITICAL] DNS tunneling detected to evil-tunnel[.]com
    Query Volume:       12,847 queries in 18 hours
    Avg Subdomain Len:  63 characters (normal: <20)
    Avg Entropy:        3.82 (threshold: 3.5)
    Query Types:        TXT (89%), A (11%)
    Estimated Data:     ~4.7 MB exfiltrated via DNS
    Rate:               0.58 kbps (slow drip pattern)

  [HIGH] DGA-like domains resolved
    Unique DGA Domains: 247 domains resolved
    Pattern:            15-char random alphanumeric.xyz TLD
    Entropy Range:      3.6 - 4.1

Process Attribution:
  Process:   svchost_update.exe (masquerading — not legitimate svchost)
  PID:       4892
  Parent:    explorer.exe
  Hash:      SHA256: a1b2c3d4... (VT: 34/72 malicious — Cobalt Strike beacon)

Containment:
  [DONE] Host isolated via EDR
  [DONE] Domain evil-tunnel[.]com added to DNS sinkhole
  [DONE] Incident IR-2024-0448 created
```

© mahipal · Apache-2.0 · mukul975/Anthropic-Cybersecurity-Skills

Similar skills

Everything for Security →

From the same set89

testing-api-for-broken-object-level-authorization Tests REST and GraphQL APIs for BOLA and IDOR flaws by swapping object identifiers across requests. Helps detect broken access controls between different user accounts. CX Codex +1 541installs testing-jwt-token-security A skill that walks an agent through JWT weaknesses: algorithm confusion, weak HMAC secrets, authorization bypass. Built for API and SSO pentests. CX Codex +1 536installs analyzing-apt-group-with-mitre-navigator Queries ATT&CK data for APT groups and builds MITRE ATT&CK Navigator layers to compare TTP coverage and spot detection gaps. CX Codex +1 531installs analyzing-network-traffic-with-wireshark A skill that walks your agent through packet capture and analysis with Wireshark and tshark: C2 traffic, leaks, protocol faults. CX Codex +1 533installs analyzing-command-and-control-communication This skill examines malware C2 traffic to map protocols, beacon patterns, encoding, commands, and infrastructure. Use it when a PCAP needs protocol analysis or detection signatures. CX Codex +1 528installs testing-for-broken-access-control Guides testing of web apps and APIs for broken access control flaws under OWASP A01:2021. Useful during RBAC audits and multi-tenant data boundary checks. CX Codex +1 522installs analyzing-linux-audit-logs-for-intrusion Guides Linux intrusion investigations with auditd, ausearch, and aureport, configuring kernel audit rules and rebuilding attacker timelines. CX Codex +1 522installs exploiting-sql-injection-vulnerabilities Guides SQL injection testing across web applications during authorized security assessments. It helps audit database input handling and verify protection mechanisms. CX Codex +1 504installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor