We're going to start by first exploring how to add custom rules.
There are two primary ways to add custom rural locations to Suricata.
First, by modifying the YAML, or second,
by adding a command line argument to Suricata.
For training, we'll go with the second option.
As you'll see,
this makes for an easier way to test rules as you are creating them.
The first option works better when you have rules ready to go
and want to deploy them into production.
Let's open up the suri‑ingest‑pcap script to make a slight modification.
Where we tell Suricata to process a pcap,
we're going to add the ‑s argument with the path to the custom rule file.
For the training VM, we've included custom.rules in the user's home directory.
Had that not already been there, you would need to create the file.
We can now save and exit out of our editor.
As a quick side note,
the ‑s argument also tells Suricata to use any existing rules,
plus the custom rule file you just defined.
If you use a ‑S,
it will only use the rule file you defined as a command line
argument and ignore those from the YAML.
Now,
open custom.rules in a text editor and add the rule we discussed
in the previous video to detect ICMP packets.
In this file,
lines that start with a hashtag are considered comments and ignored by Suricata.
This rule is very basic.
We tell Suricata to alert on the ICMP protocol when ICMP packets
are found going any direction on any port.
For the message, I like to ensure that it's clear I'm in a testing phase.
That way, if anything slips into production,
it's hopefully obvious that it shouldn't be there.
We can define a sid of 1 and a rev of 1 and save the file.
Now we can run our updated pcap ingest script against the
pcap/demo‑s03‑01‑icmp and wait for the results.
Keep in mind that we told Suricata to place logs at /tmp/suricata and
defined that in the same script that we just edited.
Perfect, there is our ICMP alert.
We can now use jq to query the eve.json file directly
to see more details about the alert.
We'll use jq and a select statement in order to get only
the event types that equal to alert.
The last argument is a path to the JSON file that we want to query.
Executing our command will give us all of the data
that Suricata logged with that event.
You can now also note the flow_id,
and we can use that to expand our search to look at
events associated with this alert.
By replacing event_type = alert with flow_id and the
flow_id that we want to search on, this now changes the results.
While that output will scroll by quickly, we now have two events.
You can see right now we have event_type of flow,
which is in addition to the alert event that we saw earlier.
We connected the dots using the flow_id.
If we scroll backwards a little bit further,
we'll see our original event type, which was our alert.
Let's now take a look at another example but this time with some real malware.
We're not really worried about custom rules at this point,
so the ‑s will load other rule files defined in the YAML.
Let's run our next pcap with the ingest script and see what happens.
Okay, so that's a lot more alerts that were generated.
Let's narrow down our data and focus on the alert for ET
MALWARE Trickbot Checkin Response.
I chose this because oftentimes when malware checks
into a command and control server,
there can be some interesting results that are returned,
such as additional payloads.
So again, we'll turn to jq and select only the event types by alert.
Since the alert that we're interested in happens to be the last alert generated,
it will be the last item displayed in our terminal.
So we can scroll up a bit to confirm the signature
and now also to get the flow_id.
We'll modify our jq command to filter on records that match the flow
id. We'll also tell jq to only print the event type values by further
refining our command. And we can see that on this flow there were
actually two alerts, an http event and a fileinfo event. With the flow
id, we've been able to take a step back from the alert and gather more
context.
What if we now want to investigate a different event? For example,
fileinfo could mean that malware was downloaded.
Let's investigate that data.
We can change our jq command to filter on both the flow id and the event
type by adding a logical end to our select command.
We can also get rid of the .event type, which will then display all of the data
that matches our filter. And now we can see all of the data that was recorded
for the fileinfo event associated with our flow.
In this case, it was determined to be ASCII text, as you
can see in the magic field. But we also get file hashes,
MD5, SHA‑1 and 2, by default.
This could become important information that you can utilize to quickly
pivot and search online sandboxes or places like abuse.ch to see if you're
dealing with a malicious file. Suricata can also do file extraction, but
we'll get to that a little bit later.
This is just a brief example. There's a lot more
Suricata can do, so let's keep going.