Snort nids, how and where to use it

Written by  on April 23, 2018 

These days I’ve been doing a lot of “blue team” stuff and one of my best allies ha been snort. Snort is basically a free and open source network intrusion detection system, very light weight and easy to use, though a little bit slow and non-efficient when it is used in a high throughput environments. Snort can be used not only for detection intrusions and for blocking them, as a firewall/alarm but it can be used as a complementary subsystem inside more advanced solutions (ex: kaspersky kata or ccn-cert SAT), using it as a sensor makes a lot of sense but it can also be used as a “pcap” signature based antivirus. Maybe that sounds a little bit confusing? Let’s look inside how Snort works and play a little bit with it and we’ll see.

First of all you can get snort in a standard linux distro by:

apt-get install snort

You’ll probably work with snort 2.x although snort 3 is about to be released and a couple of things may change, but the idea is basically the same.

Once we get snort we can start it easily with

snort -v -i eth0

This will start snort in verbose mode on interface eth0. We should see something like that:

As you can see it works like a simple sniffer, like tcpdump for example. We can stop the session by pressing ctrl+c and then the program will show some sort of summary to us, like this one:

Snort can not only capture or display packets, it’s main feature is it’s capacity to analyze packets in real time and perform certain actions such as alert, log and block based on it’s content. We’ll see how it goes later in this post.

Snort can inspect packets in different layers. For example we can inspect the application layer by using:

snort -d -v -i eth0

We can test this filter by connecting to a web application while snort is listening on background. It will prompt something like that:

Snort is pretty versatile and works on many levels. We can use it to analyze packets at ethernet level by:

snort -d -v -e -i eth0

And we’ll see something like:

But of course what we’ve seen till now it’s pretty simple and even useless as we can do the same with tcpdump or other kinds of software. Snort is also useful for capturing packets for later analysis.

We can do that using:

snort -dev -i eth0 -l logfolder/

This will store a session log of the capture into the “logfolder” folder. We can then open that capture file (pcap format) with wireshark for further analysis. For example here we have captured a ping between two boxes on the same network:

But still, till now, everything we’ve done we could done it with a regular packet capturer. Now we are getting to the point. The main functionality of snort is it’s packet inspection mode and it’s filter system for alerts and blocks, acting not as firewall but as a network intrusion detection system. Before getting further into that explanation we’ll see how snort filters also called snort RULES work.

Let’s supose that we want to detect pings done to our box. First of all we run snort as a packet capturer and we capture a ping session. Then we open that in wireshark and we study the packets. After doing that we can build a filter like the following:

alert icmp any any -> any any (msg: “ICMP Packet found”; sid:100003;)

Let’s take a look on that rule works.

The first word “alert” identifies the rule as an alert, so, it will not block the packet but it will store a log entry at /var/log/snort/alerts every time the condition we specify is encountered in a packet. The next words ICMP ANY ANY basically say that we are locking for ICMP packets from any port and any network. The arrow -> is saying that we looking for packets from outside of our box coming in and the next two any’s stay for packets coming to any interface and any port. The most interesting part comes after that, between ()’s. In our case we specify that once we match the packet we want a message “ICMP Packet found” to be prompted on the log entry, the other parameter, “sid” is just an identifier number so we can identify rules if we have a lot of them.

We can run snort using rules with:

snort -dev -i eth0 -l log/ -c ping.rule

This will start listening on eth0 with our custom rule file. We can also use rules to work on stored pcap sessions with:

snort -d -h -c ping.rule -r  session.pcap

Running that with our ping session should prompt something like:

And if we look at our log file /var/log/snort/alert we see

Looking for content inside packets

But what we’ve done now it is also simple. Let’s think about something more real. We may have a custom web app located in a non production environment and we may want to monitor it to see if some potential bots or attackers are trying to access it. We can use the “content” parameter in a rule file to detect that someone is accessing a custom url on our server. We’ll do it using a rule like the following:

alert tcp any any -> any 80 (msg:”WEB GET”; content:”/app.php?id=”; rev:1;)

As we see, here we look for tcp packets coming to port 80 containing “/app.php?id=” which is our sensible url.

Using regular expressions (PCRE)

But let’s think about it, maybe we want to look for potential attacks to our web applications. If we have a web app that works as the public interface of an API system and receives some get parameter in the “id” field such as 1, 2..a,b.. making a legit request look like:

/app.php?id=1 or /app.php?id=a2

An unusual and potentially dangerous request may look like:

/app.php?id=aaaaaaaaaaaaaaaaa or /app.php?id=aaaabbbbbccccdddddshell.php or /app.php?id=1′ or /app.php?id=../../../../etc/passwd%00

Or something like that.

But how can detect that using the content option? It may be pretty hard because an attacker launching an attack such as ?id=aaaaaaashell.php may switch to ?id=aaabbbbscode.php making the attack look different but doing exactly the same also he can use some kind of url encoding to mess up the thing even more.

Snort has an option called PCRE which is basically the usage of regular expressions to look for certain content inside snort. If you know about regular expressions then you should be ready to go. You can also google for different kind of automatic regex generators for making it more easy.

A pcre for detecting one of the previously mentioned attacks may look like:

alert tcp any any -> any 80 (msg:”WEB ATTACK”; content:”/app.php?id=”; pcre:”/app.php\?id=\w{8,}.php/”; sid:103; rev:1;)

Basically here we are telling snort to look for content starting with app.php?id= and then 8 or more characters ending with the “.php” string. This may cover different context mentioned before based on the same kind of attack.

Using that kind of filter should give us alerts performing get requests such as /app.php?id=aaaaaaaaashell.php and /app.php?id=cscsccscscsekjd9reverse.php

Preventing LFI

We can put PCRE regex rules into a more real and well known context. Let’s suppose that we want to detect potential LFI attacks looking for files in our system after exploiting a vulnerability. A typical LFI attack packet may look like the following:

So we can build a custom rule for that using this filter

alert tcp any any -> any 80 (msg:”LFI ATTACK”; content:”/app.php?id=”; fast_pattern; pcre:”/app.php\?id=.{1,2}\//”; sid:103; rev:1;)

This is telling snort to look for content starting with app.php?id= then after matching that content look for ?id= with 1 or 2 “.”‘s followed by a “/” With fast_pattern; we tell snort to first match the content and after go to match the pcre, using a lot of pcre’s may make snort so slow.

An alert will look like:

Digging deeper

Snort comes with a really large set of options, so we don’t have time for playing with them in this single blog post. For example let’s work a little bit more on our LFI example:

Here we can play with rule options like:

content:”GET”; depth:3; content:”app.php”; distance:0;

With that we are telling snort to look for “GET” in content in the first 3 bytes of the packet and right after (distance:0) start for looking for “app.php” if we switch from distance:0 to distance:10:

content:”GET”; depth:3; content:”?id=”; distance: 10;

We tell snort to look for ?id= 10 bytes after GET.

An even more advanced option could work like:

content “GET”; depth:3; nocase; content:”?id=”; distance:10; within:9; nocase;

Here we added nocase to make no distinction between upper and lower case and within that will tell snort to look just 9 bytes right after 10 bytes from GET for it’s ?id= content, so it does not need to parse the whole packet.

Here we see that we can do really cool and specific stuff with snort.

Detecting exploits and shellcode

We’ve seen snort working quite well as some sort of a “web application firewall” or alert system to be more accurate, but not everything in snort can be related to the port 80. Snort can also be used to detect general exploits such as, for example, ftp exploits and shellcode moving through the network.

In this next scenario we start with an FTP exploit going straight to the port 21. The exploit may look like this:

So we proceed to launch the exploit to one of our systems and then capture the whole session. We then open that session with wireshark to perform a further analysis.

If we look closer we can see the exploit packet. A really long buffer of chars and then the RET address as well as some shellcode

We can go closer and look for the bytes of the payload:

So at this point we have to start looking for a “signature” of the exploit. We have to look for something really unique in that exploit and hard to change, so we avoid false positives and we can be more accurate in detecting a “specific” attack. On that case a reasonable signature may involve the RET address hardcoded in the exploit, as the shellcode may change (and may be encoded) and the buffer of A’s may be replaced by B’s or something like that.

So an initial rule for that may look like:

alert tcp any any -> any 21 (msg:”FTP EXPLOIT ATTACK”; content:”| C7 31 6B 7E |”; sid:10003; rev:1;)

Here we see that if we want to match content at the byte level we have to put those bytes between |’s, the rest works as usual. But if we think about it one more time… those bytes alone may lead to a lot of false positives, so it may be better to add a second condition to make the signature more unique. In this case we see that the packet launched by the exploit is really large, as it is a buffer overflow launched over the network. So we can combine that RET address with the dsize option for a long packet, like that.

alert tcp any any -> any 21 (msg:”FTP EXPLOIT ATTACK”; dsize:>900; content:”| C7 31 6B 7E |”; sid:10003; rev:1;)

Here we say that we are looking for a packet larger than 900 bytes.

So here we see that a snort is a really versatile solution and its available as open source. Based on that we can see different ways to correctly use that software.

Using snort as a “firewall”

Using snort as a firewall can be useful if you work with a relatively small network such as a home network, using it in a big network segments may be a bad idea, you’ll tend to lose a lot of packets and also the network activity may be slowed a lot. For that you may want to think about other solutions such as suricata (snort’s brother) or maybe payed or custom solutions. Using snort as a subsystem of a bigger system or as a complementary system is always a good idea.

Resultado de imagen de snort network firewall


Using snort as a sensor/alarm:

I think that probably this is the best way to use a NIDS such as Snort, using it in various network nodes such as routers or servers to gather “threat intel” about what happens on the network, using alert rules and effectively parsing them and or inserting them into a common DB for further analysis may be a great idea I’ve personally applied that strategy and I got good results in the past.

Using snort as a packet analyzer (close to an anti-virus):

As malware researchers snort is a really useful tool for generating threat intelligence. We may work with sandboxes, reverse engineering different kinds of malware, we can use sandboxes and software such as OllyDBG, IDA or Radare to look for malware behavior on the binary/memory level but if we want to perform analysis at the network level, snort can be so useful for capturing session packets and then analyzing those packets using it’s set of rules. Sharing rules between the community may be also a great strategy. We may also want to consider using snort in combination of other systems such as OSSIM for building full scale security systems (SIEM) in companies.

We’ll be back with more examples!

Leave a Reply