<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: analyzing-dns-security-logs
description: >-
  Analyze DNS logs for security threats including C2 communication, data exfiltration,
  DNS tunneling, DGA domains, and DNS rebinding. Covers collection, enrichment,
  statistical analysis, and detection rule creation.
domain: cybersecurity
subdomain: blue-team
tags:
  - dns-security
  - threat-detection
  - network-monitoring
  - siem
  - c2-detection
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1071.004", "T1568"]
---

# Analyzing DNS Security Logs

## Overview

DNS is abused in nearly every stage of an attack — from initial reconnaissance to
C2 communication and data exfiltration. DNS logs provide high-value, low-noise
detection opportunities. This skill covers DNS log collection, threat pattern
identification, statistical anomaly detection, and automated alerting.

## Prerequisites

| Requirement | Install |
|---|---|
| Sysmon (EID 22) or DNS Server logs | Windows DNS telemetry |
| Zeek DNS logs | `zeek -i eth0` for network DNS capture |
| PassiveDNS | `passivedns -i eth0 -l /var/log/passivedns.log` |
| Python 3.10+ | Analysis scripts |
| SIEM with DNS data | Indexed DNS query logs |

## Key Concepts

### DNS Threat Patterns

| Pattern | Indicator | ATT&CK |
|---|---|---|
| DNS tunneling | Long subdomain labels (>50 chars), high query volume | T1071.004 |
| DGA domains | High entropy domain names, NXD responses | T1568.002 |
| DNS C2 | Periodic beacon patterns to rare domains | T1071.004 |
| Data exfiltration | Large TXT records, encoded subdomain data | T1048.003 |
| DNS rebinding | Rapid A record changes for same domain | T1584 |
| Fast flux | Many IPs resolving for single domain | T1568.001 |

### Detection Queries

```spl
| -- DNS tunneling: high-entropy long subdomains
index=dns query_type=TXT OR query_type=A
| eval subdomain=mvindex(split(query, "."), 0)
| eval sub_len=len(subdomain)
| where sub_len > 50
| stats count dc(query) AS unique_queries by src_ip, query
| where count > 100

| -- DGA detection: high entropy domain names
index=dns reply_code=NXDOMAIN
| eval domain_parts=split(query, ".")
| eval sld=mvindex(domain_parts, -2)
| eval entropy=0
| where len(sld) > 10
| stats count AS nxd_count by src_ip
| where nxd_count > 50

| -- DNS beaconing: periodic query patterns
index=dns
| bin _time span=1m
| stats count by _time, src_ip, query
| eventstats stdev(count) AS std, avg(count) AS avg by src_ip, query
| where std < 1 AND avg > 0
| stats count AS beacon_minutes by src_ip, query
| where beacon_minutes > 60
```

### Sigma Rules for DNS Threats

```yaml
title: Potential DNS Tunneling via Long Subdomain
id: d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a
status: experimental
description: Detects DNS queries with unusually long subdomain labels indicative of tunneling
logsource:
  category: dns_query
  product: windows
detection:
  selection:
    QueryName|re: '^[a-zA-Z0-9]{50,}\.'
  condition: selection
falsepositives:
  - CDN domains with long hashed subdomains
  - Certificate validation OCSP queries
level: medium
tags:
  - attack.command_and_control
  - attack.t1071.004
```

### Entropy Calculation

```python
import math
from collections import Counter

def shannon_entropy(domain: str) -> float:
    """Calculate Shannon entropy of a domain string."""
    counts = Counter(domain)
    length = len(domain)
    return -sum(
        (c / length) * math.log2(c / length)
        for c in counts.values()
    )

# Normal domain: ~3.0-3.5 entropy
# DGA domain: ~3.8-4.5+ entropy
```

## Workflow

1. **Enable DNS logging** — Sysmon EID 22, Windows DNS debug, or Zeek
2. **Forward to SIEM** — Ensure DNS logs are indexed and parsed
3. **Baseline normal** — Profile legitimate DNS patterns (top domains, query volume)
4. **Hunt anomalies** — Run statistical queries for tunneling, DGA, beaconing
5. **Enrich** — Cross-reference with threat intel feeds and WHOIS data
6. **Alert** — Create Sigma rules for confirmed threat patterns
7. **Block** — Feed confirmed malicious domains to DNS sinkhole/RPZ

## Verification

| Check | Method |
|---|---|
| DNS logs flowing | `index=dns earliest=-1h | stats count` returns data |
| Fields parsed | `query`, `query_type`, `reply_code`, `src_ip` populated |
| Baseline established | Top 1000 domains documented |
| Anomaly detection working | Test with known-bad DGA domain list |
| Alerts configured | Sigma rules deployed and firing |

## References

- [Sysmon DNS Query Logging](https://learn.microsoft.com/en-us/sysinternals/downloads/sysmon)
- [Zeek DNS Log Documentation](https://docs.zeek.org/en/current/scripts/base/protocols/dns/main.zeek.html)
- [SANS DNS Security Poster](https://www.sans.org/posters/dns-security/)
- [MITRE ATT&CK T1071.004](https://attack.mitre.org/techniques/T1071/004/)
