Improved search rule options in Snort 2.x data Zone
Created:
Article attributes: original
Article submitted: stardust (stardust_at_xfocus.org)
The rule options of Snort 2.x have been greatly improved compared with those of earlier versions 2.0. It is necessary to introduce and analyze them.
First, translate the description of relevant rule options in the Snort user manual. Due to the poor writing of this manual, many of the meanings are repeated and lengthy, the words are inaccurate, and there are still some obvious mistakes. What should be explained carefully is not explained, the narrative order is also chaotic. What makes it hard to understand is that the sample rules in the manual are simple texts that actually adopt the image format, which is simply an example of the spam manual, therefore, there is no complete reference during translation. Instead, I have integrated and supplemented the statements that I think are correct, and adjusted the order in which some options are described. This document was written more than a year ago, when the original link for http://www.snort.org/docs/snort_manual/node14.html, for the current site, the corresponding link is almost http://www.snort.org/docs/snort_manual/node21.html.
Bytes ----------------------------------------------------------------------------------------
2.5.1 content Option
The content option is one of the most important options provided by snort. It allows users to search for specific content in a packet's Net Load and trigger corresponding actions. When a content option match is executed, the program calls the Boyer-Moore pattern matching routine to check whether the package content contains this content, if the data specified in the option is included in the packet's net load, the check returns a successful result, and other options in the rule will continue to be executed. Note that the matching of the default content option is case sensitive.
The data specified in the option may be complex; it may contain mixed text and binary data. Binary data is enclosed by common pipe (|) symbols and specified in bytecode. Bytecode is expressed in hexadecimal format, which can easily describe complex binary data. The Snort rule in this example contains the mixed text and binary data.
You can specify multiple content options in a rule to minimize false positives.
The following characters must be escaped when they appear in the content option (how to escape is not mentioned in this section at least in this manual. I will add that there are two methods: 1. use the leading "/" character 2. use the binary representation of bytes, for example, "| 3A |" for ":"):
:;/"
If the content option is prefixed with "!", It indicates that an alarm is triggered when the data does not contain the option content.
2.5.1.1 format
Content: [!] "<Content string> ";
The content option can contain multiple modifier options. Modifier options can affect the working method of the preceding content options. These modifier options are as follows:
1.
Nocase
2.
Rawbytes
3.
Depth
4.
Offset
5.
Distance
6.
Within
2.5.1.2 example
Alert tcp any-> Any 139 (content: "| 5C 00 | p | 00 | I | 00 | p | 00 | E | 00 5C | ";)
Mixed content options of binary data and text
Alert tcp any-> Any 80 (content :! "Get"; depth: 3; nocase ;)
This rule matches the condition that the first three bytes of the net packet are not "get ".
2.5.2 nocase modifier options
The nocase option modifies the content option that follows the previous step so that case sensitivity is ignored during matching.
2.5.2.1 format
Nocase;
2.5.2.2 example
Alert tcp any-> Any 21 (MSG: "FTP root"; content: "User Root"; nocase ;)
Content rules with nocase modifier options
2.5.3 rawbytes modifier options
The rawbytes option modifies the preceding content option so that it matches only the original data and ignores the decoding of those pre-processors.
2.5.3.1 format
Rawbytes;
2.5.3.2 example
Alert tcp any-> Any 21 (MSG: "Telnet NOP"; content: "| FF F1 |"; rawbytes ;)
In the preceding example, the content option matches the original network traffic instead of the Data decoded by the Telnet decoder.
2.5.4 depth modifier options
The depth option modifies the preceding content option, allowing you to specify the depth of the search mode in the data area. If depth is set to 5, it indicates starting from a certain starting point in the packet net load (if there is no other offset modifier mentioned below, it is the beginning of the data block Net Load by default) match the mode specified by the content option in the starting five bytes.
2.5.4.1 format
Depth: <number of bytes>;
2.5.5 offset modifier options
The offset option modifies the preceding content option, allowing you to specify the bytes starting from the net packet. If the offset value is set to 5, Snort searches for the mode specified by the content option after the first five bytes of the data area.
2.5.5.1 format
Offset: <number of bytes>;
Alert tcp any-> Any 80 (content: "cgi-bin/phf"; offset: 4; depth: 20 ;)
The content, offset, and depth options are combined to search for the "cgi-bin/phf" string within 20 bytes starting from the first byte of the net packet.
2.5.6 distance
The distance option modifies the preceding content option, allowing you to specify the number of bytes added to the end of the string that matches the previous content option to start searching for the matching content specified by the content option modified by distance. This modifier is similar to offset, except that it is the end of a string that matches the previous content option, rather than the beginning of the Net Load of the data area.
2.5.6.1 format
Distance: <number of bytes>;
2.5.6.2 example
Alert tcp any-> Any any (content: "ABC"; content: "def"; distance: 1 ;)
This rule example matches with a regular expression:/ABC. {1} DEF/
2.5.7
The within option modifies the content option next to the previous one, you can specify the number of bytes starting from the number of bytes specified by the distance option added to the end of the last successful match of the content option to search for the matching content specified by the content option modified by. This modifier is similar to depth, except that it is the number of bytes specified by the distance option at the end of the string that matches the previous content option, rather than the beginning of the Net Load of the data area.
2.5.7.1 format
Within: <number of bytes>;
2.5.7.2 example
Alert tcp any-> Any any (content: "ABC"; content: "EFG"; within: 10 ;)
2.5.8 uricontent
The uricontent option is used to match the URI field after normalization. This means that if you write rules to try to match the data that may be normalized, such as the "% 2f" string commonly used to traverse directories, the matching will fail.
For example, Uri:
/Scripts/.. % C0 % af ../winnt/system32/cmd.exe? /C + ver
Will be normalized:
/Winnt/system32/cmd.exe? /C + ver
/Cgi-bin/aaaaaaaaaaaaaaaaaaaaaaaaaaaa/... % 252fp % 68f?
Will be normalized:
/Cgi-bin/phf?
When you use the uricontent option to write a rule, you must specify the content that matches the Regular Expression and cannot contain the string that traverses the directory, because these will be normalized. If you want to match the data before normalization, use the content option.
Uricontent is used with the HTTP pre-processor.
2.5.8.1 format
Uricontent: [!] <Content string>;
2.5.9 isdataat options
This option is used to determine the number of bytes of data at the specified position. The modifier option is used to specify the start time of the string that matches the previous content option successfully.
2.5.9.1 format
Isdataat: <int> [, relative];
2.5.9.2 example
Alert tcp any-> Any 111 (content: "pass"; isdataat: 50, relative; content :! "| 0a |"; distance: 0 ;)
This rule searches for the "pass" string in the Net Load of the data area, and then confirms that there are at least 50 bytes of data that does not contain line breaks.
2.5.10 PCRE Option
The PCRE option allows you to use regular expressions compatible with the Perl language. For more information about the regular expression, see the PCRE Web site: http://www.pcre.org
2.5.10.1 format
PCRE: [!] "(/<RegEx>/| M <delim> <RegEx> <delim>) [ismxaegrub]";
The modifier after the expression sets some flag for compiling the regular expression.
Perl-compatible Modifier
+-+ --------------------------------------------- +
| I | insensitive to size |
+-+ --------------------------------------------- +
| S | contains line breaks in point escape characters |
+-+ --------------------------------------------- +
| Generally, the matched buffer is used as a large string |
| M |, ^, and $ match the string header and end. When M modifier is set |
| Character, ^, and $ match closely with the line break and are tightly followed by the line break |
| Condition. |
+-+ --------------------------------------------- +
| X | the space character in the pattern to be matched is ignored unless it is escaped |
| An excessively passed or in a character set. |
+-+ --------------------------------------------- +
PCRE-compatible Modifier
+-+ --------------------------------------------- +
| A | the mode must match (same as ^) at the beginning of the buffer. |
+-+ --------------------------------------------- +
| The specified $ must be matched at the end of the buffer. If e is not used |
| E | modifier. $ may match only the line break before the end of the string. |
+-+ --------------------------------------------- +
| G | by default, the greedy mode is not used. Only after the mode is used |
| Face followed by "?" Character is greedy. |
+-+ --------------------------------------------- +
Snort-specific Modifier
+-+ --------------------------------------------- +
| R | this match starts with the end of the previous successful string. |
| (Similar to distance: 0) |
+-+ --------------------------------------------- +
| U | match the decoded URI Buffer (similar to uricontent) |
+-+ --------------------------------------------- +
| B | do not use the decoded buffer (similar to rawbytes) |
+-+ --------------------------------------------- +
The modifier R and B cannot be used at the same time.
2.5.10 example
Alert IP any-> Any any (PCRE: "/blah/I ";)
2.5.11 byte_test Modifier
Converts the string at a specific position in the net packet to a numerical value and compares it with the specified value.
2.5.11 format
Byte_test: <bytes_to_convert>, <operator>, <value>, <OFFSET> [, [relative], [Big], [little], [String], [hex], [DEC], [Oct]
Bytes_to_convert
Number of extracted bytes
Operator
Operator to be executed (<,>, = ,!, &)
Value
Value compared with the converted data
Relative
Starting from the end of the last matched string
Big
Processing in big endian byte order
Little
Processing in little endian byte order
String
The converted data is stored as strings in the package.
HEX
The converted data is in hexadecimal format.
Dec
The converted data is in decimal format.
Oct
The converted data is represented in octal format.
2.5.11.2 example
Alert udp any-> Any 1237 (byte_test: 10, =, 1234567890, 0, String, Dec; MSG: "Got 1234567890! ";)
Alert udp any-> Any 1238 (byte_test: 8, =, 0 xdeadbeef, 0, String, Hex; MSG: "Got deadbeef! ";)
2.5.12 byte_jump Option
The byte_jump option is used to obtain some bytes from a certain position of the data packet, convert them to numerical values, and skip the bytes displayed in the value to the new position of the data packet for further matching. In this way, the data in the network data packet can be used to jump to the relative position.
2.5.12.1 format
Byte_jump: <bytes_to_convert>, <OFFSET> [, [relative], [Big], [little], [String], [hex], [DEC], [Oct], [align]
Bytes_to_convert
Number of bytes to be converted
Offset
Starting from where the data volume is loaded
Relative
Starting from the end of the last matched string
Big
Processing in big endian byte order (default)
Little
Processing in little endian byte order
String
The converted data is stored as strings in the package.
HEX
The converted data is in hexadecimal format.
Dec
The converted data is in decimal format.
Oct
The converted data is represented in octal format.
Align
Round the converted value to the value of the 32-bit boundary.
2.5.12.2 example
Alert udp any-> Any 32770: 34000 (content: "| 00 01 86 B8 |"; content: "| 00 00 00 01 |"; distance: 4;: 4; byte_jump: 4, 12, relative, align; byte_test: 4,>, 900, 20, relative; MSG: "statd Format String Buffer Overflow ";)
2.5.13 RegEx
The RegEx option has been replaced by the PCRE option.
2.5.14 content-list
The content-list option has been deprecated.
Bytes ----------------------------------------------------------------------------------------
This section analyzes the rule options of the new snort version.
Compared with the earlier version of Snort, the new version of the rule mainly has the following specific improvements:
1. added distance and within modifier options to the content option.
2. added the isdataat option.
3. added the byte_jump option.
4. added the byte_test option.
5. Improved Regular Expressions
Its core function is to introduce the concept of data matching relative offset. In the past, the biggest limit for Snort writing rules was that we had to hard-encode the possible location of the packet content during the net loading of the packet, due to the flexibility of the network protocol and the possibility of data packet sharding, the offset of the data to be matched in the net packet is not easy to determine, which may cause a large omission or false alarm.
For example, for MDaemon form2raw. CGI Overflow Attack detection, the net packet loading of an attack request can be matched using the following regular expression:
[GET | HEAD | post]/S +/S */form2raw. cgi [? |/S]/S * From = [^ &] {100 ,}
If you use the Snort rule options of earlier versions, the following rules can only be implemented because the pattern to be matched is:
Alert TCP! $ Home_net any-> $ home_net 3000 (MSG: "MDaemon form2raw. CGI Overflow Attack! "; Content:"/form2raw. cgi "; nocase; content:" From = "; nocase; offset: 17; depth: 15; content :! "&"; Offset: 30; depth: 120 ;)
Such a rule can only detect the following "normal" Attack Net loads:
"Get/form2raw. cgi? From = aaa... aaa & to = me@hello.org & subject = Hi & Body = Hello HTTP/1.0"
Regardless of the URI deformation methods against IDs, it is only in "/form2raw. if CGI is prefixed with a long directory, it will lead to missing results, but we cannot excessively expand the search range for the "from =" string, this may cause more false positives.
The distance and within modifier options added to the content option make it possible to match multiple modes with certain sequence and fixed interval, this is useful for matching protocol header structures with relatively fixed structures (such as SMB, sun-RPC, and DNS) in network traffic, so that you can easily check certain fields in the structure.
For the preceding form2raw. cgi Detection example, with the help of the new content modifier options, we can improve the rules to the following form:
Alert TCP! $ Home_net any-> $ home_net 3000 (MSG: "MDaemon form2raw. CGI Overflow Attack! "; Content:"/form2raw. cgi "; nocase; content:" From = "; nocase; distance: 1; content :! "&"; Within: 120 ;)
In this way, regardless of the offset of the "from =" string in the packet's net load, we can ensure that the parameter string that is connected to it is too long, this greatly improves the accuracy of detection.
The newly added isdataat is mainly used to determine the amount of data after a match. It is mainly used to determine whether the parameters after FTP-like protocol commands are too long. Because isdataat determines that the starting offset is relative, this is more accurate than the previous method to determine the length of the entire net load, because a net load may contain multiple commands and data may exist before the command.
The new byte_jump option is very powerful. It enables us to dynamically select the starting offset for matching based on the value of the network packet, in fact, this has partially implemented the Protocol Decoding capability. We can directly locate the position of the field we care about in the data packet based on the field offset information contained in the coheader, it can achieve very precise matching. This option is described in detail in the following example.
The new byte_test option is mainly used to check the values of some fields in the protocol data structure. The most common is the length of a string. This option is described in detail in the following example.
The new version of Snort enhances Regular Expressions and is widely used in many rules.
The following describes a combination of multiple options of rpc. statd Format String Attack rules to demonstrate the powerful features of the new Rule options.
An rpc. statd attack data packet may look like this. An attacker uses an rpc. statd packet with a long format string parameter to exploit the format string attack to obtain the root user permissions of the Linux system:
Frame 3 (1118 bytes on wire, 1118 bytes captured)
Ethernet II, Src: 00: 06: 5b: 9f: 95: 37, DST: 00: 01: 02: 86: A6: F3
Internet protocol, Src ADDR: 192.168.5.223 (192.168.5.223), dst addr: 202.99.11.220 (202.99.11.220)
User datateprotocol, Src port: 816 (816), DST port: 32770 (32770)
Remote Procedure Call, type: Call Xid: 0x000088ef6
Xid: 0x000088ef6 (1114148598)
Message Type: Call (0)
RPC version: 2
Program: Stat (100024)
Program version: 1
Procedure: Stat (1)
The reply to this request is in frame 4
Credentials
Flavor: auth_unix (1)
Length: 32
Stamp: 0x3db04376
Machine name: localhost
Length: 9
Contents: localhost
Fill Bytes: Opaque data
UID: 0
GID: 0
Auxiliary gids
Verifier
Flavor: auth_null (0)
Length: 0
Network status monitor Protocol
Program version: 1
V1 procedure: Stat (1)
Name :???????????????? 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 236x % N % 137x % N % 10x % N % 192x % N %%%%%%%%%%%%%%%%%%%%%% please refer to the following link for more information: when there are too many threads, too many threads?
Length: 999
Contents :???????????????? 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 236x % N % 137x % N % 10x % N % 192x % N %%%%%%%%%%%%%%%%%%%%%% please refer to the following link for more information: when there are too many threads, too many threads?
Fill Bytes: Opaque data
0000 00 01 02 86 A6 F3 00 06 5B 9f 95 37 08 00 45 00 ...... [... 7. E.
0010 04 50 00 00 40 00 01 11 D8 D6 A8 05 df ca 63. P... @...
0020 0b DC 03 30 80 02 04 3C 58 79 42 68 8e F6 00 00... 0 ...... <xybh ....
0030 00 00 00 00 02 00 01 86 B8 00 00 00 01 00 ................
0040 00 01 00 00 01 00 00 00 00 20 3D B0 43 76 00 00 ...... =. CV ..
0050 00 09 6C 6f 63 61 6C 68 6f 73 74 00 00 00 00 00... localhost .....
0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0070 00 00 00 03 E7 18 F7 ff bf 18 F7 ff bf 19 F7 ................
0080 ff bf 19 F7 ff bf 1A F7 ff bf 1A F7 ff bf 1B F7 ................
0090 ff bf 1B F7 ff bf 25 38 78 25 38 78 25 38 78 25 ...... % 8x % 8x % 8x %
00a0 38 78 25 38 78 25 38 78 25 38 78 25 38 78 25 38 8x % 8x % 8x % 8x % 8x % 8
00b0 78 25 32 36 78 25 6e 25 31 33 37 78 25 6e 25 x % 236x % N % 137x % N %
00c0 31 30 78 25 6e 25 31 39 32 78 25 6e 90 90 90 10x % N % 192x % n ....
00d0 90 90 90 90 90 90 90 90 90 90 90 90 ................
...
...
03c0 90 90 90 90 90 90 90 90 90 90 90 90 ................
03d0 90 90 90 90 90 90 31 C0 EB 7C 59 89 41 10 ...... 1 ...... | Y..
03e0 89 41 08 Fe C0 89 41 04 89 C3 Fe C0 89 01 B0 66. A ...... a ...... F
03f0 CD 80 B3 02 89 59 0C C6 41 0e 99 C6 41 08 10 89... y......
0400 49 04 80 41 04 0C 88 01 B0 66 CD 80 B3 04 B0 66 I... a... F... f
0410 CD 80 B3 05 30 C0 88 41 04 B0 66 CD 80 89 ce 88... 0... a... F .....
0420 C3 31 C9 B0 3f CD 80 Fe C1 B0 3f CD 80 Fe C1 B0. 1 ..?.....?.....
0430 3f CD 80 C7 06 2f 62 69 6e C7 46 04 2f 73 68 41 ?.... /Bin. f./Sha
0440 30 C0 88 46 07 89 76 0C 8d 56 10 8d 4E 0C 89 F3 0 .. f .. V .. n...
0450 B0 0b CD 80 B0 01 CD 80 E8 7f FF 00 ..............
The demonstration rules of Snort are as follows:
Alert udp any-> Any 32770: 34000 (content: "| 00 01 86 B8 |"; content: "| 00 00 00 01 |"; distance: 4;: 4; byte_jump: 4, 12, relative, align; byte_test: 4,>, 900, 20, relative; MSG: "statd Format String Buffer Overflow ";)
Paste the header structure of the sun-RPC protocol from TCP/IP protocol strated before analyzing the rules:
+ ---------------------- +
| Transaction ID (Xid) | 4 bytes
+ ---------------------- +
| Call (0) | 4 bytes
+ ---------------------- +
| RPC version (2) | 4 bytes
+ ---------------------- +
| Program number | 4 bytes
+ ---------------------- +
| Version number | 4 bytes
+ ---------------------- +
| Procedure Number | 4 bytes
+ ---------------------- +
|
| Credentials |
|
+ ---------------------- +
|
| Verifier |
|
+ ---------------------- +
|
| Procedure |
| Parameters |
|... |
|
+ ---------------------- +
The Snort demo rule consists of two content options, one byte_jump option, and one byte_test option.
The first content option: Content: "| 00 01 86 B8 |", used to match the program number in the SunRPC header structure: /x00/x01/x86/xb8 indicates the network byte order 100024,100024 indicates the statd program number. The offset of this string in the above attack package is 0x36.
The second content option: Content: "| 00 00 00 01 |"; distance: 4; within: 4; indicates the last matched string, in the above example, the attack package starts from 0x3a and skips 4 bytes and matches 4 bytes from there, that is to say, from the point where the offset is 0x3e, match 4 bytes to/x00/x00/x00/x01. From the above structure, the version number is skipped, because we don't care about it. The matched target is procedure number. If it is 0x00000001, it indicates the stat process.
The third option is byte_jump: 4, 12, relative, align;, indicating that the last matched string starts at the end, in the preceding example, the attack package starts with 0x3e + 0x04 = 0x42 and skips 12 bytes, that is, the offset of 0x42 + 12 = 0x4e begins to take 4 bytes, convert to an integer and round it to a multiple of 4. Then, the converted integer bytes are skipped from 0x4e + 0x04 = 0x52. From the above attack packet, we can see that the four bytes starting from the offset 0x4 are converted to the network byte order value 0x00000009, And the integer rounded to 4 is 12, that is to say, the next matching start offset of the engine will jump to the 0x4e + 4 + 12 = 0x5e place. This byte_jump operation aims to skip the Host Name field of the stat process with uncertain length.
The fourth option is byte_test: 4,>, 900, 20, relative;, which indicates the start of the current pointer, that is, the 0x5e offset jumped to by byte_jump above, skipping 20 bytes, that is, starting from the offset 0x5e + 20 = 0x72, 4 bytes are converted to an integer and 900 for comparison. If the value is greater than 0, the last condition of this rule is met. From the data in the above example, the value of the four bytes obtained from the offset 0x72 is 0x000003e7 = 999, greater than 900, so it is an attack. The 20 bytes skipped are the UID, GID, auxiliary gids, flavor, and length fields from ethereal decoding. They are 4 bytes long and 20 bytes in total.
The following are the key points of matching rules for packets decoded by Ethereal:
Remote Procedure Call, type: Call Xid: 0x000088ef6
Xid: 0x000088ef6 (1114148598)
Message Type: Call (0)
RPC version: 2
Program: Stat (100024); content: "| 00 01 86 B8 |", 0x0186b8 = 100024
Program version: 1; skip these four bytes, which is indicated by the distance: 4 modifier of the second content option.
Procedure: Stat (1); content: "| 00 00 00 01 |"; distance: 4; within: 4;
The reply to this request is in frame 4
Credentials
Flavor: auth_unix (1)
Length: 32
Stamp: 0x3db04376
Machine name: localhost
Length: 9; byte_jump: 4, 12, relative, align; skip this step by converting the four bytes to an integer.
Contents: localhost
Fill Bytes: Opaque data
UID: 0
GID: 0
Auxiliary gids
Verifier
Flavor: auth_null (0)
Length: 0
Network status monitor Protocol
Program version: 1
V1 procedure: Stat (1)
Name :???????????????? 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 236x % N % 137x % N % 10x % N % 192x % N %%%%%%%%%%%%%%%%%%%%%% please refer to the following link for more information: when there are too many threads, too many threads?
Length: 999; byte_test: 4,>, 900, 20, relative; skip the previous 20 bytes and convert the four bytes to an integer. Compared with 900, if the value is greater, it is regarded as an attack.
Contents :???????????????? 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 8x % 236x % N % 137x % N % 10x % N % 192x % N %%%%%%%%%%%%%%%%%%%%%% please refer to the following link for more information: when there are too many threads, too many threads?
Fill Bytes: Opaque data
Summary:
The concept of relative offset introduced by the new snort rule option greatly improves the flexibility and accuracy of attack detection rules. In particular, the introduction of the byte_jump option partially makes up for the weakness of Snort not decoding the application layer protocol.