Introduction
Snort is a powerful and lightweight Network Intrusion Detection System. It has the capability for real-time traffic analysis and logging of IP network packets, and can perform protocol analysis, as well as search/match content. It can detect various attack methods and generate real-time alerts for attacks. Additionally, Snort has excellent extensibility and portability. This article will discuss how to develop Snort rules.
1. Basics
Snort uses a simple rule description language that is easy to extend yet quite powerful. Here are some basic concepts:
Each Snort rule must be contained in a single line, as its rule interpreter cannot parse multi-line rules. Note: Some examples in this article are split into two lines due to formatting reasons. Every Snort rule can be divided into two logical parts: the rule header and the rule options. The rule header includes: rule’s action, protocol, source/destination IP address, subnet mask, and source/destination port. Rule options contain alert messages and information about anomalous packets (signatures), using these signatures to determine whether to take the action specified by the rule.
Here is an example:
alert tcp any any -> 192.168.1.0/24 111(content:”|00 01 86 a5|”;msg:”mountd access”;)
Table 1. A simple Snort rule
Everything from the beginning to the leftmost parenthesis belongs to the rule header section, and the part within the parentheses belongs to the rule options. The words before the colons in the rule options are called option keywords. Note that rule options are not necessary for every rule, as they provide a more detailed definition of packets to gather or alert on. Snort only executes rule actions on packets that match all options. If many options are combined, they are logically “ANDed” together. Let’s start with the rule header.
1.1 Include
The rules file used by Snort is specified in the command line, and the include keyword allows this rule file to include rules from other files, very similar to #include in C language. Snort will read and replace the include keyword with the contents of the included file.
Format:
include
Note: There is no semicolon at the end of the line.
1.2 Variables
Variables can be defined within Snort rule files.
Format:
var
Example:
var MY_NET 192.168.1.0/24,10.1.1.0/24 $MY_NET any (flags:S;msg:”SYNMETA packet”;)
Table 2. Definition and usage of variables
Rule variable names can be modified using various methods, employing the $ operator to define meta-variables. These modification methods can be combined using variable modification operators: ? and -.
$var: Define a meta-variable
$(var): Use the content of variable var as variable name
$(var:-default): Use the content of variable var as variable name, if var is not defined, use default as the variable name
$(var:?message): Use the content of variable var as variable name, if unsuccessful, print error message and exit.
For example:
var MY_NET $(MYU_NET:-192.168.1.0/24) tcp any any -> $(MY_NET:?MY_NET is undefined!) 23
Table 3. Advanced variable application
2. Rule Headers
2.1 Rule Action
The rule header contains some information, including: which packets, the origin of the packets, what type of packets, and how to handle matching packets. The first item in each rule is the rule action. The rule action tells Snort how to handle packets when a match is found. In Snort, there are five default handling methods: alert, log, pass, activate, and dynamic.
alert: Generate alert using the selected alert method and record the packet
log: Record the packet
pass: Ignore the packet
activate: Alert and then activate other dynamic rules
dynamic: Remain idle until activated by an activete rule, acting as a log rule
You can also define your own rule types, linking them with one or several output plugins, and then use these rule types in Snort rules.
This example will create a type that outputs logs only in tcpdump format:
ruletype suspicious
{
type log
output log_tcpdump: suspicious.log
}
The following example will create a type that sends logs to syslog and MySQL database:
ruletype redalert
{
type alert
output alert_syslog:LOG_AUTH LOG_ALERT
output database:log,user=snort dbname=snort host=localhost
}
2.2 Protocol
The second item in each rule is the protocol field. Currently, Snort can analyze protocols such as TCP, UDP, and ICMP. In the future, support may be offered for ARP, ICRP, GRE, OSPF, RIP, IPX, and other protocols.
2.3 IP Address
Below the rule header is the IP address and port information. The keyword “any” can be used to define any IP address. Snort does not support host name resolution, so addresses must be in numeric/CIDR format. /24 indicates a class C network; /16 signifies a class B network; while /32 indicates a specific host address. For example, 192.168.1.0/24 represents addresses from 192.168.1.1 to 192.168.1.255.
In rules, you can use the negation operator to modify IP addresses. It instructs Snort to match all IP addresses except the ones listed. The negation operator is denoted by !. For example, using the negation operator can easily rewrite the rule in Table 1 to alert on data from the external network heading inward.
alert tcp !192.168.1.0/24 any -> 192.168.1.0/24 111(content:”|00 01 86 a5|”;msg:”external mountd access”;)
Table 4. Rule using IP address negation operator
The IP address in the rule above indicates: all source IP addresses are not internal network addresses, while the destination address is an internal network address.
You can also define a list of IP addresses (IP list). The format for an IP address list is as follows:
[IP address1/CIDR, IP address/CIDR, …]
Note that there can be no spaces between IP addresses. For example:
alert tcp ![192.168.1.0/24, 10.1.1.0/24] any -> [192.168.1.0/24, 10.1.1.0/24] 111 (content:”|00 01 86 a5|”;msg:”external mountd access”;)
2.4 Port Numbers
In rules, there are several ways to specify port numbers, including: any, static port number definition, port range, and negation definition. “any” represents any legal port number; a static port number represents a single port number, such as: 111 (portmapper), 23 (telnet), 80 (http), etc. The range operator “:” can be used to specify a range of port numbers. There are various ways to use the range operator to achieve different objectives, for example:
log udp any any -> 192.168.1.0/24 1:1024
Logs UDP packets from any port with destination port number between 1 and 1024
log tcp any any -> 192.168.1.0/24 :600
Logs TCP packets from any port with destination port number less than or equal to 6000
log tcp any :1024 -> 192.168.1.0/24 500:
Logs TCP packets with source port number less than or equal to 1024 and a destination port number greater than or equal to 500
Table 5. Port range examples
You can also use the logical NOT operator “!” to perform port negation. The logical NOT operator can be used for other rule types (except the “any” type, for obvious reasons). For example, if you want to log all ports except X-window system ports, you can use the following rule:
log tcp any any -> 192.168.1.0/24 !6000:6010
Table 6. Logical port negation
2.5 Direction Operator
The direction operator “->” indicates the flow direction of packets. To its left is the source address and source port, and to its right the destination address and port. There is also a bi-directional operator “<>”, which allows Snort to record/analyze data transmission bidirectionally between two IP addresses/ports within the rule, such as a telnet or POP3 session. The rule below records bidirectional data transmission for a telnet session:
log !192.168.1.0/24 any <> 192.168.1.0/24 23
Table 7. Snort rule using bidirectional operator
activate/dynamic rules
Activate/dynamic rules extend Snort’s functionality. Using activate/dynamic rule pairs, you can use one rule to activate another. When a specific rule triggers, if you want Snort to continue recording packets that meet the criteria, the use of activate/dynamic rule pairs is very convenient. An activate rule is very similar to an alert rule, except it has a required option, “activates.” Dynamic rules are also similar to log rules but require an “activated_by” option. Dynamic rules also require a “count” option. When an activating rule triggers, it activates the dynamic rule indicated by the number following the activate/activated_by option, logging count packets.
Here is an activate/dynamic rule pair:
activate tcp !$HOME_NET any -> $HOME_NET 143 (flags:PA;content:”|E8C0FFFFFF|in|;activates:1;
Table 8. activate/dynamic rule pair
This rule makes Snort alert when detecting an IMAP buffer overflow and record the subsequent 50 packets from outside $HOME_NET to port 143 of $HOME_NET. If the buffer overflow is successful, then the following 50 packets sent to the same service port (in this example, port 143) of this network will have very important data useful for future analysis.
3. Rule Options
Rule options form the core of Snort’s intrusion detection engine. They are very easy to use, yet quite powerful and easy to extend. In each Snort rule, options are separated by semicolons. The rule option keyword and its parameters are separated by a colon. Up until the point of ……..