Investigating Network traffic activity using Brim and Zeek
In the last article, I shared my favourite Brim ZQL queries to begin a threat hunting investigation in Zeek data. We covered pretty generic observables and events, so this time we’ll delve into how you can get better insights into network activity and actors.
TIP! You can find detailed installation instructions for Brim on Windows, Linux and macOS under https://github.com/brimsec/brim/wiki/Installation
Zeek produces a dedicated “conn.log” stream containing all of the relevant connection data, for example IP addresses, ports, or connection duration and throughput, which most of our analysis will lean on. This gives us a powerful and useful data source to analyze network activity without requiring too much data preparation.
TIP! We use the Mordor data sets for APT29 in this article. The Mordor Project provides pre recorded adversarial traffic. It’s a really useful repository of practise data for threat hunting, so if you haven’t checked it out yet, you can find it at https://mordordatasets.com/introduction.html
Which hosts are communicating on the network?
One of the first things we’re going to want to know is which unique assets we can actually identify communicating in the network data. The ZQL query below will show the unique IP address pairings in conn.log.
cut id.orig_h, id.resp_h | sort | uniq
Extract unique Source and Destination IP addresses
Which hosts communicate with each other the most frequently?
Now we know which hosts our data generally contains, it would be interesting to also understand how they are communicating with each other. Let’s take a look at the most common connection pairings to see which hosts communicate most frequently with one another
_path=conn | cut id.orig_h, id.resp_h | sort id.orig_h, id.resp_h | uniq -c | sort -r
Show the count of all unique connection pairings between hosts
While we can see that there is a lot going on, aside from the high count of connections between “10.0.1.6” and “192.168.0.4”, there’s nothing that sticks out as majorly suspicious. We’re going to have to add more context around these connections to identify any suspicious activity.
Which are the most active ports?
Now that we’ve identified the participants, we want to know what the hosts are doing in detail. For this we need an overview of which ports and services are visible in the network traffic — for example to identify remote management activity on non-standard ports.
_path=conn | cut id.orig_h, id.resp_h, id.resp_p, service | sort id.resp_p | uniq -c | sort -r
Show a count of all network connections including associated destination port and service protocol
We can now see that “10.0.1.6” and “10.0.0.4” have generated a large amount of activity. Due to Zeek’s Dynamic Protocol Detection, we also have reliable service detection that does not rely on simple port numbering. We can see what looks like a lot of SSL connections to a non-standard, unprivileged port (8443), as well as a variety of different protocols being used such as LDAP (Port 389), SMB over TCP/IP (445), and DCE/RPC activity (port 135).
Which hosts had the most inbound traffic?
Having seen the type and count of the different connections, it will also be interesting to see how much data is actually being transferred. This will allow us to pinpoint the outliers, for example any suspiciously large data transfers like downloading malware, or extracting data.
_path=conn | put total_bytes = orig_bytes + resp_bytes | sort -r total_bytes | head 10 | cut uid, id, orig_bytes, resp_bytes, total_bytes
Show the Top 10 connections between hosts, by data received
The large file transfer between 10.0.1.4 and 10.0.1.6 seems anomalously large. And we can see that it is one of several interactions between the two assets. Our next step will be to drill down deeper into the logs, now we have a better idea of where to look.
Pivoting and drilling down
Due to the awesome combination of Zeek and Brim, I can now double-click anywhere on the record and immediately obtain a detailed view of the suspiciously large transfer between 10.0.1.4 and 10.0.1.6.
Now we are presented with a clear summary of the connection outline, and we can see that “10.0.1.4” transferred a large file to “10.0.1.6”
TIP! Zeek assigns a unique identifier(UID) to every connection it processes, and then includes the UID in every related log, making it easy to correlate them. See https://docs.zeek.org/en/current/examples/logs/#using-uids for a detailed description
We can also pivot directly via the UID, either by right clicking on the UID and selecting “New Search with this value”, or by entering the UID directly into the search bar.
The first record shows “python.exe” being copied to a “temp” folder over the network, indicating that someone is doing something suspicious. Our next steps would be to see whether “10.0.1.6” does anything anomalous after this, as well as recovering the file to further analyze, for example by opening the original section of the pcap using Brim’s Wireshark integration.
Conclusion
Putting together the high level ZQL queries we demonstrated in our last article and the network-centric queries this week, you now have a solid set of standard queries to get a good overview of the lay of the land in any investigation using Brim. In most cases, this toolbox enables you to quickly pinpoint and isolate suspicious and anomalous events and activity, reducing the time-to-insight considerably.
Using the auxiliary capabilities such as the Log Detail View, the UID connection table and one-step pivot and drill down lets you contextualize and detail the data you are exploring, all in a streamlined workflow with minimal context changes.
In the next article, we’re going to apply what we’ve learned so far to a real-world example and investigate the Emotet Malware.