Tuning Snort
Richard Bejtlich
Many people are familiar
with Snort, the most popular open source intrusion detection (IDS) system [1]. This
article suggests ways to intelligently tune Snort to reduce the number of alerts
it produces. The recommendations will also help Snort generate alerts appropriate
for the monitored network.
Too many Snort users are content to
run Snort in its default configuration, confident that their Security Information
Management (SIM) or Security Event Management (SEM) tool will sort out the most
useful data. This article contends that Snort (and any IDS) is most effective when
configured to suit the environment in which it is deployed. These configuration
recommendations apply not only to detection but also to layer 7 access control (so-called
"intrusion prevention system" [IPS]) operation.
This article uses Snort 2.6.0RC1, released
April 17, 2006, as a reference implementation. (By the time you read this, Snort
2.6.0 will most likely be released.) Since July 2005, Snort rules have not been
bundled with the program's source code. Therefore, this article used the snortrules-snapshot-CURRENT.tar.gz
available as of April 18, 2006. The host operating systems is FreeBSD 6.0 with security
patches applied. Sguil 0.6.1 was the NSM suite used to analyze alerts [2]. Snort
was installed using the following syntax:
fetch http://www.snort.org/dl/prerelease/snort-2.6.0RC1.tar.gz
tar -xzf snort-2.6.0RC1.tar.gz
cd snort-2.6.0RC1
./configure --enable-dynamicplugin
make
sudo make install
Retrieving snortrules-snapshot-CURRENT.tar.gz
at the time of writing required registering with Sourcefire. The rules file is extracted
into the snort-2.6.0RC1/ directory, where it populates the rules/ and doc/ subdirectories.
Readers who have not tried Snort 2.6
may wonder about the significance of the --enable-dynamicplugin option. Beginning
with Snort 2.6, Sourcefire (the company that develops Snort) introduced the ability
to add preprocessors, detection capabilities, and rules as dynamically loadable
modules. This feature is activated by running configure with the --enable-dynamicplugin switch. Preprocessors and detection capabilities are more of an issue for Snort
developers, since few Snort users code their own features. The advantage of the
dynamic engine is that developers can write their own modules without having to
patch Snort itself [3].
Snort's operation can be controlled
via the command line and/or a configuration file, typically called snort.conf. This
article will present a few options for command-line tuning, but the majority of
the recommendations involve modifying the snort.conf file.
The simplest invocation of Snort as
an intrusion detection system would look like the following, if launched in the
snort-2.6.0RC1/ directory:
snort -i fxp0 -c etc/snort.conf -l /var/log/snort
--dynamic-preprocessor-lib-dir /usr/local/lib/snort_dynamicpreprocessor
The syntax above tells Snort to monitor the fxp0
interface and configure itself using the default snort.conf file. It logs an alert
file to /var/log/snort, along with matching packet contents in binary Libpcap format.
The final switch tells Snort where to find dynamic preprocessors, which for Snort
2.6 support SMTP (via libsf_smtp_preproc.so) and FTP/Telnet (via libsf_ftptelnet_preproc.so).
This basic invocation of Snort will work, but the analyst will likely see a huge
number of alerts that she will not care to review.
Setting Variables on the Command Line
The first step to take control of the excessive
alerts generated by Snort is to set certain important variables. Snort offers many
possibilities, but the most significant and commonly used options will appear here.
The most important variable is HOME_NET, which identifies the network that Snort
should consider its monitored network. If HOME_NET is left as the default value
of "any", Snort will apply its rule base much less selectively. For example,
consider the rule header option of rule sid 1498:
alert tcp $EXTERNAL_NET any -> $HOME_NET 8181
By default, Snort sets EXTERNAL_NET to any
and HOME_NET to any. If HOME_NET is not set, then this rule header matches
traffic from the Internet to port 8181 on any host on the monitored network, or
from the monitored network to port 8181 on any host on the Internet. Assuming the
analyst is less concerned with outbound traffic, HOME_NET should always be set.
Setting HOME_NET to reflect the
monitored network does not imply one should not care about outbound activity. Assigning HOME_NET is a practical matter, since most Snort rules assume HOME_NET represents
the monitored network. Those who want to use Snort in an extrusion detection capacity
should explicitly configure Snort with this in mind, rather than simply letting HOME_NET default to any.
An analyst can set the HOME_NET variable from the command line with the -h switch. The following command is accompanied
by selected startup output:
snort -i fxp0 -c etc/snort.conf -l /var/log/snort -h 192.18.0.0/16
--dynamic-preprocessor-lib-dir /usr/local/lib/snort_dynamicpreprocessor
Running in IDS mode
--== Initializing Snort ==--
Initializing Output Plugins!
Initializing Preprocessors!
Initializing Plug-ins!
Parsing Rules file etc/snort.conf
...edited...
4096 Snort rules read...
4096 Option Chains linked into 204 Chain Headers
0 Dynamic rules
...edited...
Rule application order: ->activation->dynamic->pass->drop->alert->log
Log directory = /var/log/snort
Loading all dynamic preprocessor libs from
/usr/local/lib/snort_dynamicpreprocessor...
Loading dynamic preprocessor library
/usr/local/lib/snort_dynamicpreprocessor/libsf_ftptelnet_preproc.so... done
Loading dynamic preprocessor library
/usr/local/lib/snort_dynamicpreprocessor/libsf_smtp_preproc.so... done
Finished Loading all dynamic preprocessor libs from
/usr/local/lib/snort_dynamicpreprocessor
...edited...
Initializing Network Interface fxp0
Var 'fxp0_ADDRESS' defined, value len = 22 chars, \
value = 198.18.0.0/255.255.0.0
Decoding Ethernet on interface fxp0
--== Initialization Complete ==--
,,_ -*> Snort! <*-
o" )~ Version 2.6.0RC1 (Build 52) FreeBSD
'''' By Martin Roesch & The Snort Team:
http://www.snort.org/team.html
(C) Copyright 1998-2006 Sourcefire Inc., et al.
Preprocessor Object: SF_SMTP Version 1.0 <Build 1>
Preprocessor Object: SF_FTPTELNET Version 1.0 <Build 1>
Not Using PCAP_FRAMES
This invocation of Snort activates 4096 rules
and two dynamic preprocessors. The Not Using PCAP_FRAMES line indicates Snort
is not using Phil Woods' shared memory Libpcap, available on Linux but not
FreeBSD. Also observe that Snort sets the variable fxp0_ADDRESS as 198.18.0.0/255.255.0.0,
because the sniffing interface in this example is 198.18.166.79, netmask 255.255.0.0.
In production, Snort should listen on an interface with no IP address and no capability
to exchange Address Resolution Protocol (ARP) traffic. For example:
ifconfig fxp0 -arp up
ifconfig fxp0
fxp0: flags=88c3<UP,BROADCAST,RUNNING,NOARP,SIMPLEX,MULTICAST> mtu 1500
options=8<VLAN_MTU>
inet6 fe80::203:47ff:fe0f:1f3c%fxp0 prefixlen 64 scopeid 0x1
ether 00:03:47:0f:1f:3c
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
When fxp0 has no interface assigned, Snort reports
the following:
Initializing Network Interface fxp0
OpenPcap() device fxp0 network lookup:
fxp0: no IPv4 address assigned
Decoding Ethernet on interface fxp0
Snort will accept other variable definitions on
the command line, provided they are listed in the format -S VAR=VALU. For example,
here the SMTP_SERVERS and HTTP_SERVERS variables are explicitly defined
via command-line settings:
-S SMTP_SERVERS=198.18.0.1 \
-S HTTP_SERVERS=[\66.102.7.147,66.102.7.104,66.102.7.99\]
Snort's startup output will reflect these
changes:
Var 'HTTP_SERVERS' defined, value len = 39 chars, value =
[66.102.7.147,66.102.7.104,66.102.7.99]
Running in IDS mode
--== Initializing Snort ==--
Initializing Output Plugins!
Initializing Preprocessors!
Initializing Plug-ins!
Parsing Rules file etc/snort.conf
+++++++++++++++++++++++++++++++++++++++++++++++++++
Initializing rule chains...
Var 'HOME_NET' defined, value len = 3 chars, value = any
Var 'EXTERNAL_NET' defined, value len = 3 chars, value = any
Var 'DNS_SERVERS' defined, value len = 3 chars, value = any
Var 'SMTP_SERVERS' redefined
Var 'HTTP_SERVERS' redefined
...truncated...
HOME_NET, EXTERNAL_NET, and DNS_SERVERS are not set on the command line, so they default to any. SMTP_SERVERS and HTTP_SERVERS are set with -S. Observe that although SMTP_SERVERS and HTTP_SERVERS have
values defined via -S, only the values for HTTP_SERVERS are reported on startup.
Whichever variable is listed last will be displayed, although tests show the variables
are still set. For example, reversing the order of the variables on the command
line results in no declaration for HTTP_SERVERS on startup, but the following
appears instead:
Var 'SMTP_SERVERS' defined, value len = 10 chars,
value = 198.18.0.1
Other variables will be mentioned in a later section
that discusses settings in snort.conf.
Berkeley Packet Filters on the Command Line
In addition to setting variables, another command-line
modification Snort users often make is to add Berkeley Packet Filter instructions
to watch or ignore certain hosts or IP addresses. For example, the following BPF
tells Snort to ignore a large netblock owned by Google, as well as any traffic on
port 6346 (TCP or UDP):
not net 66.102.0.0/20 or port 6346
Simply appending that filter to the end of the
previous Snort invocations will meet our requirements. Complex BPF statements can
be placed in a file and read via the command-line switch -F.
This is the extent to which most users
tune Snort from the command line. In fact, many users prefer to centralize Snort
control within the snort.conf configuration file. The snort.conf file is important
enough to be included in a version control system like the GNU Revision Control
System (RCS) or similar means to track changes in configuration files. At the very
least, the snort.conf file should be copied, with changes made to successive copies.
This preserves the original snort.conf for reference.
Setting Variables in snort.conf
The first set of variables one should tune in
Snort appears at the beginning of the snort.conf file. They are shown here as an
excerpt from the default snort.conf, with comments removed:
var HOME_NET any
var EXTERNAL_NET any
var DNS_SERVERS $HOME_NET
var SMTP_SERVERS $HOME_NET
var HTTP_SERVERS $HOME_NET
var SQL_SERVERS $HOME_NET
var TELNET_SERVERS $HOME_NET
var SNMP_SERVERS $HOME_NET
var AIM_SERVERS (a long list of AOL Instant Messenger server \
subnets follows)
By default all of these are set to "any",
with the exception of AIM_SERVERS. Leaving the default value set to "any"
results in many so-called "false positive" alerts, frequently triggered
by innocent outbound Web surfing and similar activity. Simply setting HOME_NET
will cut down on unwanted alerts. Specifically defining the DNS, SMTP, HTTP, SQL,
TELNET, and SNMP servers will cause Snort to apply its rules directly to the hosts
running those services.
The following reflects a variety of
means to notate appropriate values for these variables:
A single server running Telnet:
var TELNET_SERVERS 10.1.1.23
One subnet hosting Web servers:
var HTTP_SERVERS 10.80.0.0/16
Three specific SQL servers:
var SQL_SERVERS [10.2.3.4,10.2.3.5,10.2.3.6]
Besides variables representing IP addresses, Snort
offers several variables for setting TCP and UDP ports:
var HTTP_PORTS 80
var SHELLCODE_PORTS !80
var ORACLE_PORTS 1521
These ports can be important to define manually
if one runs nonstandard Web servers, for example. If a network offers Web services
on port 8080 to the Internet, Snort will not detect attacks when HTTP_PORTS
is set to port 80 only.
Analysts should keep in mind that they
can create custom variables and use them in rules they build. For example, one could
define SGUIL_SERVERS and SGUIL_PORTS to define the IP addresses and ports
used by their Sguil systems. Rules built for custom purposes are best saved in a
local.rules file.
The final variable available in snort.conf
is the location of the rule set Snort should parse on startup:
var RULE_PATH ../rules
This setting can suit the analyst's needs.
For example, Sguil users often set the following:
var RULE_PATH /nsm/rules/sensornamePreprocessor Settings: http_inspect
Because this article focuses on tuning Snort,
it will not cover every aspect of the snort.conf file. The next section of the configuration
file that can be adjusted for easy tuning is the http_inspect preprocessor.
Many analysts see alerts from this system that they would often choose to ignore.
This is the default configuration:
preprocessor http_inspect: global \
iis_unicode_map unicode.map 1252
preprocessor http_inspect_server: server default \
profile all ports { 80 8080 8180 } oversize_dir_length
500
The preprocessor http_inspect: global section
is best left unedited. The second section can be modified thus:
preprocessor http_inspect_server: server default \
profile all ports { 80 8080 8180 } oversize_dir_length
500 \
no_alerts
It is important to realize that setting no_alerts
only tells the http_inspect preprocessors to stop generating alerts. Alerts
contained in the Snort rule set will continue to be generated even when no_alerts
is set for http_inspect_server. For example, the default http_inspect
preprocessor creates an alert when it sees bare byte encoding. This and other alerts
are represented as saved output from Sguil, the open source NSM suite:
Count:1 Event#1.1580 2006-05-05 02:49:25
http_inspect: BARE BYTE UNICODE ENCODING
69.243.40.116 -> 204.176.49.2
IPVer=4 hlen=5 tos=0 dlen=1311 ID=14181 flags=2 offset=0 \
ttl=63 chksum=37672
Protocol: 6 sport=1133 -> dport=80
Seq=3395044305 Ack=2403798475 Off=8 Res=0 Flags=***AP*** Win=5840 \
urp=18838 chks
um=0
This alert was triggered by outbound Web surfing
observed by an untuned Snort deployment.
The Snort manual states:
"Bare byte encoding is an IIS
trick that uses non-ASCII characters as valid values when decoding UTF-8 values.
This is not in the HTTP standard, as all non-ASCII values have to be encoded with
a %... The alert on this decoding should be enabled, because there are no legitimate
clients that encode UTF-8 this way since it is non-standard."
In practice, legitimate traffic in
bare-byte format often appears on the wire. When no_alerts is enabled, these
alerts are no longer reported.
Preprocessor Settings: sfPortscan
Snort's portscan detector is implemented
by the sfPortscan preprocessor. SfPortscan is powerful but prone to generating alerts
if left unconfigured. The default settings are simple:
preprocessor sfportscan: proto { all } \
memcap { 10000000 } \
sense_level { low }
If these settings produce an acceptable number
of alerts, there is no need for tuning. However, two options can be very helpful
when one wants to reduce unwanted alerts:
ignore_scanners { Snort IP List }
ignore_scanned { Snort IP List }
Note that { Snort IP List } takes a form similar
to the lists defined in the earlier variables section, for example, { 66.102.7.147,66.102.7.104,66.102.7.99 }.
Set ignore_scanners to a list of
source IPs you consider benign. For example, if a host or set of hosts offers a
legitimate scanning service, they can be included within ignore_scanners.
Set ignore_scanned to a list of
destination IPs for which you do not want to see alerts. The snort.conf file suggests
that Snort's sfPortscan preprocessor might think a system like a Syslog server
is the target of scans. When multiple legitimate hosts send UDP Syslog messages
to the Syslog server, an untuned sfPortscan might flag that activity as reconnaissance.
If you wanted to explicitly watch for
scanning from a defined set of hosts, a third option could be set:
watch_ip { Snort IP List }
This option is not used very often, since most
analysts want to detect reconnaissance from all potentially malicious parties.
In production it is common to first
run sfPortscan untuned and then set ignore_scanners and/or ignore_scanned
as necessary.
The following shows a TCP Portsweep
alert generated by sfPortscan:
Count:211 Event#1.58096 2006-05-02 17:55:22
portscan: TCP Portsweep
22.35.23.119 -> 209.247.220.152
IPVer=4 hlen=5 tos=0 dlen=161 ID=4569 flags=2 offset=0 ttl=0 \
chksum=38235
Protocol: 255 Payload:
50 72 69 6F 72 69 74 79 20 43 6F 75 6E 74 3A 20 Priority Count:
35 0A 43 6F 6E 6E 65 63 74 69 6F 6E 20 43 6F 75 5.Connection Cou
6E 74 3A 20 37 0A 49 50 20 43 6F 75 6E 74 3A 20 nt: 7.IP Count:
35 0A 53 63 61 6E 6E 65 64 20 49 50 20 52 61 6E 5.Scanned IP Ran
67 65 3A 20 32 31 36 2E 34 30 2E 33 33 2E 33 31 ge: 216.40.33.31
3A 32 30 39 2E 32 34 37 2E 32 32 30 2E 31 35 33 :209.247.220.153
0A 50 6F 72 74 2F 50 72 6F 74 6F 20 43 6F 75 6E .Port/Proto Coun
74 3A 20 31 0A 50 6F 72 74 2F 50 72 6F 74 6F 20 t: 1.Port/Proto
52 61 6E 67 65 3A 20 32 35 3A 32 35 0A Range: 25:25.
Note that sfPortscan reports its findings via
a pseudo-packet, where the majority of the IP payload is dummy data. Details on
the event are contained in the pseudo-packet payload. This event is a TCP Portsweep,
which sfPortscan believes is an instance of a single host trying to contact one
port on multiple targets.
In this case, 22.35.23.119 is a mail
server on the monitored network. The sfPortscan preprocessor observes the mail server
making outbound connections to port 25 TCP on other mail servers, such as 216.40.33.31
and 209.247.220.153. Because sending mail is a legitimate event, an analyst could
add 22.35.23.119 to the ignore_scanners list.
The following shows a TCP Portscan
alert:
Count:7 Event#1.261192 2006-05-03 14:52:25
portscan: TCP Portscan
192.168.1.114 -> 6.16.237.138
IPVer=4 hlen=5 tos=0 dlen=162 ID=36870 flags=2 offset=0 ttl=0
\ chksum=27553
Protocol: 255 Payload:
50 72 69 6F 72 69 74 79 20 43 6F 75 6E 74 3A 20 Priority Count:
35 0A 43 6F 6E 6E 65 63 74 69 6F 6E 20 43 6F 75 5.Connection Cou
6E 74 3A 20 32 0A 49 50 20 43 6F 75 6E 74 3A 20 nt: 2.IP Count:
35 0A 53 63 61 6E 6E 65 72 20 49 50 20 52 61 6E 5.Scanner IP Ran
67 65 3A 20 31 39 32 2E 31 36 38 2E 31 2E 37 31 ge: 192.168.1.71
3A 31 39 32 2E 31 36 38 2E 31 2E 31 32 31 0A 50 :192.168.1.121.P
6F 72 74 2F 50 72 6F 74 6F 20 43 6F 75 6E 74 3A ort/Proto Count:
20 36 0A 50 6F 72 74 2F 50 72 6F 74 6F 20 52 61 6.Port/Proto
Ra
6E 67 65 3A 20 31 33 39 3A 38 30 38 30 0A nge: 139:8080.
Sguil provides the following open port data:
6.16.237.138:8080
6.16.237.138:445
6.16.237.138:1494
6.16.237.138:1845
6.16.237.138:139
6.16.237.138:3425
A sfPortscan TCP Portscan alert represents a case
where one or more source IPs connect to multiple ports on a target system. In this
case, IPs in the range 192.168.1.71-192.168.1.121 have connected to multiple ports
on 6.16.237.138. For whatever reason, if an analyst did not care to see alerts involving
scans against 6.16.237.138, she could add 6.16.237.138 to the ignore_scanned
list.
Rule Selection
Near the end of the snort.conf, one sees a variety
of include statements. These define the rule sets that Snort will parse. An excerpt
from the stock snort.conf appears below:
include $RULE_PATH/icmp.rules
...edited...
include $RULE_PATH/nntp.rules
include $RULE_PATH/other-ids.rules
# include $RULE_PATH/web-attacks.rules
# include $RULE_PATH/backdoor.rules
# include $RULE_PATH/shellcode.rules
Here the icmp.rules, nntp.rules, and other-ids.rules
are enabled, but web-attacks.rules, backdoor.rules, and shellcode.rules are disabled.
Deactivating the potentially unwanted icmp.rules set can be done by adding the #
comment symbol before the include statement. Activating backdoor.rules is as simple
as removing the # comment symbol.
Similarly, disabling individual rules
can be done by adding the # comment symbol in front of the rule statement. For example,
the following appear in the bad-traffic.rules file:
# alert ip $EXTERNAL_NET any -> $HOME_NET any \
(msg:"BAD-TRAFFIC bad frag bits";
fragbits:MD; classtype:misc-activity; sid:1322; rev:7;)
alert ip $EXTERNAL_NET any -> $HOME_NET any \
(msg:"BAD-TRAFFIC Unassigned/Reserved IP protocol"; ip_proto:>134; \
reference:url,www.iana.org/assignments/protocol-numbers; \ classtype:non-standard-protocol;
sid:1627; rev:3;)
Rule sid 1322 is disabled by default, while rule
sid 1627 is enabled by default.
Commenting out a rule is the most common
way to disable a noisy source of alerts, but it may not be the best way to manage
rules.
Thresholding and Suppression
The end of the snort.conf file shows the following:
# include threshold.conf
The threshold.conf file controls application of
thresholding and suppression. Thresholding gives Snort guidance on when it should
generate an alert. Suppression tells Snort to completely disable alert generation
for specified rules.
Thresholding is an extremely powerful
technique. Consider the sample syntax and three examples in threshold.conf:
# Threshold commands are formatted as:
# threshold gen_id gen-id, sig_id sig-id, type limit|threshold|both,
track
# by_src|by_dst, count n , seconds m
# Limit to logging 1 event per 60 seconds
# threshold gen_id 1, sig_id 1851, type limit, track by_src,
count 1,
# seconds 60
# Global Threshold - Limit to logging 1 event per 60 seconds per
IP
# triggering each rule (rules are gen_id 1).
# threshold gen_id 1, sig_id 0, type limit, track by_src,
count 1,
# seconds 60
# Global Threshold - Limit to logging 1 event per 60 seconds per
IP
# triggering any alert for any event generator
# threshold gen_id 0, sig_id 0, type limit, track by_src,
count 1,
# seconds 60
The file etc/gen-msg.map, which shows sources
for alert generated, says gen_id 1 refers to alerts caused by Snort rules:
1 || 1 || snort general alert
The first threshold statement will only show one
instance of sid 1851 (WEB-MISC active.log access) no more than once per 60 seconds.
The second threshold statement applies
to all Snort rules, since the sig_id is set to 0 and not to a specific sid like
sid 1851. The second statement will result in Snort generating only one rule-based
alert per unique source IP address every 60 seconds.
The third threshold statement applies
to all Snort rules (sid_id 0) and all alert sources (gen_id 0). For example,
alerts from Snort rules (gen_id 1), http_inspect (gen_id 119), etc.
are covered by gen_id 0. Snort will generate only one alert per unique source
IP address every 60 seconds.
Thresholding is powerful because it
can reduce the accumulation of alerts that might not be especially interesting to
an analyst. For example, an intruder could scan a class B address using Nmap, potentially
generating thousands of ICMP PING NMAP alerts. Thresholding could reduce the number
of alerts significantly.
Beyond thresholding, suppression can
be used to selectively tell Snort not to alert on specified activity. Suppression
is an excellent way to modify Snort's alerting behavior without altering its
rule set.
The threshold.conf file examples are
straightforward:
# Suppress this event completely
#
# suppress gen_id 1, sig_id 1852
#
# Suppress this event from this IP
#
# suppress gen_id 1, sig_id 1852, track by_src, ip
10.1.1.54
#
# Suppress this event to this CIDR block
#
# suppress gen_id 1, sig_id 1852, track by_dst, ip
10.1.1.0/24
The first statement shows disabling sid 1852 via
suppression, rather than commenting out the WEB-MISC robots.txt access alert in
web-misc.rules.
The second statement tells Snort not
to generate alerts on sid 1852 if the source IP is 10.1.1.54. The same effect might
be accomplished by modifying the rule header of sid 1852, which is:
tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS
to the following:
tcp !10.1.1.54 any -> $HTTP_SERVERS $HTTP_PORTS
However, that alteration is not as specific as
leaving EXTERNAL_NET set and simply omitting 10.1.1.54 via suppression.
The third statement tells Snort not
to generate alerts using rule sid 1852 if the destination IP is in the 10.1.1.0/24
netblock. This modification to sid 1852 accomplishes a similar goal:
tcp $EXTERNAL_NET any -> !10.1.1.0/24 $HTTP_PORTS
Again, it is not as precise, and the technique
relies on altering the rules.
Where possible, it is easier to modify
Snort's behavior using variable settings, thresholding, and suppression, leaving
the rules files as provided by Sourcefire. Custom rules can be placed in a local.rules
file. This strategy simplifies rule updates. However, frequent use of suppression
will hamper Snort's performance. Snort will process traffic faster when alerts
are completely disabled. Suppression is a post-processing way to prevent rule generation,
meaning Snort will devote resources to certain rules that could have been completely
disabled instead.
Sguil Alert Aggregation
Sguil is an open source interface to NSM data,
such as alert data from Snort, session data from SANCP, and full content data [4].
Sguil provides two additional mechanisms to reduce the number of alerts shown to
an analyst. First, similar alerts are aggregated when they appear in the Sguil console.
Second, Sguil aggregates alerts from the same source IP, to the same destination
port, involving one or more unique destination IPs. The following is a text representation
of two aggregated alerts:
--------------------------------------------------------------------
Count:2 Event#1.661 2006-04-22 11:39:33
http_inspect: OVERSIZE CHUNK ENCODING
69.243.40.166 -> 204.2.177.48
IPVer=4 hlen=5 tos=0 dlen=835 ID=45899 flags=2 offset=0 ttl=63
chksum=39325
Protocol: 6 sport=40919 -> dport=80
Seq=2002731009 Ack=2098431754 Off=8 Res=0 Flags=***AP*** \
Win=32767 urp=40469 chk
sum=0
These two alerts appear like the following when
shown individually:
--------------------------------------------------------------------
Count:1 Event#1.661 2006-04-22 11:39:33
http_inspect: OVERSIZE CHUNK ENCODING
69.243.40.166 -> 204.2.177.48
IPVer=4 hlen=5 tos=0 dlen=835 ID=45899 flags=2 offset=0 ttl=63
chksum=39325
Protocol: 6 sport=40919 -> dport=80
Seq=2002731009 Ack=2098431754 Off=8 Res=0 Flags=***AP*** \
Win=32767 urp=40469 chk
sum=0
--------------------------------------------------------------------
Count:1 Event#1.681 2006-04-22 23:30:15
http_inspect: OVERSIZE CHUNK ENCODING
69.243.40.166 -> 204.157.9.191
IPVer=4 hlen=5 tos=0 dlen=416 ID=34922 flags=2 offset=0 ttl=63
chksum=27896
Protocol: 6 sport=48728 -> dport=80
Seq=3262000869 Ack=3118356063 Off=8 Res=0 Flags=***AP*** \
Win=5840 urp=32625 chks
um=0
An example with two alerts is not that impressive,
but consider cases where a single aggregated alert represents dozens or hundreds
of events!
Aggregation is an automatic feature
in Sguil, although one aspect of its operation can be set in the server/sguild.conf
file. By default, Sguil will aggregate alerts that share the same sensor, source
IP, and event message:
set SENSOR_AGGREGATION_ON 1
If an analyst wishes to aggregate alerts regardless
of the sensor that generated them, this value can be altered:
set SENSOR_AGGREGATION_ON 0
No other parameters can be modified.
Sguil Auto-Categorization
Sguil also offers auto-categorization as a means
to reduce the number of alerts an analyst must examine. Sguil was designed to be
used by managed security services providers (MSSPs) who take accountability for
investigating and validating alerts from IDSs. Sguil lets analysts assign one of
eight categories to alert data, such as Category I for root-level intrusions or
Category VI for reconnaissance [5]. After an analyst assigns a category to an alert
or set of alerts, the alert disappears from the Sguil console. It is marked with
the designated alert category in the Sguil database, along with the username of
the analyst making the decision, a timestamp, and an optional comment.
Analysts can tell Sguil to automatically
categorize events. This means they will not appear in the Sguil console, but they
will still be generated by Snort and stored in the Sguil database. Sguil auto-categorization
("auto-cat") is controlled by the autocat.conf file in the sguil-0.6.1/server/
directory. Here is the synatx followed by an example:
# <erase time>||<sensorName>||<src_ip>||<src_port>||<dst_ip>|| \
<dst_port>||<pro to>||<sig msg>||<cat value>
none||ANY||ANY||ANY||ANY||ANY||ANY||MS-SQL Worm propagation attempt||13
none||ANY||ANY||ANY||ANY||ANY||ANY||MS-SQL version overflow attempt||13
The first field lets Sguil users determine when
the auto-cat should expire. A value of none makes the auto-cat a permanent condition.
The second field lets analysts decide the sensors to which the auto-cat rule will
apply. The next five fields give analysts control over the IPs, ports, and protocol
associated with events that trip rules. The <sig msg> field is the means by
which a specific rule is identified. Regular expressions can be used here. The final
field is the categorization value, which for this example is 13 (Category III, attempted
compromise).
In sum, these two auto-cat rules will
prevent any MS-SQL Worm propagation attempt or MS-SQL version overflow attempt alerts
from appearing in the Sguil console. They will instead be stored in the database
with the Category III categorization value applied automatically by Sguil.
Conclusion
Sensor tuning is critical to obtaining desired
results from any intrusion detection system. Making the basic changes described
in this article will significantly improve a sensor's output and an analyst's
productivity. For more information on tuning Snort, refer to the latest Snort manual
and related documentation [6]. References
1. Snort -- http://www.snort.org
2. Sguil -- http://www.sguil.net
3. Most Snort users customize Snort by writing their own rules.
Beginning with Snort 2.6.0RC1, a new C-style rule language is available. The Snort
2.6 manual discusses the new rule format in section 5.1.5 (Dynamic Rules). Also
see "Shared Object Rules vs. the New Rules Language", http://www.mcabee.org/lists/snort-users/May-06/msg00105.html.
4. SANCP -- http://www.metre.net/sancp.html
5. Sguil alert categories -- http://sguil.sourceforge.net/index.php?page=incident_categories
6. Snort documentation -- http://www.snort.org/docs/ and http://oinkmaster.sourceforge.net/avoiding_snort_alerts.txt
Richard Bejtlich is founder of TaoSecurity (www.taosecurity.com)
and the TaoSecurity Blog (taosecurity.blogspot.com). He is also author of The Tao
of Network Security Monitoring and Extrusion Detection, and co-author of Real Digital
Forensics.
|