Hunting for Beaconing with Frequency Analysis
When to Use
- When proactively searching for compromised endpoints calling back to C2 infrastructure
- After threat intelligence reports indicate active C2 frameworks targeting your sector
- When network logs show periodic outbound connections to unfamiliar destinations
- During purple team exercises validating C2 detection capabilities
- When investigating a potential breach and need to identify active C2 channels
Detection Gaps & Validation
- High jitter defeats CV thresholds: a
CV < 0.20 rule misses beacons configured with large jitter (Cobalt Strike jitter 50, or Sunburst's minutes-scale randomization) — widen the window, score on data-size consistency, and use FFT/autocorrelation rather than CV alone for jittered beacons.
- Long sleep / dormancy: beacons sleeping hours-to-days produce too few connections in a 24h window to be significant — extend the lookback to 7–14 days and lower the
min connections floor for rare destinations.
- Destination filtering breaks on domain fronting / cloud abuse: C2 over
*.cloudfront.net, Slack, Discord, Telegram, or Graph API rides allowlisted FQDNs — do not exclude major CDNs/SaaS wholesale; pivot on JA3/JA4 and bytes-out regularity instead.
- Log gaps: proxy logs that aggregate or sample connections destroy the inter-arrival timing the math depends on — confirm per-connection Zeek
conn.log/firewall records, not summarized flows.
- Validate: run Atomic Red Team T1071.001 or a Cobalt Strike/Sliver test profile with a known interval+jitter and confirm the SPL/KQL streamstats query surfaces it.
- Tune FPs: Windows Update, AV definition pulls, NTP, telemetry, and SaaS heartbeats are textbook periodic — allowlist by destination + process (Sysmon EID 1/3 correlation), not by interval alone.
Prerequisites
- Network proxy/firewall logs with timestamps and destination data (minimum 24 hours)
- Zeek conn.log, dns.log, and ssl.log or equivalent NetFlow/IPFIX data
- SIEM platform with statistical analysis capability (Splunk, Elastic, Microsoft Sentinel)
- RITA (Real Intelligence Threat Analytics) or AC-Hunter for automated beacon analysis
- Threat intelligence feeds for domain/IP reputation enrichment
Workflow
- Define Beacon Parameters: Establish detection thresholds -- coefficient of variation (CV) below 0.20 indicates strong periodicity, minimum 50 connections over 24 hours, average interval between 30 seconds and 24 hours.
- Collect Network Telemetry: Aggregate proxy logs, DNS queries, firewall connection logs, and Zeek metadata into the analysis platform.
- Calculate Connection Intervals: For each source-destination pair, compute the time delta between consecutive connections and derive mean interval, standard deviation, and CV.
- Apply Jitter Analysis: Sophisticated C2 frameworks like Cobalt Strike add jitter (randomness) to beacon intervals. The Sunburst backdoor beaconed every 15 minutes plus/minus 90 seconds. Analyze jitter patterns to detect even randomized beaconing.
- Filter Legitimate Periodic Traffic: Exclude known-good beaconing sources including Windows Update, antivirus definition updates, NTP synchronization, SaaS heartbeat services, and CDN health checks.
- Analyze Data Size Consistency: C2 heartbeat packets typically have consistent payload sizes. Calculate the CV of bytes transferred per connection -- low variance suggests automated communication.
- Enrich with Threat Intelligence: Check identified beaconing destinations against VirusTotal, WHOIS registration data (flag domains under 30 days old), certificate transparency logs, and passive DNS history.
- Correlate with Endpoint Telemetry: Map beaconing source IPs to endpoint hostnames via DHCP logs, then correlate with process creation events (Sysmon Event ID 1, 3) to identify the responsible process.
- Score and Prioritize: Assign risk scores based on CV value, domain age, TI matches, data size consistency, and suspicious port usage. Escalate high-confidence findings.
Key Concepts
| Concept |
Description |
| T1071.001 |
Application Layer Protocol: Web Protocols -- HTTP/HTTPS beaconing |
| T1071.004 |
Application Layer Protocol: DNS -- DNS-based C2 tunneling |
| T1573 |
Encrypted Channel -- TLS/SSL encrypted C2 communication |
| T1568.002 |
Dynamic Resolution: Domain Generation Algorithms |
| Coefficient of Variation |
Standard deviation divided by mean; values below 0.20 indicate periodicity |
| Jitter |
Random variation added to beacon interval to evade detection |
| RITA Beacon Score |
Composite score from connection regularity, data size consistency, and connection count |
| JA3/JA4 Fingerprinting |
TLS client fingerprinting to identify C2 framework signatures |
| Fast-Flux DNS |
Rapidly changing DNS resolution used to protect C2 infrastructure |
Tools & Systems
| Tool |
Purpose |
| RITA (Real Intelligence Threat Analytics) |
Automated beacon scoring from Zeek logs |
| AC-Hunter |
Commercial threat hunting platform with beacon detection |
| Splunk |
SPL-based statistical beacon analysis with streamstats |
| Elastic Security |
ML anomaly detection for periodic network behavior |
| Zeek |
Network metadata collection (conn.log, dns.log, ssl.log) |
| Suricata |
Network IDS with JA3/JA4 TLS fingerprint extraction |
| FLARE |
C2 profile and beacon pattern detection |
| VirusTotal |
Domain and IP reputation enrichment |
Detection Queries
Splunk -- HTTP/S Beacon Frequency Analysis
index=proxy OR index=firewall
| where NOT match(dest, "(?i)(microsoft|google|amazonaws|cloudflare|akamai)")
| bin _time span=1s
| stats count by src_ip dest _time
| streamstats current=f last(_time) as prev_time by src_ip dest
| eval interval=_time-prev_time
| stats count avg(interval) as avg_interval stdev(interval) as stdev_interval
min(interval) as min_interval max(interval) as max_interval by src_ip dest
| where count > 50
| eval cv=stdev_interval/avg_interval
| where cv < 0.20 AND avg_interval > 30 AND avg_interval < 86400
| sort cv
| table src_ip dest count avg_interval stdev_interval cv
KQL -- Microsoft Sentinel Beacon Detection
DeviceNetworkEvents
| where Timestamp > ago(24h)
| where RemoteIPType == "Public"
| summarize ConnectionTimes=make_list(Timestamp), Count=count() by DeviceName, RemoteIP, RemoteUrl
| where Count > 50
| extend Intervals = array_sort_asc(ConnectionTimes)
| mv-apply Intervals on (
extend NextTime = next(Intervals)
| where isnotempty(NextTime)
| extend IntervalSec = datetime_diff('second', NextTime, Intervals)
| summarize AvgInterval=avg(IntervalSec), StdDev=stdev(IntervalSec)
)
| extend CV = StdDev / AvgInterval
| where CV < 0.2 and AvgInterval > 30
| sort by CV asc
Sigma Rule -- Beaconing Pattern Detection
title: Potential C2 Beaconing Pattern Detected
status: experimental
logsource:
category: proxy
detection:
selection:
dst_ip|cidr: '!10.0.0.0/8'
timeframe: 24h
condition: selection | count(dst) by src_ip > 50
level: medium
tags:
- attack.command_and_control
- attack.t1071.001
Common Scenarios
- Cobalt Strike Beacon: Default 60-second interval with configurable 0-50% jitter over HTTPS. Malleable C2 profiles can mimic legitimate traffic patterns.
- Sunburst/SUNSPOT: 12-14 day dormancy period, then beaconing every 12-14 minutes with randomized jitter, designed to evade frequency analysis.
- DNS Tunneling C2: Encoded data exfiltration via DNS TXT/CNAME queries to attacker-controlled domains, detectable via high subdomain entropy and query volume.
- Sliver C2: Modern C2 framework with HTTPS, mTLS, and WireGuard protocols, configurable beacon intervals with built-in jitter support.
- Legitimate Service Abuse: C2 communication over Slack, Discord, Telegram, or cloud storage APIs, making destination-based filtering ineffective.
Output Format
Hunt ID: TH-BEACON-[DATE]-[SEQ]
Source IP: [Internal IP]
Source Host: [Hostname from DHCP/DNS]
Destination: [Domain/IP]
Protocol: [HTTP/HTTPS/DNS]
Beacon Interval: [Average seconds]
Jitter Estimate: [Percentage]
Coefficient of Variation: [CV value]
Connection Count: [Total connections in window]
Data Size CV: [Payload consistency metric]
Domain Age: [Days since registration]
TI Match: [Yes/No -- source]
Risk Score: [0-100]
Risk Level: [Critical/High/Medium/Low]
Indicators: [List of triggered risk factors]
1---2name: hunting-for-beaconing-with-frequency-analysis3description: Identify command-and-control beaconing patterns in network traffic by applying statistical frequency analysis, jitter calculation, and coefficient of variation scoring to detect periodic callbacks from compromised endpoints.4license: Apache-2.05---6
7# Hunting for Beaconing with Frequency Analysis
8
9## When to Use
10
11- When proactively searching for compromised endpoints calling back to C2 infrastructure
12- After threat intelligence reports indicate active C2 frameworks targeting your sector
13- When network logs show periodic outbound connections to unfamiliar destinations
14- During purple team exercises validating C2 detection capabilities
15- When investigating a potential breach and need to identify active C2 channels
16
17## Detection Gaps & Validation
18
19- **High jitter defeats CV thresholds:** a `CV < 0.20` rule misses beacons configured with large jitter (Cobalt Strike `jitter 50`, or Sunburst's minutes-scale randomization) — widen the window, score on data-size consistency, and use FFT/autocorrelation rather than CV alone for jittered beacons.
20- **Long sleep / dormancy:** beacons sleeping hours-to-days produce too few connections in a 24h window to be significant — extend the lookback to 7–14 days and lower the `min connections` floor for rare destinations.
21- **Destination filtering breaks on domain fronting / cloud abuse:** C2 over `*.cloudfront.net`, Slack, Discord, Telegram, or Graph API rides allowlisted FQDNs — do not exclude major CDNs/SaaS wholesale; pivot on JA3/JA4 and bytes-out regularity instead.
22- **Log gaps:** proxy logs that aggregate or sample connections destroy the inter-arrival timing the math depends on — confirm per-connection Zeek `conn.log`/firewall records, not summarized flows.
23- **Validate:** run Atomic Red Team **T1071.001** or a Cobalt Strike/Sliver test profile with a known interval+jitter and confirm the SPL/KQL streamstats query surfaces it.
24- **Tune FPs:** Windows Update, AV definition pulls, NTP, telemetry, and SaaS heartbeats are textbook periodic — allowlist by destination + process (Sysmon EID 1/3 correlation), not by interval alone.
25
26## Prerequisites
27
28- Network proxy/firewall logs with timestamps and destination data (minimum 24 hours)
29- Zeek conn.log, dns.log, and ssl.log or equivalent NetFlow/IPFIX data
30- SIEM platform with statistical analysis capability (Splunk, Elastic, Microsoft Sentinel)
31- RITA (Real Intelligence Threat Analytics) or AC-Hunter for automated beacon analysis
32- Threat intelligence feeds for domain/IP reputation enrichment
33
34## Workflow
35
361. **Define Beacon Parameters**: Establish detection thresholds -- coefficient of variation (CV) below 0.20 indicates strong periodicity, minimum 50 connections over 24 hours, average interval between 30 seconds and 24 hours.
372. **Collect Network Telemetry**: Aggregate proxy logs, DNS queries, firewall connection logs, and Zeek metadata into the analysis platform.
383. **Calculate Connection Intervals**: For each source-destination pair, compute the time delta between consecutive connections and derive mean interval, standard deviation, and CV.
394. **Apply Jitter Analysis**: Sophisticated C2 frameworks like Cobalt Strike add jitter (randomness) to beacon intervals. The Sunburst backdoor beaconed every 15 minutes plus/minus 90 seconds. Analyze jitter patterns to detect even randomized beaconing.
405. **Filter Legitimate Periodic Traffic**: Exclude known-good beaconing sources including Windows Update, antivirus definition updates, NTP synchronization, SaaS heartbeat services, and CDN health checks.
416. **Analyze Data Size Consistency**: C2 heartbeat packets typically have consistent payload sizes. Calculate the CV of bytes transferred per connection -- low variance suggests automated communication.
427. **Enrich with Threat Intelligence**: Check identified beaconing destinations against VirusTotal, WHOIS registration data (flag domains under 30 days old), certificate transparency logs, and passive DNS history.
438. **Correlate with Endpoint Telemetry**: Map beaconing source IPs to endpoint hostnames via DHCP logs, then correlate with process creation events (Sysmon Event ID 1, 3) to identify the responsible process.
449. **Score and Prioritize**: Assign risk scores based on CV value, domain age, TI matches, data size consistency, and suspicious port usage. Escalate high-confidence findings.
45
46## Key Concepts
47
48| Concept | Description |
49|---------|-------------|
50| T1071.001 | Application Layer Protocol: Web Protocols -- HTTP/HTTPS beaconing |
51| T1071.004 | Application Layer Protocol: DNS -- DNS-based C2 tunneling |
52| T1573 | Encrypted Channel -- TLS/SSL encrypted C2 communication |
53| T1568.002 | Dynamic Resolution: Domain Generation Algorithms |
54| Coefficient of Variation | Standard deviation divided by mean; values below 0.20 indicate periodicity |
55| Jitter | Random variation added to beacon interval to evade detection |
56| RITA Beacon Score | Composite score from connection regularity, data size consistency, and connection count |
57| JA3/JA4 Fingerprinting | TLS client fingerprinting to identify C2 framework signatures |
58| Fast-Flux DNS | Rapidly changing DNS resolution used to protect C2 infrastructure |
59
60## Tools & Systems
61
62| Tool | Purpose |
63|------|---------|
64| RITA (Real Intelligence Threat Analytics) | Automated beacon scoring from Zeek logs |
65| AC-Hunter | Commercial threat hunting platform with beacon detection |
66| Splunk | SPL-based statistical beacon analysis with streamstats |
67| Elastic Security | ML anomaly detection for periodic network behavior |
68| Zeek | Network metadata collection (conn.log, dns.log, ssl.log) |
69| Suricata | Network IDS with JA3/JA4 TLS fingerprint extraction |
70| FLARE | C2 profile and beacon pattern detection |
71| VirusTotal | Domain and IP reputation enrichment |
72
73## Detection Queries
74
75### Splunk -- HTTP/S Beacon Frequency Analysis
76```spl
77index=proxy OR index=firewall
78| where NOT match(dest, "(?i)(microsoft|google|amazonaws|cloudflare|akamai)")
79| bin _time span=1s
80| stats count by src_ip dest _time
81| streamstats current=f last(_time) as prev_time by src_ip dest
82| eval interval=_time-prev_time
83| stats count avg(interval) as avg_interval stdev(interval) as stdev_interval
84 min(interval) as min_interval max(interval) as max_interval by src_ip dest
85| where count > 50
86| eval cv=stdev_interval/avg_interval
87| where cv < 0.20 AND avg_interval > 30 AND avg_interval < 86400
88| sort cv
89| table src_ip dest count avg_interval stdev_interval cv
90```
91
92### KQL -- Microsoft Sentinel Beacon Detection
93```kql
94DeviceNetworkEvents
95| where Timestamp > ago(24h)
96| where RemoteIPType == "Public"
97| summarize ConnectionTimes=make_list(Timestamp), Count=count() by DeviceName, RemoteIP, RemoteUrl
98| where Count > 50
99| extend Intervals = array_sort_asc(ConnectionTimes)
100| mv-apply Intervals on (
101 extend NextTime = next(Intervals)
102 | where isnotempty(NextTime)
103 | extend IntervalSec = datetime_diff('second', NextTime, Intervals)
104 | summarize AvgInterval=avg(IntervalSec), StdDev=stdev(IntervalSec)
105)
106| extend CV = StdDev / AvgInterval
107| where CV < 0.2 and AvgInterval > 30
108| sort by CV asc
109```
110
111### Sigma Rule -- Beaconing Pattern Detection
112```yaml
113title: Potential C2 Beaconing Pattern Detected
114status: experimental
115logsource:
116 category: proxy
117detection:
118 selection:
119 dst_ip|cidr: '!10.0.0.0/8'
120 timeframe: 24h
121 condition: selection | count(dst) by src_ip > 50
122level: medium
123tags:
124 - attack.command_and_control
125 - attack.t1071.001
126```
127
128## Common Scenarios
129
1301. **Cobalt Strike Beacon**: Default 60-second interval with configurable 0-50% jitter over HTTPS. Malleable C2 profiles can mimic legitimate traffic patterns.
1312. **Sunburst/SUNSPOT**: 12-14 day dormancy period, then beaconing every 12-14 minutes with randomized jitter, designed to evade frequency analysis.
1323. **DNS Tunneling C2**: Encoded data exfiltration via DNS TXT/CNAME queries to attacker-controlled domains, detectable via high subdomain entropy and query volume.
1334. **Sliver C2**: Modern C2 framework with HTTPS, mTLS, and WireGuard protocols, configurable beacon intervals with built-in jitter support.
1345. **Legitimate Service Abuse**: C2 communication over Slack, Discord, Telegram, or cloud storage APIs, making destination-based filtering ineffective.
135
136## Output Format
137
138```
139Hunt ID: TH-BEACON-[DATE]-[SEQ]
140Source IP: [Internal IP]
141Source Host: [Hostname from DHCP/DNS]
142Destination: [Domain/IP]
143Protocol: [HTTP/HTTPS/DNS]
144Beacon Interval: [Average seconds]
145Jitter Estimate: [Percentage]
146Coefficient of Variation: [CV value]
147Connection Count: [Total connections in window]
148Data Size CV: [Payload consistency metric]
149Domain Age: [Days since registration]
150TI Match: [Yes/No -- source]
151Risk Score: [0-100]
152Risk Level: [Critical/High/Medium/Low]
153Indicators: [List of triggered risk factors]
154```