Threshold and suppression rules were first introduced in Snort Version 2.0.0. They allow an administrator to control how many alerts are generated from (or to) a given host or for a particular signature. Unfortunately, they were very thinly documented and (while it might get me in a bit of trouble with the folks at Sourcefire) were a little buggy. Snort 2.1.x not only fixes the problems, it also introduces global thresholds. Global thresholds let you control alert volume for all rules. Threshold and suppression commands are, by convention, placed in the threshold.conf file in the same directory as the rule sets. While this is not required, it is a good idea to keep them in one place. Threshold and suppression rules can track by source or destination IP address. Sometimes a signature alerts on an inbound attack packet or an outbound response to an attack. It should be noted that suppression rules are applied before thresholding rules.
Threshold rules come in three flavors (excerpt from the README.thresholding file):
Alert on the first M events during the time interval, then ignore events for the rest of the time interval.
Alert every M times this event is seen during the time interval.
Alert once per time interval after seeing M occurrences of the event, then ignore any additional events during the time interval.
Threshold rules can be incorporated into the rule definitions themselves or built as standalone rules. The administrative ease of keeping the threshold rules in one place argues against incorporating them into the rules directly. When scattered among the rule sets, threshold rules can be hard to find. There are, however, some instances when it makes sense to incorporate the threshold components to a rule.
Here's an excerpt from the README.thresholding file:
There is no functional difference between adding a threshold to a rule, or using a separate threshold command applied to the same rule. There is a logical difference. Some rules may only make sense with a threshold. These should incorporate the threshold command into the rule.
For instance, when security policies are set to lock out an account after four bad password guesses, alerting on the fifth bad guess is appropriate. Such a threshold can be incorporated into the rule itself.
When incorporating thresholds into rules, the following format is used:
threshold: type [limit|threshold|both], track [by_src|by_dst], count n , seconds m ;
Here are some thresholding examples:
Logs the first event to a particular destination IP address of this signature every 60 seconds:
alert tcp $LOCAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"WEB-IIS unicode directory traversal attempt"; flow:to_server,established; content:"/..%c0%af../"; nocase; classtype:web-application-attack; reference:cve,CVE-2000-0884; threshold: type limit, track_by_dst, count 1, seconds 60; sid:981; rev:6;)
Logs every twentieth event on this signature during a 60-second
interval—so if less than 20 occur in 60 seconds, nothing gets
logged. Once an event is logged, a new time period starts for
type=threshold
. This might be used to watch for
the 403
: Forbidden
web responses where the administrator is concerned when
the incidence of this event becomes too high:
alert tcp $HTTP_SERVERS $HTTP_PORTS -> $EXTERNAL_NET any (msg:"ATTACK- RESPONSES 403 Forbidden"; flow:from_server,established; content:"HTTP/1.1 403"; depth:12; classtype:attempted-recon; threshold: type threshold, track by_dst, count 20, seconds 60; sid:1201; rev:7;)
Logs at most one event every 120 seconds if at least 4 events on this sid are fired. This is the example given previously, in which an account locks after four bad guesses. Only one alert would be generated for a locked account every two minutes:
alert tcp $SQL_SERVERS 1433 -> $EXTERNAL_NET any (msg:"MS-SQL sa login failed"; content: "Login failed for user |27|sa|27|"; flow:from_ server,established; classtype:unsuccessful-user; threshold: type both, track by_ dst, count 5, seconds 60; sid:688; rev:4;)
Standalone thresholds are written with the following syntax:
threshold gen_id gen-id, sig_id sig-id, type [limit|threshold|both], track [by_ src|by_dst], count n , seconds m
The main difference between standalone
thresholds and those incorporated into
rules is the inclusion of the gen_id
and the
sig_id
parameters. These are needed in the
standalone threshold rules to specify the rule and generators to
which the threshold applies. As discussed in Chapter 7,
gen_id
refers to the Snort generator
involved and sig_id
is the unique identifier for the rule
the threshold is being applied to. Only one threshold can be applied
per unique sig_id
. Most often, the
gen_id
is set to 1 (the Snort Rules Engine).
Here's how you would limit to logging 1 event per
120 seconds for the signature with the sig_id
of
1,759 (MS-SQL xp_cmdshell program execution):
threshold gen_id 1, sig_id 1759, type limit, track by_src, count 1, seconds 120
And limit to logging every fifth event in 120 seconds for the same signature:
threshold gen_id 1, sig_id 1759, type threshold, track by_src, count 5, seconds 120
And limit to logging just 1 event per 60 seconds, but only if we exceed 50 events in 60 seconds:
threshold gen_id 1, sig_id 1759, type both, track by_src, count 50, seconds 60
Global threshold commands are the
same as standalone thresholds, except the sig_id
is parameter is set to 0 to indicate "all
rules."
Here's how you would limit to logging 1 event per 120 seconds per IP triggering any rule generated by the Snort rules engine tracking by source address:
threshold gen_id 1, sig_id 0, type limit, track by_src, count 1, seconds 120
And here's how you'd limit to logging 1 event per 120 seconds per IP triggering any rule for any Snort event generator component tracking by destination address:
threshold gen_id 0, sig_id 0, type limit, track by_dst, count 1, seconds 120 ..."
Suppression rules are similar in syntax to standalone threshold rules. Suppression rules can suppress alerts by signature, by source or destination address, or by an entire CIDR network block. This flexibility has considerable power. Care must be taken to only suppress the correct alerts or addresses. An administrator could inadvertently suppress legitimate alerts.
Suppression rules are written with the following syntax:
suppress gen_id gen-id, sid_id sid-id, track [by_src|by_dst], ip IP/MASK-BITS
Suppress this event completely:
suppress gen_id 1, sig_id 114
Suppress this event from this source IP address:
suppress gen_id 1, sig_id 114, track by_src, ip 10.2.1.154
Suppress this event to this destination CIDR block:
suppress gen_id 1, sig_id 114, track by_dst, ip 10.2.1.0/24