Hack 82 Detect Intrusions with Snort

figs/moderate.gif figs/hack82.gif

Use one of the most powerful (and free) network intrusion detection systems available to help you keep an eye on your network.

Monitoring your logs can take you only so far in detecting intrusions. If the logs are being generated by a service that has been compromised, welcome to the security admin's worst nightmare: you can no longer trust your logs. This is where NIDS come into play. They can alert you to intrusion attempts, or even intrusions in progress.

The undisputed champion of open source NIDS is Snort (http://www.snort.org). Some of the features that make Snort so powerful are its signature-based rule engine and its easy extensibility through plug-ins and preprocessors. These features allow you to extend Snort in whichever direction you need. Consequently, you don't have to depend on anyone else to provide you with rules when a new exploit comes to your attention: with a basic knowledge of TCP/IP, you can write your own rules quickly and easily. This is probably Snort's most important feature, since new attacks are invented and reported all the time. Additionally, Snort has a very flexible reporting mechanism that allows you to send alerts to a syslogd, flat files, or even a database.

To compile and install a plain-vanilla version of Snort, download the latest version and unpack it. Run the configure script and then make:

$ ./configure && make

Then become root and run:

# make install

Note that all the headers and libraries for libpcap (http://www.tcpdump.org) must be installed before you start building Snort, or else compilation will fail. Additionally, you may need to make use of the --with-libpcap-includes and --with-libpcap-libraries configure options to tell the compiler where it can find the libraries and headers. However, you should only need to do this if you have installed the libraries and headers in a nonstandard location (i.e., somewhere other than the /usr or /usr/local hierarchy).

For example, if you have installed libpcap within the /opt hierarchy, you would use this:

$ ./configure --with-libpcap-includes=/opt/include\


Snort has the ability to respond to the host that has triggered one of its rules. This capability is called flexible response . To enable this functionality, you'll also need to use the --enable-flexresp option, which requires the libnet packet injection library (http://www.packetfactory.net/projects/libnet/). After ensuring that this package is installed on your system, you can use the --with-libnet-includes and --with-libnet-libraries switches to specify its location.

If you want to include support for sending alerts to a database, you will need to make use of either the --with-mysql, --with-postgresql, or --with-oracle options. To see the full list of configure script options, you can type ./configure --help.

After you have installed Snort, test it out by using it in sniffer mode. You should immediately see some traffic:

# ./snort -evi eth0 

Running in packet dump mode

Log directory = /var/log/snort

Initializing Network Interface eth0

        --== Initializing Snort ==--

Initializing Output Plugins!

Decoding Ethernet on interface eth0

        --== Initialization Complete ==--

-*> Snort! <*-

Version 2.0.5 (Build 98)

By Martin Roesch (roesch@sourcefire.com, www.snort.org)

12/14-16:25:17.874711 0:A:95:C7:2B:10 -> 0:C:29:E2:2B:C1 type:0x800 len:0x42 -> TCP TTL:64 TOS:0x10 ID:56177 IpLen:20 DgmLen:52 DF

***A**** Seq: 0x67E53951  Ack: 0x2BA09FF7  Win: 0xFFFF  TcpLen: 32

TCP Options (3) => NOP NOP TS: 3426501948 469087 


12/14-16:25:17.874828 0:C:29:E2:2B:C1 -> 0:A:95:C7:2B:10 type:0x800 len:0x252 -> TCP TTL:64 TOS:0x10 ID:50923 IpLen:20 DgmLen:580 DF

***AP*** Seq: 0x2BA09FF7  Ack: 0x67E53951  Win: 0x2200  TcpLen: 32

TCP Options (3) => NOP NOP TS: 469100 3426501948 


Some configuration files are provided with the Snort source distribution in the etc/ directory, but they are not installed when running make install. You can create a directory to hold these in /etc or /usr/local/etc and copy the pertinent files to it by running something similar to this:

# mkdir /usr/local/etc/snort &&\

 cp etc/[^Makefile]* /usr/local/etc/snort

You'll probably want to copy the rules directory to there as well.

Now you need to edit the snort.conf file. Snort's sample snort.conf file lists a number of variables. Some are defined with default values, and all are accompanied by comments that make this section mostly self-explanatory. Of particular note, however, are these two variables:

var HOME_NET any


HOME_NET specifies which IP address spaces should be considered local. The default is set so that any IP address is included as part of the home network. Networks can be specified using CIDR notation (i.e., xxx.xxx.xxx.xxx/yy). You can also specify multiple subnets and IP addresses by enclosing them in brackets and separating them with commas:

var HOME_NET [,]

HOME_NET can also be automatically set to the network address of a particular interface by setting the variable to $eth0_ADDRESS. In this particular case, $eth0_ADDRESS sets it to the network address of eth0.

The EXTERNAL_NET variable allows you to explicitly specify IP addresses and networks that are not a part of HOME_NET. Unless a subset of HOME_NET is considered hostile, you can just keep the default value, which is any.

The rest of the variables that deal with IP addresses or network ranges? DNS_SERVERS, SMTP_SERVERS, HTTP_SERVERS, SQL_SERVERS, and TELNET_SERVERS?are set to $HOME_NET by default. These variables are used within the ruleset that comes with the Snort distribution and can be used to fine-tune a rules behavior. For instance, rules that deal with SMTP-related attack signatures use the SMTP_SERVERS variable to filter out traffic that isn't actually related to the rule. Fine-tuning these variables not only leads to more relevant alerts and less false positives, but also to higher performance.

Another important variable is RULE_PATH, which is used later in the configuration file to include rulesets. The sample configuration file sets it to ../rules but, to be compatible with the previous examples, this should be set to ./rules since snort.conf and the rules directory are both in /usr/local/etc/snort.

The next section in the configuration file allows you to configure Snort's built-in preprocessors. These do anything from reassembling fragmented packets to decoding HTTP traffic to detecting portscans. For most situations, the default configuration is sufficient. However, if you need to tweak any of these settings, the configuration file is fully documented with each preprocessor's options.

If you've compiled in database support, you'll probably want to enable the database output plug-in, which will cause Snort to store any alerts that it generates in your database. Enable this plug-in by putting lines similar to these in your configuration file:

output database: log, mysql, user=snort password=snortpass dbname=SNORT \ host=dbserver

output database: alert mysql, user=snort password=snortpass dbname=SNORT \ host=dbserver

The first line configures Snort to send any information generated by rules that specify the log action to the database. Likewise, the second line tells Snort to send any information generated by rules that specify the alert action to the database. For more information on the difference between the log and alert actions, see [Hack #86] .

If you're going to use a database with Snort, you'll need to create a new database, and possibly a new database user account. The Snort source code's contrib directory includes scripts to create databases of the supported types: create_mssql, create_mysql, create_oracle.sql, and create_postgresql.

If you are using MySQL, you can create a database and then create the proper tables by running a command like this:

# mysql SNORT -p < ./contrib/create_mysql

The rest of the configuration file deals mostly with the rule signatures Snort will use when monitoring network traffic for intrusions. These rules are categorized and stored in separate files, and are activated by using the include directive. For testing purposes (or on networks with light traffic) the default configuration is sufficient, but you should look over the rules and decide which rule categories you really need and which ones you don't.

Now that all of the hard configuration and setup work is out of the way, you should test your snort.conf file. You can do this by running something similar to the following command:

# snort -T -c /usr/local/etc/snort/snort.conf

Snort will report any errors that it finds and then exit. If there aren't any errors, run Snort with a command similar to this:

# snort -Dd -z est -c /usr/local/etc/snort/snort.conf

Two of these flags, -d and -c, were used previously (to tell Snort to decode packet data and to use the specified configuration file, respectively). The other two are new. The -D flag tells Snort to print out some startup messages and then fork into the background. The -z est argument tells Snort's streams preprocessor plug-in to ignore TCP packets that aren't part of established sessions, which makes your Snort system much less susceptible to spoofing attacks and certain DoS attacks. Some other useful options are -u and -g, which let Snort drop its privileges and run under the user and group that you specify. These are especially useful with the -t option, which will chroot() Snort to the directory that you specify. Now you should start to see logs appearing in /var/log/snort.

See Also

  • Chapter 11, "Simple Intrusion Detection Techniques," in Building Secure Servers with Linux, by Michael D. Bauer (O'Reilly)