This query looks at CoreDNS log data to identify beaconing, where a system periodically reaches out to an Internet host to check in. It can be a useful way to identify malware... or a Photoshop installation. We detect beaconing by using mean & standard deviation to identify hostnames which are queried at very regular intervals.

This query is a doozy, so let's break down the workflow. After extracting the DNS hostname and timestamp, we calculate the standard deviation and mean for each hostname (the "by Name" part of the "stats" module does this). From there, we filter out one-offs and entries that don't have enough datapoint to be meaningful and then calculate a fields "r" as the standard deviation divided by the mean for each hostname. This is the coefficient of variation -- a simple measure of how tight the beaconing period is. "Duration" is just a pretty printed time value of mean (5m10s as opposed to 310). We sort by "r" to give us the most consistently beaconing results first, and throw everything onto a table.


tag=dns sort by time asc
| json Question.Hdr.Name
| diff TIMESTAMP by Name
| require -s diff
| stats mean(diff) stddev(diff) count by Name
| eval (stddev < mean && count > 2)
| eval setEnum("r", stddev/mean)
| eval setEnum("Duration", toDuration(mean))
| sort by r asc
| table Name Duration count


QOTW_Detect DNS Beaconing Results


Check out our CoreDNS plugin to get CoreDNS into Gravwell.