As I stated earlier,
Zeek uses its scripting to define and analyze policies based
on events that it's seen in the network.
This isn't the only way that it can detect
abnormalities or threats in the network though.
Similar to other intrusion detection system type tools,
it can use signatures to detect threats based on the predefined signatures.
Let's talk about this for a little while.
The signature framework adds to Zeek's capabilities by giving us a
more traditional signature analysis capability.
It's by far not the most desired way to utilize Zeek, but it can be beneficial.
It's still a part of the overall Zeek language and
plays a part in its functionality, so that's why we're covering it here.
Using the signature framework,
we're able to write specific criteria for the events to
match on and send messages as a result.
From a security perspective, this is great.
We can use this portion of Zeek more like a normal IDS and have Zeek raise an
event whenever that signature that we build is matched.
The nice thing about this is that we can make these signatures
as simple or as complicated as we'd like.
So let's take a look at this example signature that I made really quick.
What it's looking for is our device is reaching out on port
53 to our DMZ server handling DNS queries.
I don't know why, but I love using DNS as an example for many things.
It's because it's very easy to misconfigure devices or forget
to program the DNS servers for some devices,
so we always see activity like this.
You can also write a rule to look for matches that reach out to DNS servers
that aren't yours to detect this type of misconfiguration.
So anyway, here I'm looking for this particular activity to match.
If all of this criteria is matched, an event will be raised.
If not all of them are matched, then nothing happens.
Remember,
these signatures are completely separate from the rest
of the Zeek scripts and analysis.
The signature framework uses conditions to match values,
like I showed you with my example just now.
There are a few different types of conditions that we can
match on with a signature framework, one of which is the header condition.
If you think about how a datagram is structured,
at layer 3 we have our packet headers.
These give us the information such as source and destination
IP and the protocols that are being used.
We also have the content conditions that we can tag in the
signature rule that we build to give us some flexibility
with what we're learning on.
The content conditions use regex to match the content that
we want an event to be generated with.
We can match strings either in the raw payload data that we see in a packet or
in an analyzer-specific content such as protocol analyzers.
Using something like this,
we can match against the criteria in something like HTTP request,
as an example.
Something cool about the signature framework is that it also allows
us to define conditions matching other signatures and to flag only
if it matches that other signature,
these are called dependency conditions and require a
signature ID to match this signature to.
We can also match context conditions that use other portions of Zeek
to help us compare the signature to other things.
This really adds to the flexibility of not only Zeek itself,
but the usefulness of the signature framework.
Really quick,
before we move on into the scripting that Zeek uses and dig into that language,
there are two actions that are available for us to use
with the Zeek signature framework.
One is the event action, and the other is the enable action.
The event action raises an event and takes some sort of
predefined action based on that event,
whether it generates a log message or does something more
advanced like send an email alert via a plugin.
The other action is the enable action.
This gives Zeek the capability to activate a specific analyzer
dynamically and as needed based upon an event.
There's a lot of integration that can be done here.
We're about to hop in the lab really quick to demonstrate my
example of a signature rule that can be created.
We're going to jump into the signature framework and show a
signature I created about looking at traffic going out from our
internal DNS server to our DMZ DNS server.
This isn't a security risk,
but it's going to help me identify how often my internal
DNS needs to perform its own lookups.
We'll check out the contents of the script,
talk about how it works, and how to use it.
Then,
we'll see if we can test it out and get a message generated by my
internal DNS server reaching out to that DMZ one.
Let's hop in there.
So now that we're in the lab,
I'm going to show you the signature that I created really quick.
It's super simple and you can play around with this in your lab
instance and tweak the fields as you like.
I have everything set up in the temp folder just for ease.
As you can see, we have the DNS.sig file,
which is where our signature is,
and the test.pcap file that I'm going to be using to run
through the signature to detect information.
You can take a pcap of your own network if you want and upload it
to your Zeek virtual machine on your own so you can see the
signature interact with your own environment.
Pulling up the signature, I have the name of it,
which is also the signature ID here.
I have it looking for the header field of the destination IP,
and I want it to be the 10.75 address.
You'll have to change this information depending on
your environment setup though.
Here, I have it generating an event of WrongDNS server,
but we're going to change this a little bit.
Using VI,
I'm going to hop in and edit this signature to change the
ID and event that it corresponds to.
Remember,
you can have multiple fields tagged here from the other header
fields to regex statements looking in the payloads.
I only have one header field here for simplicity.
Now I'm going to save it so we can run it through the Zeek signature.
I'm only invoking an instance of Zeek to run this particular
pcap through the Zeek signature that I created.
I'm not sticking it in the necessary folders to have it
automagically alert based on the traffic seen.
To be able to do this, I'm going to use the command zeek -r test.pcap -s DNS.sig,
and that will ensure that we're running it through that signature rule.
After that's done, we can see that we have a lot of log files here.
This is because we invoked a Zeek instance from within this particular folder.
When looking for signatures, by default,
Zeek adds any matches to this signature.log file.
It doesn't use any signatures by default with the exception of
some that are built into the default scripts,
so this is a customization that you'll have to do if you want this capability.
This log file will be with all of the other ones in the
Zeek log folder that we saw previously.
So here, I'm going to pull it up, and look at that,
I have four matches from the pcap.
My 30.11 machine was reaching out to the 10.75 server over port 53,
which is the standard DNS port.
We also have the DNS server event that we had in the signature file,
as well as the signature ID here.
This is pretty cool.
You can play around with more complex rules,
inspecting payloads as well, so this is fairly robust.
One thing to note though is that Zeek currently is first match
wins for the header fields within the signature,
so if you're looking at multiple types of header fields,
let's say port number and IP, whichever one gets the first match wins.
Let's move into the next clip and learn more about scripts.