SysAdminMag.com
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 installRetrieving 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_dynamicpreprocessorThe 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 8181By 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_FRAMESThis 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: activeWhen 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 fxp0Snort 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.1Other 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 6346Simply 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.23One subnet hosting Web servers:
var HTTP_SERVERS 10.80.0.0/16Three 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 1521These 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 ../rulesThis setting can suit the analyst's needs. For example, Sguil users often set the following:
var RULE_PATH /nsm/rules/sensorname Preprocessor Settings: http_inspectBecause 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 500The 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_alertsIt 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=0This 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 \<br> 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 \<br> 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:3425A 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.rulesHere 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 \<br> (msg:"BAD-TRAFFIC bad frag bits"; fragbits:MD; classtype:misc-activity; sid:1322; rev:7;) alert ip $EXTERNAL_NET any -> $HOME_NET any \<br> (msg:"BAD-TRAFFIC Unassigned/Reserved IP protocol"; ip_proto:>134; \<br> reference:url,www.iana.org/assignments/protocol-numbers; \<br> 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.confThe 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 60The 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 alertThe 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/24The 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_PORTSto the following:
tcp !10.1.1.54 any -> $HTTP_SERVERS $HTTP_PORTSHowever, 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_PORTSAgain, 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*** \<br> Win=32767 urp=40469 chk sum=0These 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*** \<br> 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*** \<br> Win=5840 urp=32625 chks um=0An 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 1If an analyst wishes to aggregate alerts regardless of the sensor that generated them, this value can be altered:
set SENSOR_AGGREGATION_ON 0No 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.