BigAdmin System Administration Portal
Feature Article
Print-friendly VersionPrint-friendly Version

Introduction to Intrusion Detection With Snort

Amy Rich, September 2005

Abstract: After a brief discussion of intrusion detection systems (IDS), this article focuses on a pattern-matching network-based IDS, Snort.

Contents:

As soon as someone discovers a new computer security vulnerability, hordes of crackers start knocking at the doors of computers worldwide to see if they can penetrate their defenses. Many sites employ a combination of border router firewalls and host-based packet filters and wrappers to protect themselves, but what if the vulnerability is in the very mechanism that's used to secure a service? How can systems administrators know that their machines are under attack and/or have been compromised? The best way to catch the crackers in the act is to use an intrusion detection system (IDS).


What Is Intrusion Detection?

Intrusion detection is the methodology by which undesirable or aberrant activity is detected on a host or a network. The two main approaches to intrusion detection systems are host-based (HIDS) and network-based (NIDS). A combination of both provides the most complete coverage, but a site's needs and resources may dictate that it uses one or the other.

Host-Based Detection

Host-based intrusion detection systems, as the name implies, are installed on each end host and look for attacks directed directly at the host. Most HIDS employ automated checks of log files, file checksums, file and directory permissions, local network port activity, and other basic host security items. HIDS offer the benefit of being able to detect attacks local to the machine or on an encrypted or switched network where a NIDS might have issues. HIDS provide a wealth of forensic data and can often determine whether or not an attack, originating from the local host or the network, succeeded or failed. Some disadvantages to HIDS include the administrative and computing overhead of running them on each machine and the potential compromise of the HIDS in the event of a successful attack. Some popular HIDS include Tripwire, COPS, Tiger, and AIDE.

Under the Solaris 10 Operating System, systems administrators can use BART, the Basic Audit Reporting Tool, to track files at a system level. On earlier versions of Solaris, checksums for system files can be matched against the Solaris Fingerprint Database. While neither of these is a full-blown HIDS, they do provide some basic functionality for detecting modified files.

Network-Based Detection

Network-based intrusion detection systems run on one or several critically placed hosts and view the network as a whole. NIDS use NICs running in promiscuous mode to capture and analyze raw packet data in real time. Most NIDS use one of two methods to identify an attack, statistic anomaly detection or pattern-matching detection.

In the statistic anomaly detection model, the software discovers intrusions by looking for activity that is different from a user's or system's normal behavior. The baseline for normal behavior is established by profiling user, host, or network activity for some learning period. After the learning period ends, the anomaly detection-based IDS scans for usage which deviates from the baseline. The advantage to an anomaly-based IDS is that it does not have to be specifically trained to look for a given attack and can often spot new attacks before they are well publicized. The downside, of course, is that there is also a good chance of receiving false positives even with an extensive learning period and frequent tweaking.

Because an anomaly-based IDS is relatively high maintenance, professionals whose sole job function is not site security are more likely to employ some form of pattern-matching detection. In this case, the IDS compares activity to signatures of known attacks and flags them when it finds a match. The attack signatures are usually stored in some form of database and regularly updated as new attacks emerge. The advantages to a pattern-matching IDS include an easier and shorter implementation time and learning curve for the administrator as well as the reporting of fewer false positives. On the downside, these systems rely on frequent rule upgrades, often from outside sources, and cannot detect attacks until they have a pattern to do so. They're also more easily fooled by the obfuscation and evasion attempts of crackers.

Snort, a Pattern-Matching NIDS

Since the topic of IDS covers a lot of ground, I'll limit the scope of this article to the discussion of one of the more popular pieces of NIDS software, Snort. Snort can perform real-time packet logging, protocol analysis, and content searching/matching. It can be used to detect a variety of attacks and probes such as stealth port scans, CGI-based attacks, Address Resolution Protocol (ARP) spoofing, and attacks on daemons with known weaknesses. Snort utilizes descriptive rules to determine what traffic it should monitor and a modularly designed detection engine to pinpoint attacks in real time. When an attack is identified, Snort can take a variety of actions to alert the systems administrator to the threat.

Several important components are at work behind the Snort NIDS: the packet sniffer, preprocessors, detection engine, logging and alerting mechanisms, and output processors. The packet sniffer listens to all IP packets on the wire and decodes them. The preprocessors take the decoded packets and perform some preliminary tasks, such as defragmentation. The detection engine, the heart of the Snort IDS, performs pattern matches on the data stream to identify known attack signatures. The logging and alerting mechanisms define how recognized attacks will be handled. The output processors define how the output of the logging and alerting system looks.

The Snort web site includes the free source code, subscription access to Sourcefire VRT Certified Rule Updates, documentation, user forums, training resources, and a wealth of other information.


Installing Snort and Supporting Software

Snort has a few prerequisites that need to be installed before compilation. The instructions below assume that the build machine already has a well-defined development tool chain installed (SUNWbtoo, SUNWbtool, SUNWsprot, gcc, Flex, Bison, and the rest). To get started, download, unpack, and install libpcap, used by Snort to read raw packets from the NIC. Note that if you've installed tcpdump, you may already have a copy of libpcap on your machine.

wget http://www.tcpdump.org/release/libpcap-0.8.3.tar.gz
tar zxf libpcap-0.8.3.tar.gz
cd libpcap-0.8.3
../configure 
make
make install

Next, download, unpack, and install the Perl Compatible Regular Expressions (PCRE) library. Go to http://prdownloads.sourceforge.net/pcre/pcre-6.1.tar.bz2 and select a mirror from which to download. Once you have the file, run:

bzcat pcre-6.1.tar.bz2 | tar xf -
cd pcre-6.1
../configure
make
make install

Finally, download the source to Snort, unpack it, configure it, and install it (if your libpcap include files and libraries are in a non-traditional place, you can specify their location using --with-libpcap-* options to configure):

wget http://www.snort.org/dl/current/snort-2.3.3.tar.gz
tar zxf snort-2.3.3.tar.gz
cd snort-2.3.3
../configure
make
make install

Now that you have a successful Snort installation, let's take a look at how it operates and what it can do.


Running Snort as a Simple Packet Sniffer/Logger

Under the Solaris OS, Snort runs in three different modes: sniffer mode, packet logger mode, and NIDS mode. In sniffer mode, Snort operates much like a basic snoop or tcpdump command and just reads the packets from the network and displays them on the screen. Most users will not use Snort in plain sniffer mode, since there are other system tools available. If you just want to view the packet headers, simply run:

snort -v

To view packet data as well, add the -d switch. To view the data link layer, add the -e switch. The switches can be specified in any order, separately or together. The following two commands behave exactly the same:

snort -vde
snort -e -v -d

In packet logger mode, the captured data is logged to the directory hierarchy, which you specify with the -l flag. Snort will create subdirectories and log packets based on the address of the remote or local host address. To log relative to the local host network, specify your network with the -h flag:

mkdir /tmp/snort.log
snort -de -l /tmp/snort.log -h 192.168.1.0/24

If both the source and destination host of the recorded packet are on the home network, the packet is logged to the directory of the machine with the higher source/destination port number. If both machines are on the home network, and the source and destination port are the same, the packet is logged to the subdirectory of the source machine.

For any serious logging, it's highly suggested to store the logs in tcpdump-compatible binary format. This logs all packets to one compact file that can later be read back by any sniffer which supports the tcpdump format. To capture packets:

snort -l /tmp/snort.binarylog -b

The packets can be read back from the log file by running Snort in playback mode:

snort -dvr /tmp/snort.binarylog

Snort as an IDS: the Snort Configuration File

In NIDS mode, Snort matches packet bytes against a set of rules and takes the specified action if a match occurs. When running as an IDS, the administrator needs to specify the name of a rules file. The Snort source code comes with a default rules file called etc/snort.conf which can be placed into a location of your choice (usually /usr/local/etc/snort.conf). Use this file as a starting point for creating your own Snort installation, turning on binary logging and fast alerts once you have it customized to your liking:

snort -b -A fast -c /usr/local/etc/snort.conf

Looking at this file, you'll notice several types of directives: include, var, and config, preprocessor, and output.

Snort var Statements

The var statement defines a simple substitution variable, much like shell code. The syntax for defining a variable is:

var <name> <value>
var RULE_PATH /usr/local/etc/snort/rules

Variables can be referenced as follows:

Variable Syntax Description
$var The meta-variable
$(var) Replaces with the contents of var in the expression
$(var:-default) Defines the contents of var as "default" if var is undefined
$(var:?error message) Replaces with the contents of var in the expression or prints out "error message" and exits if var is undefined

The default snort.conf file includes a number of var directives, such as RULE_PATH and all of the _NET, _SERVERS, and _PORTS variables, which you'll want to customize for your environment.

Snort include Statements

include statements allow the addition of other configuration files so that various types of configuration information and rules can be split out into logically contained sets. The example snort.conf file includes various rules files from the rules subdirectory in the Snort source tree:

include classification.config
include reference.config
include $RULE_PATH/local.rules
include $RULE_PATH/bad-traffic.rules
....

Snort config Statements

The config statement defines command-line and other Snort configuration options. The example snort.conf file includes one config directive, flowbits_size. The included files classification.config and reference.config define various classification and reference settings:

config flowbits_size: 256
config classification: not-suspicious,Not Suspicious Traffic,3
config reference: bugtraq   http://www.securityfocus.com/bid/ 

The flowbits_size config option specifies the maximum number of flowbit tags that can be used within a ruleset. The classification config option defines rule classifications, and the reference config option defines external attack identification systems. We'll discuss the classification option in more depth when we look at rules. For a list of all of the available configuration options, see the Snort manual.

Snort preprocessor Statements

If we're looking for realistic attacks, Snort often needs to be able to massage the data before it tries to find matches against its rules database. Perhaps the packets are fragmented, part of a portscan, or an ARP spoof, or have encoded characters in a telnet stream or URI. This is where the preprocessors come into play.

Snort's modular preprocessor architecture consists of small C programs which take some action on a packet. These C routines are compiled into a library when you build Snort. The routines are each called after Snort decodes a packet but before it is sent to the detection engine. Developers can also write their own specialized preprocessor modules and recompile them into Snort as detailed in the doc/README.PLUGINS file of the source code. Since each preprocessor is called for each packet, enabling a large number of preprocessors in the snort.conf file can considerably impact Snort's performance. Support for the following preprocessors is included in the default Snort compile:

Portscan Detector (portscan)
Logs the start and end of portscans from a source IP. If a log file is specified, it logs the type of scan and the destination IPs and ports.
Portscan Ignorehosts (portscan-ignorehosts)
Modifies the portscan detector to ignore TCP Syn and UDP portscans from certain hosts.
sfPortscan (sfportscan)
Detects excessive negative responses from scanning tools such as Nmap.
Frag2 (frag2)
Reassembles fragmented packets.
Stream4 (stream4 and stream4_reassemble)
Provides TCP stream reassembly and stateful analysis.
Flow (flow)
Unifies the state-keeping mechanisms for Snort.
Flow-Portscan (flow-portscan)
Detects portscans based off of flow creation in the flow preprocessors.
Telnet Decode (telnet_decode)
Normalizes telnet control protocol characters from the session data. By default, it examines ports 21 (FTP), 23 (telnet), 25 (SMTP), and 119 (NNTP).
RPC Decode (rpc_decode)
Normalizes RPC multiple fragmented records into a single unfragmented record. By default, it examines ports 111 (rpc) and 32771 (various RPC services).
Performance Monitor (perfmonitor)
Measures Snort's real-time and theoretical maximum performance.
HTTP Inspect (http_inspect and http_inspect_server)
Decodes and normalizes buffers of stateless HTTP transactions.
ASN.1 Detection (asn1)
Detects malicious encoding within the packet.
X-Link2State Mini-Preprocessor (xlink2state)
Detects attacks against the X-Link2State vulnerability in Microsoft Exchange Server.

Detailed information on each of the supplied preprocessors can be found in the preprocessor section of the Snort manual.

Snort output Statements

Snort's output modules run when the alert or logging modules of Snort are called and format the output data. When multiple plug-ins of the same type (log or alert) are specified, they are handled in sequence. The output modules supplied with Snort are:

alert_syslog
Sends alerts to the syslog facility.
alert_fast
Prints one-line alerts to the specified output file.
alert_full
Prints alerts with the full packet headers out to the logging directory. The use of this output module is discouraged because the constant file creation greatly impacts Snort's performance.
alert_unixsock
An experimental output module which prints alerts to programs listening to a UNIX socket.
log_tcpdump
Print packets to the specified tcpdump-style log file for later analysis.
database
Stores log and alert messages in an SQL database back end.
csv
Stores log and alert messages as the specified format in the specified log file.
unified
Stores log and alert messages to two separate binary log files. Since the records are separated into two different files and stored in binary format, this style provides the best performance.
log null
Akin to using snort -n, this output module does not log the packet after triggering an alert.

Snort Rules, Configuring the Detection Engine

The detection engine is truly the heart of Snort's functionality. Snort uses a simple, flexible rules description language to describe how data should be handled. Snort rules are usually written in one line but may, like shell code, span multiple lines by appending the backslash (\) character to the end of an incomplete line. Let's take a look at the following rule from rules/dns.rules as an example:

alert tcp $EXTERNAL_NET any -> $HOME_NET 53 \
(msg:"DNS EXPLOIT named 8.2->8.2.1"; flow:to_server,established; \
content:"../../../"; reference:bugtraq,788; reference:cve,1999-0833; \
classtype:attempted-admin; sid:258; rev:6;)

This rule says to look for packets from any external source to any internal source on port 53 (DNS) where the content matches "../../../". This is an attempted exploit for an old version of BIND 8 which is documented by bugtraq and CVE. If a packet matches this rule, then Snort triggers an alert. Each rule is divided into two sections, the header (everything before the open paren) and the options (everything enclosed in the parens). Let's break the rule down into its different components.

The Rule Header

The header contains some criteria for matching the rule against a packet and dictates what action a rule will take if a match occurs. The general structure of the header is shown in Table 1.

Table 1: Rule Header Structure for Snort
Action Protocol Address Port Direction Address Port
alert tcp $EXTERNAL_NET any -> $HOME_NET 53
 

The action must be one of the following or user defined:

alert
Generate an alert using the selected alert method, and then log the packet.
log
Log the packet.
pass
Ignore the packet.
activate
Alert and then turn on another dynamic rule.
dynamic
Remain idle until activated by an activate rule, then act as a log rule.

The specified protocol must be one of these: icmp, ip, tcp, or udp.

The two address sections may contain a single IP address, CIDR blocks, or a list comprising any combination of the two. The single IP or CIDR block notation may also be negated with the ! character to indicate that a match should be made on any IP address but the one(s) listed. Some examples of valid addresses include:

192.168.1.0/24
!192.168.1.0/24
10.1.1.1
[192.168.1.0/24,10.1.1.1]
![192.168.1.0/24,10.1.1.1]

The address section may also contain the keyword any to imply that any address should match.

The port number fields define the port or range of ports applied to the preceding address. If the left side of a port range is left blank, Snort assumes that it should match on all ports less than or equal to that specified on the right side of the port range. If the right side of a port range is left blank, Snort assumes that it should match on all ports greater than or equal to that specified on the left side of the port range. Lists of ports are not yet supported but are planned for future code releases. Like addresses, ports and port ranges may also be negated with the ! character, and the keyword any indicates that all ports should match. When specifying a protocol which does not use ports, such as ICMP, the port field has no meaning and should be left as the keyword any. Some examples of valid port declarations include:

111
!443
:1023
1024:
6000:6010

The direction field determines the direction of traffic flow. If the direction field is ->, the address/port combination on the left-hand side is the source and that on the right is the destination. If it's <-, then the left-hand side is the destination and the right-hand side is the source. If it's <>, then Snort considers the address/port as either source or destination. This syntax is useful for analyzing both sides of something such as a telnet conversation.

The Rule Options

Rule options are separated from each other using a semicolon (;), and option keywords are separated using a colon (:). Four types of options are usable within a rule:

meta-data
Provide information about the rule but do not have any affect during detection.
payload
Look for data inside the packet payload.
non-payload
Look for non-payload data.
post-detection
Rule-specific triggers that happen after a rule runs.

Let's go back and look at our example rule:

alert tcp $EXTERNAL_NET any -> $HOME_NET 53 \
(msg:"DNS EXPLOIT named 8.2->8.2.1"; flow:to_server,established; \
content:"../../../"; reference:bugtraq,788; reference:cve,1999-0833; \
classtype:attempted-admin; sid:258; rev:6;)

This rule includes eight options, two of which are the same but with different values (as shown in Table 2).

Table 2: Example Snort Rule Options
Option Type Option Keywords
msg meta-data "DNS EXPLOIT named 8.2->8.2.1"
flow non-payload to_server,established
content payload "../../../"
reference meta-data bugtraq,788
reference meta-data cve,1999-0833
classtype meta-data attempted-admin
sid meta-data 258
rev meta-data 6
 

The msg option informs the alerting engine what message to print. Special rule characters such as : and ; may be escaped within the msg option with the backslash (\) character.

The flow option is used in conjunction with TCP stream reassembly to indicate that rules should apply only to certain kinds of traffic flow. In our example, a match should occur only when the client requests the content from the server and the connection is already established.

The content option allows Snort to perform a case-sensitive search for specific content in the packet payload. The option to the content keyword can contain mixed text and binary data. Binary data is usually enclosed within two pipe characters (|) and represented as hexadecimal byte code. The content keyword also has several modifiers which change how the content match is applied. Take a look at the content section of the Snort manual for an in-depth explanation.

As we previously covered, the reference option defines a link to external attack identification systems: in this case, bugtraq id 788 and Mitre's Common Vulnerabilities and Exposures id CVE-1999-0833.

The classtype option indicates what type of attack the packet attempted. A full list of all the default classtype values is available as part of the classtype section of the Snort manual. The classtype uses classifications defined in the configuration file distributed with the Snort source code as etc/classification.config. The syntax of this classification config option is: <class name>,<class description>,<default priority>. The priority is an integer value, usually 1 for high priority, 2 for medium, or 3 for low. The classification for attempted-admin appears as follows in etc/classification.config:

config classification: attempted-admin,Attempted Administrator Privilege Gain,1

The sid option, in combination with the rev option, uniquely identify a Snort rule by correlating the individual rule ID with the revision of the rule.


Managing and Updating Rules

Once Snort is running and triggering alerts, you can spot many of the attempted attacks on your machines. Since Snort is a pattern-matching IDS, though, you need up-to-date rules in order to catch the latest vulnerabilities. Sourcefire, the company behind Snort development, offers four ways to obtain Snort rules. The first method is to retrieve the latest Snort source distribution and use the rules contained therein. In addition, you can download newer rules from the Snort Download Rules page. To receive rules in real time, you need to purchase a subscription to the VRT rules. These rules are later released without cost to the registered Snort users. Lastly, there are Snort rules submitted by the open source community. Any registered Snort user may also submit a rule for consideration or discuss Snort rules on the Snort-sigs mailing list.

Once you have new rules, you can either merge them by hand, do a straight replace (assuming you've made no customizations at all), or use a tool to do the work in an automated fashion. One of the more popular rule management tools is a perl script called oinkmaster. Oinkmaster downloads a specified file, unpacks it, and looks for a rules subdirectory. All the rules files in this directory specified in the oinkmaster.conf file are processed and then written back out. If you've specified changes to a specific rule in the oinkmaster.conf file, such as disabling a rule, then oinkmaster preserves those changes when it copies the new rules files into place. Once you've read over the changes oinkmaster made, you can restart Snort to pick up the new rules.


Resources

Unless otherwise licensed, code in all technical manuals herein (including articles, FAQs, samples) is provided under this License.


BigAdmin