Jasper Alblas
Jasper Alblas
Welcome to this walkthrough of the Zeek Room on TryHackMe. In this room we get an introduction to Zeek, and how it is used for hands-on network monitoring and threat detection.
https://tryhackme.com/room/zeekbro
I am making these walkthroughs to keep myself motivated to learn cyber security, and ensure that I remember the knowledge gained by these challenges on HTB and THM. Join me on learning cyber security. I will try and explain concepts as I go, to differentiate myself from other walkthroughs.
Now, let’s move on!
Zeek (formerly Bro) is an open-source and commercial network monitoring tool used for security investigations, performance measurement, and troubleshooting. It passively analyzes network traffic and is widely used as a Network Security Monitor (NSM). The TryHackMe room provides an overview of network monitoring and hands-on experience with Zeek for traffic analysis. Basic Linux knowledge and network fundamentals (ports, protocols, and traffic data) are recommended prerequisites, with the “Network Fundamentals” path suggested before starting.
Answer: No answer needed
Zeek might sound similar to Snort? While both tools are categorized as network intrusion detection systems (NIDS), they serve different purposes. Zeek is better for detailed network analysis and forensic investigations, while Snort is more effective for real-time attack detection and prevention.
Event Engine: Processes network packets, extracting metadata like source/destination addresses, protocols, sessions, and files.
Policy Script Interpreter: Uses Zeek scripts for event correlation, allowing custom detection rules and security analysis.
Zeek has several frameworks to provide extended functionality in the scripting layer. These frameworks enhance Zeek‘s flexibility and compatibility with other network components. Each framework focuses on the specific use case and easily runs with Zeek installation. For instance, we will be using the “Logging Framework” for all cases. Having ide on each framework’s functionality can help users quickly identify an event of interest.
Logging | Notice | Input | Configuration | Intelligence |
Cluster | Broker Communication | Supervisor | GeoLocation | File Analysis |
Signature | Summary | NetControl | Packet Analysis |
Zeek can be used in two ways:
Live network monitoring is useful for continuous security monitoring and anomaly detection.
To run Zeek in real-time, use the ZeekControl module:
sudo zeekctl
Once inside the ZeekControl shell:
[ZeekControl] > start # Start Zeek service
[ZeekControl] > status # Check if Zeek is running
[ZeekControl] > stop # Stop Zeek service
Alternatively, use:
sudo zeekctl start sudo zeekctl status sudo zeekctl stop
To analyze captured network traffic from a pcap file, use:
zeek -C -r sample.pcap
This command processes the pcap file and generates log files in the current directory
Each log contains specific network event data, such as connections (conn.log), DNS queries (dns.log), and DHCP activity (dhcp.log).
Parameter | Description |
---|---|
-r | Reads and processes a pcap file |
-C | Ignores checksum errors |
-v | Displays Zeek version information |
zeekctl | Runs the ZeekControl module |
Answer: No answer needed
To see the Zeek instance version number, simply run:
zeek -v
Answer: 4.2.1
The ZeekControl module is used for real-time traffic monitoring. When we activate it, it prints the version number, so simply write:
sudo zeekctl
Hmm, but I got a “command not found” error. I solved it by changing to the root user: sudo su
. Afterwards simply run zeekctl
.
Answer: 2.4.0
First, make sure you are in the right folder: /home/ubuntu/Desktop/Exercise-Files/TASK-2.
In there, run zeek with the -r flag (and add -C to ignore checksum errors).
zeek -C -r sample.pcap
Wait, no output?
Well yes, but they got outputted into log files:
The total number of log file created is 8.
Answer: 8
As we just found out, Zeek creates a bunch of log files when reading a pcap file. Logs are categorized into seven main types, each serving a different purpose:
Some logs update daily (e.g., known hosts, services, certificates, and software), while others update per session (e.g., alerts, signature matches).
Each session has a unique identifier (UID) for correlation.
Since there are so many different log files, it is advisable to follow this general workflow when analyzing traffic:
Extracting key details from conn.log:
cat conn.log | zeek-cut uid proto id.orig_h id.orig_p id.resp_h id.resp_p
This filters only relevant columns, making analysis more efficient.
Answer: No answer needed
Make sure you change directory to the TASK-3 folder.
We should start by reading the sample.pcap file:
zeek -C -r sample.pcap
This should create all the different log files we saw earlier.
Time to read the dhcp.log file. If we use a regular cat command things get very messy!
We could probably find the answer (Microknoppix), but it it not very organized. Zeek-cut to the rescue!
cat dhcp.log | zeek-cut host_name
This simply filters the log on the specified column.
Answer: Microknoppix
This to read the dns.log file:
cat dns.log
Again, it is possible to find the right data (count the unique values of query), but alternatively we can run the following command using zeek-cut:
cat dns.log | zeek-cut query
The answer is 2.
Answer: 2
This time we should read the conn.log file:
cat conn.log
Taking a look, you should be able to see a called called duration. Time for zeek-cut again!
cat conn.log | zeek-cut duration
You can even add sort to the end to make it even easier..
cat conn.log | zeek-cut duration | sort -nr
There you have it.
Answer: 332.319364
This task basically covers a variety of command line commands and tricks to help make working with Zeek logs easier.
Here are the most important takeaways:
Command | Explanation |
---|---|
history | View command history. |
!10 | Execute the 10th command from history. |
!! | Execute the previous command. |
cat file.txt | Display the content of a file. |
head file.txt | Show the first 10 lines of a file. |
tail file.txt | Show the last 10 lines of a file. |
cat test.txt | cut -f 1 | Extract the first field (column) from tab-separated values. |
cat test.txt | cut -c1 | Extract the first character from each line. |
cat test.txt | grep ‘keywords’ | Search for lines containing a specific keyword. |
cat test.txt | sort | Sort lines alphabetically. |
cat test.txt | sort -n | Sort numbers in ascending order. |
cat test.txt | uniq | Remove duplicate lines (file must be sorted first). |
sort | uniq | Remove duplicate values. |
sort | uniq -c | Remove duplicates and count the number of occurrences for each value. |
sort -nr | Sort numbers in descending order. |
cat test.txt | wc -l | Count the number of lines in a file. |
cat test.txt | nl | Show line numbers for each line. |
cat test.txt | sed -n ’11p’ | Print line 11 of a file. |
cat test.txt | sed -n ‘10,15p’ | Print lines 10 to 15 of a file. |
cat test.txt | awk ‘NR < 11 {print $0}’ | Print all lines before line 11. |
cat test.txt | awk ‘NR == 11 {print $0}’ | Print only line 11. |
zeek-cut uid src_addr dst_addr file.log | Extract specific fields from Zeek logs. |
cat test.txt | rev | Reverse the characters in each line. |
cut -d ‘.’ -f 1-2 | Extract the first two fields from dot-separated values. |
grep -v ‘keyword’ file.txt | Display lines that do not contain the keyword. |
grep -v -e ‘test1’ -e ‘test2’ file.txt | Exclude lines containing either “test1” or “test2”. |
file file.txt | View file type and metadata. |
grep -rin ‘Testvalue1’ * | column -t | less -S | Searches for the string “Testvalue1” (case-insensitive) in all files (*), displays the results with aligned columns (column -t), and allows horizontal scrolling through the output (less -S). |
Answer: No answer needed.
Zeek (formerly Bro) signatures are rule-based patterns used to detect network anomalies, attacks, and specific traffic behaviors. Unlike Zeek scripts, which provide dynamic traffic analysis, signatures focus on pattern matching within network traffic.
Zeek signatures are typically stored in .sig files, such as:
/usr/local/zeek/share/zeek/site/mysignatures.sig
To load a signature file, use the -s flag when running Zeek:
zeek -C -r network_capture.pcap -s=sample.sig
A Zeek signature consists of:
Example Signature
signature suspicious_http_request {
ip-proto == TCP
dst-port == 80
http-request /password/
event "Suspicious HTTP Request Detected"
}
When a signature matches, Zeek can perform various actions.
Action | Description |
---|---|
event | Logs a message in signatures.log |
notice | Generates a Zeek notice |
alarm | Triggers an alarm (deprecated) |
Example: Generating a Notice
signature suspicious_ftp {
ip-proto == TCP
dst-port == 21
ftp /USER root/
notice
}
Triggers a Zeek Notice when USER root is detected in an FTP session.
Zeek supports standard comparison operators.
Operator | Meaning |
---|---|
== | Equals |
!= | Not equal |
< | Less than |
<= | Less than or equal to |
> | Greater than |
>= | Greater than or equal to |
Example: Match Traffic Below a Certain Port
dst-port < 1024
Triggers only for ports below 1024.
Filters define which network traffic the signature applies to.
Filter | Description |
---|---|
src-ip | Source IP (e.g., src-ip == 192.168.1.1) |
dst-ip | Destination IP (e.g., dst-ip == 10.0.0.5) |
src-port | Source port (e.g., src-port == 443) |
dst-port | Destination port (e.g., dst-port == 21) |
ip-proto | IP Protocol (TCP, UDP, ICMP, ICMP6) |
Example: Detecting FTP Traffic
signature ftp_traffic {
ip-proto == TCP
dst-port == 21
event "FTP Traffic Detected"
}
Triggers an event when TCP traffic is detected on port 21.
Filter | Description |
---|---|
payload | Matches raw packet payload (e.g., payload /password/) |
http-request | Matches HTTP requests (http-request /login/) |
http-request-header | Matches HTTP headers (http-request-header /User-Agent: curl/) |
http-reply-header | Matches HTTP response headers (http-reply-header /200 OK/) |
ftp | Matches FTP commands (ftp /USER admin/) |
Example: Detecting a Login Attempt in HTTP Traffic
signature http_login {
ip-proto == TCP
dst-port == 80
http-request-body /username=admin&password=/
event "Possible Login Attempt"
}
Triggers if a request body contains “username=admin&password=”.
Filter | Description |
---|---|
same-ip | Matches if the source and destination IP are the same |
Example: Detecting Internal Traffic
signature internal_traffic {
same-ip == true
event "Internal Traffic Detected"
}
Triggers when a packet’s source and destination IP are identical.
Scenario: Detect HTTP requests where the User-Agent matches malicious-bot.
signature malicious_user_agent {
ip-proto == TCP
dst-port == 80
http-request-header /User-Agent: malicious-bot/
event "Possible Malicious Bot Detected"
}
If a request contains User-Agent: malicious-bot, Zeek logs an alert.
Simply change the directory to Desktop/Exercise-Files/TASK-5.
Answer: No answer needed
Ok! Ready to create some signatures?
Go into the http folder found inside of the TASK-5 folder you should be in. In it you should find a http.pcap file with traffic data, and the signature file we should be editing. There is also a clear-logs shell script used to automatically remove log files.
Let’s open the http-password.sig signature file so we can edit it.
The HTTP signature shown in the task is as follows:
signature http-password { ip-proto == tcp dst-port == 80 payload /.*password.*/ event "Cleartext Password Found!" }
Input this into the file and save.
Now let’s run Zeek with the following command:
zeek -C -r http.pcap -s http-password.sig
It will run for a few seconds, and then you should see a bunch of freshly created log files in the directory.
Now we have to find the source IP of the first event. We can find this info in the signatures.log file.
The info we need is in the src_addr column so we can quickly get the relevant info by using zeek-cut again!
Run the following command:
cat signatures.log | zeek-cut src_addr
Thus, the answer is 10.10.57.178.
Answer:10.10.57.178
The answer is found in the same file. We can add the required info by adding the new column to the previous command:
cat signatures.log | zeek-cut src_addr src_port
You will see that the answer is 38712.
Answer: 38712
This time we should look at the conn.log log.
You could simply read the conn.log file and count manually, since it is very short. But in a more realistic scenario I would recommend to use the following the command.
cat conn.log | zeek-cut id.orig_p orig_pkts resp_pkts | grep '38706'
This selects the id.orig_p (origin port), orig_pkts (sent packets) and resp_pkts (received packets) columns, and searches for the lines that include the source port 38706.
This returns 1 line, and adding the two packet columns together gives us 20 (11+9).
Answer: 20
The global rule shown in the task is as follows.
signature ftp-username { ip-proto == tcp ftp /.*USER.*/ event "FTP Username Input Found!" } signature ftp-brute { ip-proto == tcp payload /.*530.*Login.*incorrect.*/ event "FTP Brute-force Attempt!" }
Add this rule to the ftp-bruteforce.sig file. It should look like this:
Now run Zeek:
zeek -C -r ftp.pcap -s ftp-bruteforce.sig
Once more, log files are created.
Now we should read the notice.log file to count the number of unique events:
cat notice.log | zeek-cut uid | sort | uniq -c | wc -l
That was a mouthful with all those pipes! First we read the log file, then we select only the uid values. Then we sort those, so that we can remove duplicates. Finally we count the number of lines.
Answer: 1413
Time for more CLI ninja skills!
This one is more easy though. Simply read the notice.log file and grep for the signature event name. Then simply count the number of lines:
cat notice.log | grep "FTP Brute-force Attempt" | wc -l
The answer is 1410.
Answer: 1410
Zeek has a powerful event-driven scripting language for investigating and correlating network events.
event dhcp_message(c: connection, msg: dhcp_msg)
{
print msg$hostname;
}
zeek -C -r smallFlows.pcap dhcp-hostname.zeek
Just ensure you are in the TASK-6 folder 🙂
Answer: No answer needed
Go into the smallflow folder. Here you can find a script file (dhcp-hostname.zeek) and a pcap file. We now have to run the following command to read the pcap file with the script file active:
zeek -C -r smallFlows.pcap dhcp-hostname.zeek
This will create all of the log files once more.
Now read the dhcp.log file using zeek-cut:
cat dhcp.log | zeek-cut host_name domain
Answer: astaro_vineyard
Go into the bigflow folder and run the following command:
zeek -C -r bigFlows.pcap dhcp-hostname.zeek
This will take a bit longer to run. After a minute or so it should be done.
Let’s look at the dhcp.log file again, now zeek-cutting on hostname, sorting, and selecting all unique values and counting the lines.
cat dhcp.log | zeek-cut host_name | sort | uniq | wc -l
Note that one of the values is empty (-), hence the answer is 17.
Answer: 17
Simply read the dhcp log file and use zeek-cut on the domain:
cat dhcp.log | zeek-cut domain
There is only one unique domain in the file.
Answer: jaalam.net
Events: zeek_init (start) and zeek_done (stop).
event zeek_init() { print ("Started Zeek!"); } event zeek_done() { print ("Stopped Zeek!"); }
Scripts process network traffic and generate logs.
Running a Script
zeek -C -r sample.pcap 101.zeek
(Runs script on a PCAP file).Extracting Network Data
Filtering & Optimizing Output
Event Correlation with Signatures
ftp-admin.sig
.signature_match
event to trigger alerts.Running Scripts with Signatures
zeek -C -r ftp.pcap -s ftp-admin.sig 201.zeek
Load All Local Scripts
zeek -C -r ftp.pcap local
loads all scripts in local.zeek.Load a Specific Script
zeek -C -r ftp.pcap /opt/zeek/share/zeek/policy/protocols/ftp/detect-bruteforcing.zeek
Simply move to the task 7 directory.
Answer: No answer needed
This is the same command as we used in the previous task:
zeek -C -r sample.pcap 103.zeek
There are a lot of new connections, to much to easily found!
So I used the following command to automatically count the number of times “New Connection Found!” was printed:
zeek -C -r sample.pcap 103.zeek | grep "New Connection Found!" | wc -l
The returned number is 87.
Answer: 87
This time we should run Zeek with both a script and signature this time. This requires the following command:
zeek -C -r ftp.pcap -s ftp-admin.sig 201.zeek | wc -l
Note, I added the wc -l
command straight away, as each hit signature entry only outputs one line.
Answer: 1401
Read the signatures.log file and grep on “USER administrator”:
cat signatures.log | grep "USER administrator" | wc -l
The total number is 731.
Answer: 731
To run all local scripts we need to add local after our usual Zeek command.
zeek -C -r ftp.pcap local | wc -l
This results in 507 entries, but at a closer look there are a bunch of comments lines in the loaded_scripts.log file. Therefore I used this command instead, counting all lines that included a string path (all scripts are nested in the /opt/ main directory:
zeek -C -r ftp.pcap local | grep "/opt/| wc -l
Answer: 498
We use a example similar to the one mentioned in the discussed theory:
zeek -C -r ftp-brute.pcap /opt/zeek/share/zeek/policy/protocols/ftp/detect-bruteforcing.zeek
Now simply read the notice.log file:
cat notice.log
There are only 2 entries in the log, so a manual check suffices here.
Answer: 2
This section covers Zeek’s frameworks, focusing on file analysis and intelligence capabilities.
Here are examples of two scripts in the framework:
The Intelligence framework processes data feeds and correlates events to detect anomalies.
It requires an external intelligence source (e.g., /opt/zeek/intel/zeek_intel.txt) to generate alerts based on traffic analysis.
An example is the following:
zeek -C -r case1.pcap intelligence-demo.zeek
Simply move to the TASK-8 folder.
Answer: No answer needed
This example comes straight out of the described theory:
zeek -C -r case1.pcap intelligence-demo.zeek
Now read the intel.log file, using zeek-cut to more easily find the answer:
cat intel.log | zeek-cut seen.where
The second row gives the answer.
Answer: IN_HOST_HEADER
Easy one. Just read the http.log file and grep on “.exe”:
cat http.log | grep "exe"
The answer is knr.exe.
Answer: knr.exe
Once more, the command to run is covered in the theory:
zeek -C -r case1.pcap hash-demo.zeek
Now read the files.log file. To make it easier to find the right md5 hash I ran the following command:
cat files.log | zeek-cut mime_type md5
The answer is the hash of the file with the mime type of x-dosexec. We could also have looked for the fuid of FOghls3WpIjKpvXaEl, which we found in the previous question.
Answer:cc28e40b46237ab6d5282199ef78c464
Once more:
zeek -C -r case1.pcap file-extract-demo.zeek
Then cd
into the extract_files folder:
cd extract_files
Now we we have to find out which file is the text file:
file *| nl
It is the first one. Read it:
cat extract-1561667874.743959-HTTP-Fpgan59p6uvNzLFja
Answer: Microsoft NCSI
It is also possible to install third-party scripts and plugins to extend Zeek functionalies.
The Zeek Package Manager (zkg) simplifies installing and managing third-party scripts and plugins for Zeek. It is included with Zeek and requires root privileges. Key commands include:
Packages can be used in three ways:
Simply change directory to TASK-9.
Answer: No answer needed
Make sure to move into the cleartext-pass directory to find the http.pcap file.
Run the following command to read the http-pcap file with the zeek-sniffpass module:
zeek -Cr http.pcap zeek-sniffpass
Now read the http.log file:
cat http.log | zeek-cut post_username
BroZeek has 3 entries.
Answer: BroZeek
Time to move into the /home/ubuntu/Desktop/Exercise-Files/TASK-9/geoip-conn directory.
Run the following command to use the geoip-conn module:
zeek -Cr case2.pcap geoip-conn
Now read the conn.log file with a simple cat command:
cat conn.log
You can find the answer (Chicago) without fancy piping 🙂
Answer: Chicago
Nice, an easy question!
The answer is on the same row/column as before: 23.77.86.54.
Answer: 23.77.86.54
As before, read the case2.pcap with the help of the sumstats-counttable.zeek script.
zeek -Cr case2.pcap sumstats-counttable.zeek
We see the following results:
There are 4 different status codes.
Answer: 4
Congratulations! You just finished the Zeek room. In this room, we covered Zeek, what it is, how it operates, and how to use it to investigate threats.
Now, we invite you to complete the Zeek Exercise room: ZeekExercises
Answer: No answer needed.
Congratulations on finishing this walkthrough of the TryHackMe Zeek room. This was a long one! Now we have another great tool that we can employ in future SOC roles. I hope you can see that Zeek is great for detailed network analysis and forensic investigation
Come back soon for more walkthroughs of rooms on TryHackMe and HackTheBox, and other Cybersecurity discussions.
You are welcome to comment on this post, or share my post with friends.
I would be even more grateful if you support me by buying me a cup of coffee:
I learned a lot through HackTheBox’s Academy. If you want to sign up, you can get extra cubes, and support me in the process, if you use the following link: