Zeek Correlations: Outbound Connections
By David Hoelzer on 2019-09-19 09:32:01

I said that many people are using Zeek wrongly, at least in my opinion. Since that's the case, it's only right that I provide examples of what I think the "right" way to use Zeek is!

Let's start by thinking about how systems typically behave on networks. Systems within our networks, when they want to speak to external systems, should begin by performing a DNS address resolution. As I'm certain that you are aware, this is how we translate names like www.google.com to an IP address like 216.58.193.164.

Think about why a host would connect directly to an external system without performing a lookup first. A quick think for me results in this list:

  • A hard-coded IP address in a config file or application
  • The DNS resolution went over a different path (most likely in an effort to avoid DNS filtering)
  • Something "Phoning Home"
  • A compromised system that already knows where it's C2 server is
  • A worm infected system looking to make new "Friends"
  • An internal user or compromised system running outbound scans
  • My own internal DNS server performing outbound lookups to an upstream DNS server or the root servers

Looking at this list, there is really only one example that is ok, and that is your outbound DNS queries from your DNS server. "What about hard coded configurations?," you ask? Those are not ok! Those represent a "fragile" configuration. What this means is that by hardcoding an address, you are setting yourself (or your organization) up for a future support problem, trying to figure out why a service that has worked for years has suddenly broken. It is very strongly recommended that we always use named hosts rather than static addresses.

It's time for Zeek to come into the picture. What we need to do is to keep track of every address that was found in a DNS lookup and then look for any outbound connections whose responding IP address was not in a lookup. Here's a simple example of this:

# Create a whitelist of static addresses where lookups aren't required.
# Typically, this would be the list of upstream DNS servers or the root
# servers from your root.hints on your internal name server.
global whitelist: set[addr] = {
  8.8.8.8
};

# Define the list of internal subnets that we are monitoring
global  internalNets: set[subnet] = { 192.168.0.0/16 };

# Create a set to track resolved addresses.
global resolvedAddresses:set[addr];

# Track both IPv6 resolutions...
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr)
  {
    add resolvedAddresses[a];
  }

# and IPv4 resolutions...
event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr)
  {
    add resolvedAddresses[a];
  }

event new_connection(c: connection)
  {
    if(c$id$orig_h ! in internalNets || c$id$resp_h in internalNets)
      {
        return;
      }
    if(c$id$resp_h in resolvedAddresses || c$id$resp_h in whitelist)
      {
        return;
      }
    print fmt("%s:%s -> %s:%s - No DNS lookup", c$id$orig_h, c$id$orig_p, c$id$resp_h, c$id$resp_p);
}

This script is currently written in such a way that it never decays data out of the set and so that it simply outputs to the screen (run interactively). For long term use, this should be adjusted to send output to either a log that you create or a log of your choice (perhaps Weird?). I've chosen not to address the length of time that the data is held using an attribute on the variable simply because Zeek is currently in transition. The &persistent attribute was recently (and in my opinion, unwisely) deprecated, and I expect more changes to happen with attributes in the coming months.

David Hoelzer is the author and maintainer of theĀ SANS SEC503 Advanced Intrusion Detection course, the leading class for advanced network analysis in the industry. With more than 30 years of experience in information technology and security, he is the author of and a contributor to a number of open source defensive tools. In addition to acting as the Chief of Operations for Enclave Forensics, Inc., an incident response, secure coding, and managed services corporation, David is also the Dean of Faculty for the SANS Technology Institute (STI).