How to Build Rules
Problem
I see all these examples. Now, how do I create my own rules?
Solution
This is a rough example of the Snort rule language and its capabilities. We'll take some generic rules from the official Snort rules so that you can look them up later when you want to try them on your network. These examples will demonstrate a simple protocol identifier, port usage, and finally, packet details for application data.
Protocol rules
Snort can detect when an IP protocol is in use on the network. For example, Snort Identification (SID) number 2187from the official Snort rulesdetects when protocol 55 (IP Mobility) is in use on the network.
alert ip any any -> any any (msg:"Bad-traffic IP Proto 55 IP Mobility"; ip_proto:55; reference:bugtraq,8211; reference:cve, 2003-0567; classtype:non-standard-protocol; sid:2187; rev:3;)
This official signature from www.snort.org also uses of one of the other keywords from the Snort language: reference. This keyword can link to a URL for information, bugtraq, CVE, ARCHNIDS, the MacAfee virus database, and even a file on the system. However, this will alert on any packet traveling over protocol 55, no matter what its source or destination is. This rule has undergone three revisions to get to the current point.
Port rules
This example looks for a particular port in use on the network. In this example, we don't care what the payload is in the packet; we just care about the protocol and the port in use. One word of caution: be very careful about using this type of rule. It can flood Snort when used for a common port. However, this rule would be good for a policy-based IDS infrastructure in which a given port should never be used on the network and you want to be notified when client machines try to use it. This example detects IRC connections over the default port of 6667/tcp from our network.
Alert tcp $HOME_NET any -> any 6667 (msg:"IRC port in use"; flow:from_client,stateless; sid:10550; rev:1;)
One problem is that IRC can use more than one port. 6667-7001/tcp is its default range. So let's change that rule to detect when any of these ports are in use on the network.
First, add a variable to the snort.conf file:
var IRC_PORTS 6667:70001
Then rewrite the rule to reflect the change.
Alert tcp $HOME_NET any -> any $IRC_PORTS (msg:"IRC ports in use"; flow:from_client,stateless; sid:10550; rev:2;)
Application rules
Sometimes you'll want to detect when something happens inside of an application or protocol such as when a Microsoft IIS server has been exploited successfully. This example again pulls from the official Snort rules for SID number 2123. This rule shows some of the power of the Snort engine and rules language in filtering out traffic. It also shows how much detail it can extract from a packet.
Alert tcp $HOME_NET !21:23 -> $EXTERNAL_NET any (msg:"ATTACK-RESPONSES Microsoft cmd.exe banner"; flow:from_server,established; content: "Microsoft Windows"; content:"|28|C|29| Copyright 1985-"; distance:0; content:"Microsoft Corp."; distance:0; reference:nessus,11633; classtype:successful-admin; sid:2123; rev:2;)
This rule says to ignore any traffic coming back on ports 21-23/tcp and to get very specific packet details. For example, it uses the content keyword that locates either ASCII text in the packet payload (content:"Microsoft Corp.") or raw binary values in the packet (content:"|28|C|29|"). The binary data is broken up by the pipe (|) character and represents the HEX value of the binary data. This rule also uses the distance keyword to skip down bytes into the packet for analysis. If the packets you're looking for are large and common, this can help in finding the "bad" packets in a stream of good connections.
Finally, this rule uses the flow keyword. This keyword marks that the rule only runs on packets that are:
- Part of an established connection. (The TCP three-way handshake has been completed.)
- Part of a stream that's returning from the server. If we are recording full TCP sessions, our previous packet was most likely some kind of exploit packet, and it was successful given this rule being fired.
Discussion
Having seen the previous examples, you should realize that the rules language is rich with options to use for detecting traffic on your network. One caveat is that any encrypted trafficsuch as HTTPS trafficcan't be unencrypted with Snort. You can work around this if you encrypt the connections to the border of your network but keep the link to the web servers inside the network unencrypted. This could be accomplished through use of a secure proxy or SSL accelerator card. This might also make it easier to determine the cause of issues with any of your web-based applications. You might be thinking that rules can get quite complicated. One of the nice things about a tool as popular as Snort is that there is a large community of people willing to help answer questions and problems. Local Snort user groups and the Snort-sigs mailing list are just a few of the possible sources of help.
The Snort rules have a basic format that expands for more specific needs.
(msg:"Tell the user what I'm tracking"; ;; ;)
This can be broken down and identified as shown in Table 3-1.
Part |
Information |
---|---|
Snort action |
This can be one of three keywords. alert sends an alarm on this signature. log doesn't create an alarm, it just log this alarm (to a file, for example). pass is used mostly for policy based IDS. It tells the Snort engine to pass only packets that match the signature, no matter what else is in the packet(s). |
Protocol |
This keyword tells Snort what protocol to monitor. It can be one of the more common protocols like tcp, udp, and icmp. Or it can be IP in general to monitor another IP protocol. However, with IP, you need to add the keyword ip_proto, followed by the number of the protocol, in your /etc/protocols file on Unix systems. You can find a complete list of IANA protocols at www.iana.org/assignments/protocol-numbers. |
Source IP |
This is the host or group of IP addresses from which Snort will be looking for the connection to originate. |
Source ports |
This is the originating port from which Snort will be looking for the connection to start. For most connections, the ports are dynamic, and as a result, pass Snort the keyword any, and the source port will not matter. |
Direction |
This tells Snort whether to look for the connection to start from your source IP or from your destination IP. This can be in the form of -> for source-to-destination, <- for destination-to-source, or <-> for bidirectional traffic. |
Destination IP |
This is the destination IP or group of IP addresses where Snort will look for the connection to end. |
Destination port |
This is the destination port of the traffic that we are looking for: 80 for HTTP, 21 for FTP, and 23 for Telnet connections, just to name a few. |
Message |
This is the comment field of a Snort alarm. This information is displayed to an alarm manager such as ACID or syslog. |
Class type |
This is a priority helper. If you're using a tool like Barnyard to prioritize alarms into those that need to be looked at immediately or those that can wait until a slower time during the shift/day/etc., this is the way to mark them. For example, attempted-admin is one name while network-scan is another. For the full list of classes, check out the Snort source code manual. |
Snort Identification (SID) number |
This is the "unique" number assigned to your rule. If you create your own rule, the convention is to number it starting above 10,000. This makes an obvious distinction between the official Snort rules and your creations. |
Revision number |
This is an optional keyword, but you will find it useful once you start creating multiple rules. It can also be useful if you have to keep track of rule changes for an entire IDS team. |
Table 3-1 lists only a core set of keywords. There are more language keywords that allow for a much more granular level of analysis and detection into network traffic.
See Also
Snort user groups
Snort-sigs
Snort users' mailing lists
Snort documentation for the most current rule language changes
Keeping the Rules Up to Date
|