How to spot malware beaconing in a connection log
Looking for a fixed interval finds nothing, because every implant since about 2013 adds jitter for exactly that reason. Three measurements survive it, and they give the configured sleep back.
Beaconing is a heartbeat. Something on the network reaches out to the same place every so often and asks whether there is work; the answer is usually no, so the conversation is short and the next one comes a fixed interval later. The regularity is the signal, and the obvious test for it — look for identical intervals — finds nothing, because every implant written since about 2013 adds jitter for exactly that reason. Three measurements survive jitter: how tight the intervals are relative to their own size, how few distinct intervals there are, and how uniform the conversation sizes are. BEACON takes them on a connection log in your browser and gives back the sleep and the jitter the implant was configured with. What it will not do is tell you which beacon is malicious, and neither will anything else.
Why looking for a fixed interval finds nothing
An implant configured to sleep sixty seconds with twenty per cent jitter produces intervals spread evenly across forty-eight to seventy-two seconds. No two are the same. A filter for "the same interval twice" returns an empty set on a device that is calling home every minute of the day.
So you need "similar", which needs a threshold, and the threshold is where this usually falls apart. Five seconds of slop is enormous at a sixty-second period and invisible at an hour. A rule tuned to catch the first misses the second entirely, and the beacons that survive in well-watched networks are the slow ones.
The way out is to stop measuring in seconds. Divide the spread of the intervals by their own middle and the number that comes out is scale-free: a beacon at sixty seconds with twenty per cent jitter and a beacon at an hour with twenty per cent jitter score identically, which is the correct answer, because they are the same thing.
The three measurements
| What is measured | Why jitter cannot hide it | What does defeat it |
|---|---|---|
| Interval tightness. The median absolute deviation of the intervals over their median. | Jitter widens the spread by a fixed percentage, and dividing by the median cancels the scale out. The number is the jitter. | Jitter near 100%, which is an implant that has given up on being regular and paid for it in responsiveness. |
| How few intervals there are. The share of gaps falling in a narrow band around the median. | Real traffic to one host spans orders of magnitude — milliseconds inside a page load, minutes between pages, hours overnight. A beacon has one interval, blurred. | A beacon that also carries real traffic, so the two distributions are mixed. |
| Size uniformity. The coefficient of variation of the bytes per connection. | A check-in with nothing to say is the same size every time, give or take a header. A browser never is. | A log with no byte counts, and an implant padding its check-ins to random lengths. |
What it looks like on a log
Here is a log built to test the tool rather than taken from an intrusion — two hundred and twenty connections from one host to a beacon configured at sixty seconds with twenty per cent jitter, and two hundred and twenty from the same host to an ordinary web destination, interleaved:
| Pair | Period | Jitter | In band | Size CV | Score |
|---|---|---|---|---|---|
| The beacon | 60 s | 20% | 73% | 0.01 | 0.801 |
| The browsing | 13 s | 100% | 4% | 0.58 | 0.013 |
The period and the jitter came back as the numbers that went in: sixty seconds, twenty per cent. That is not a coincidence and it is the second reason to do this properly — the spread of the observed intervals is the configured jitter, so you recover the configuration rather than just flagging the pair. Those two numbers are what goes in the report and what gets matched against other incidents. "Something odd talking to that address" matches nothing.
The part that cannot be automated, and should not be
A backup agent is a beacon. So is a monitoring check, a software updater, a certificate refresh, an NTP client and most telemetry. All of them score highly on every measurement above, and on a real network most of what comes out at the top will be one of them. That is not a flaw in the method; it is what the method measures.
Any tool that claims to tell you which beacon is malicious is selling you the one judgement it cannot make. What a ranking is for is putting the handful worth opening at the top of a list of thousands. After that it is yours, and these are the questions that resolve it:
- Is the destination something you can name? A vendor's update service resolves to something recognisable. An address you have to look up is not proof of anything and is the right place to start.
- Does the process on the host make sense? A backup agent beaconing is expected. The same beacon coming from a browser child process is not.
- Was it there last month? A beacon that starts on a date is a beacon with a cause. One that has run for two years is infrastructure somebody forgot to document.
- Does one host do it, or four hundred? Enterprise software beacons from everything. An implant usually does not, at first.
- What happens at three in the morning, and at the weekend? Legitimate software does not care. Some implants only run while somebody is logged in, which is itself a tell.
What the log has to contain
One row per connection with a time, a source and a destination. A byte count makes the third measurement possible and is worth having. A Zeek conn.log, a firewall export, a proxy log or a NetFlow dump will all do, and the column names are yours to map.
Twelve connections per pair is the default floor, which is the honest limit on slow beacons: something that calls home once a day needs nearly a fortnight of log before there is anything to measure. A capture of an afternoon will find a sixty-second beacon and will not find a daily one, and no amount of arithmetic fixes that.
Two other things it will not find. A beacon through a large CDN shares its destination address with everything else using that CDN, so the pairing that makes this work is gone. And an implant that only moves data when a person is at the keyboard is not beaconing at all — it is hiding inside the traffic the person generates, which is a different problem needing a different look.
Why it runs in the browser
A connection log is a map of an entire organisation: every host, every destination, and the shape of what each of them does. It is not a file to paste into somebody else's website while investigating a possible intrusion, and the usual answer — upload it to an analysis service — is worse than useless when the question is whether an attacker is already reading your traffic. BEACON parses and measures it in the tab, and nothing leaves the device.
Alongside: WIRE reads a packet capture the same way, DGA finds generated domain names in a DNS log, and LOGON finds an account touching hosts it has never touched before.
Questions people ask about spotting malware beaconing in a connection log