Whatever tool the adversary uses, the stolen data has to cross your perimeter. Volume alone is a noisy signal, but volume measured against a per-host baseline, weighted by destination rarity and time of day, is one of the most reliable egress detections you can build from telemetry you already collect.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| Hourly bytes-out far above the host’s own 14-day baseline | Firewall, Zeek conn.log | T1030 |
| Large upload to a destination never seen from this host | Firewall, proxy | T1041 |
| Server or workstation with an upload/download ratio inverted from its role | Flow data | T1041 |
| Many equal-sized transfers just under a size threshold | Flow data, proxy | T1030 |
| Outbound volume outside business hours | Firewall, proxy | T1041 |
Building the Baseline
Baseline each internal source on its own history rather than against a global threshold. A build server and a receptionist’s laptop have nothing in common. Compare the current hour against the host’s trailing percentile and require a rare destination before you alert:
// Sentinel (KQL) - per-host bytes-out vs 14-day baseline // tune/validate: field names assume CEF firewall logs in CommonSecurityLog let baseline = CommonSecurityLog | where TimeGenerated between (ago(14d) .. ago(1d)) | where DeviceAction == "allow" and ipv4_is_private(DestinationIP) == false | summarize hourly = sum(SentBytes) by SourceIP, bin(TimeGenerated, 1h) | summarize p95 = percentile(hourly, 95), mean = avg(hourly), sd = stdev(hourly) by SourceIP; let seen = CommonSecurityLog | where TimeGenerated between (ago(14d) .. ago(1d)) | summarize by SourceIP, DestinationIP; CommonSecurityLog | where TimeGenerated > ago(1h) | where DeviceAction == "allow" and ipv4_is_private(DestinationIP) == false | summarize bytesOut = sum(SentBytes) by SourceIP, DestinationIP | join kind=leftanti seen on SourceIP, DestinationIP | join kind=inner baseline on SourceIP | extend z = (bytesOut - mean) / max_of(sd, 1.0) | where bytesOut > 100000000 and bytesOut > 3 * p95 and z > 4 | order by bytesOut desc
Zeek gives you the same view without a firewall licence. Sum orig_bytes per originator and rank by the number of distinct external responders it fed:
index=zeek sourcetype="bro:conn:json" local_orig=true local_resp=false | rename "id.orig_h" as src, "id.resp_h" as dest | stats sum(orig_bytes) as bytes_out dc(dest) as dests values(service) as services by src | eval mb_out = round(bytes_out / 1048576, 1) | where mb_out > 500 | sort - mb_out ``` tune/validate: add a lookup of approved backup and sync targets, then exclude them ```
Catching Size-Capped Egress
Operators who know about volume alerts split the data. The result is many transfers of similar size just under a limit, or a steady stream to one destination. Look at counts and size variance as well as totals:
- Alert on a source with more than 20 outbound sessions to one new destination in a day where the standard deviation of session size is under 10 percent of the mean.
- Weight by destination rarity: a first-seen ASN or a newly registered domain turns a mediocre volume signal into a strong one.
- Exclude sanctioned bulk flows by identity, not just IP — backup agents, EDR telemetry and software distribution points should live in an explicit allowlist with an owner.
- Compare upload and download ratio per host role. A file server that suddenly sends more than it receives is worth a look regardless of absolute size.
Start from SigmaHQ and Elastic network rules for anomalous egress, MITRE CAR analytics on data transfer volume, and Zeek conn.log semantics (orig_bytes, local_orig). Baseline your own environment first — backup, sync and telemetry traffic is the dominant false-positive source.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts