The content keyword is one of the more important features of Snort. It allows the user to set rules that search for specific content in the packet payload and trigger response based on that data. Whenever a content option pattern match is performed, the Boyer-Moore pattern match function is called and the (rather computationally expensive) test is performed against the packet contents. If data exactly matching the argument data string is contained anywhere within the packet's payload, the test is successful and the remainder of the rule option tests are performed. Be aware that this test is case sensitive.
The option data for the content keyword is somewhat complex; it can contain mixed text and binary data. The binary data is generally enclosed within the pipe (4#4) character and represented as bytecode. Bytecode represents binary data as hexadecimal numbers and is a good shorthand method for describing complex binary data. The example below shows use of mixed text and binary data in a Snort rule.
Note that multiple content rules can be specified in one rule. This allows rules to be tailored for less false positives.
If the rule is preceded by a !, the alert will be triggered on packets that do not contain this content. This is useful when writing rules that want to alert on packets that do not match a certain pattern
Note:
Also note that the following characters must be escaped inside a content rule:
; \ " |
content:[!]"<content string>";
alert tcp any any -> any 139 (content:"|5c 00|P|00|I|00|P|00|E|00 5c|";)
alert tcp any any -> any 80 (content:!"GET";)
Note:
A ! modifier negates the results of the entire content search, modifiers included. For example, if using content:!"A"; within:50; and there are only 5 bytes of payload and there is no "A" in those 5 bytes, the result will return a match. If there must be 50 bytes for a valid match, use isdataat as a pre-cursor to the content.
|
The content keyword has a number of modifier keywords. The modifier keywords change how the previously specified content works. These modifier keywords are:
The protected_content keyword provides much of the functionality of the content keyword, however it performs and is utilized in a very different manner. The primary advantage protected_content has over content is that protected allows one to hide the target contents by only revealing secure hash digests of said content. As with the content keyword, its primary purpose is to match strings of specific bytes. The search is performed by hashing portions of incoming packets and comparing the results against the hash provided, and as such, it is computationally expensive.
Currently, it is possible to utilize the MD5, SHA256, and SHA512 hash algorithms with the protected_content keyword. A hashing algorithm must be specified in the rule using hash if a default has not be set in the Snort configuration. Additionally, a length modifier must be specified with protected to indicate the length of the raw data.
As with content, it is possible to use multiple protected_content rules can in one rule. Additionally, it is possible to mix multiple protected_content rules with multiple content rules.
If the rule is preceded by a !, the alert will be triggered on packets that do not contain the target content. This is useful when writing rules that want to alert on packets that do not match a certain pattern
Note:
The protected_content keyword can be used with some (but not all) of the content modifiers. Those not supported include: nocase fast_pattern depth within
|
protected_content:[!]"<content hash>", length:orig_len[, hash:md5|sha256|sha512];
alert tcp any any <> any 80 (msg:"MD5 Alert"; protected_content:"293C9EA246FF9985DC6F62A650F78986"; hash:md5; offset:0; length:4;)
alert tcp any any <> any 80 (msg:"SHA256 Alert"; protected_content:"56D6F32151AD8474F40D7B939C2161EE2BBF10023F4AF1DBB3E13260EBDC6342"; hash:sha256; offset:0; length:4;)
Note:
A ! modifier negates the results of the entire content search, modifiers included. For example, if using content:!"A"; within:50; and there are only 5 bytes of payload and there is no "A" in those 5 bytes, the result will return a match. If there must be 50 bytes for a valid match, use isdataat as a pre-cursor to the content.
|
The hash keyword is used to specify the hashing algorithm to use when matching a protected_content rule. If a default algorithm is not specified in the Snort configuration, a protected_content rule must specify the algorithm used. Currently, MD5, SHA256, and SHA512 are supported.
hash:[md5|sha256|sha512];
The length keyword is used to specify the original length of the content specified in a protected_content rule digest. The value provided must be greater than 0 and less than 65536.
length:[<original_length>];
The nocase keyword allows the rule writer to specify that the Snort should look for the specific pattern, ignoring case. nocase modifies the previous content keyword in the rule.
nocase;
alert tcp any any -> any 21 (msg:"FTP ROOT"; content:"USER root"; nocase;)
The rawbytes keyword allows rules to look at the raw packet data, ignoring any
decoding that was done by preprocessors. This acts as a modifier to the
previous content option.
HTTP Inspect has a set of keywords to use raw data, such as http_raw_cookie, http_raw_header, http_raw_uri etc that match on specific portions of the raw HTTP requests and responses.
Most other preprocessors use decoded/normalized data for content match by default, if rawbytes is not specified explicitly. Therefore, rawbytes should be specified in order to inspect arbitrary raw data from the packet.
rawbytes;
This example tells the content pattern matcher to look at the raw traffic, instead of the decoded traffic provided by the Telnet decoder.
alert tcp any any -> any 21 (msg:"Telnet NOP"; content:"|FF F1|"; rawbytes;)
The depth keyword allows the rule writer to specify how far into a packet Snort should search for the specified pattern. depth modifies the previous `content' keyword in the rule.
A depth of 5 would tell Snort to only look for the specified pattern within the first 5 bytes of the payload.
As the depth keyword is a modifier to the previous content keyword, there must be a content in the rule before depth is specified.
This keyword allows values greater than or equal to the pattern length being searched. The minimum allowed value is 1. The maximum allowed value for this keyword is 65535.
The value can also be set to a string value referencing a variable extracted by the byte_extract keyword in the same rule.
depth:[<number>|<var_name>];
The offset keyword allows the rule writer to specify where to start searching for a pattern within a packet. offset modifies the previous 'content' keyword in the rule.
An offset of 5 would tell Snort to start looking for the specified pattern after the first 5 bytes of the payload.
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before offset is specified.
This keyword allows values from -65535 to 65535.
The value can also be set to a string value referencing a variable extracted by the byte_extract keyword in the same rule.
offset:[<number>|<var_name>];
The following example shows use of a combined content, offset, and depth search rule.
alert tcp any any -> any 80 (content:"cgi-bin/phf"; offset:4; depth:20;)
The distance keyword allows the rule writer to specify how far into a packet Snort should ignore before starting to search for the specified pattern relative to the end of the previous pattern match.
This can be thought of as exactly the same thing as offset (See Section
), except it is relative to the end of the last pattern match
instead of the beginning of the packet.
This keyword allows values from -65535 to 65535.
The value can also be set to a string value referencing a variable extracted by the byte_extract keyword in the same rule.
distance:[<byte_count>|<var_name>];
The rule below maps to a regular expression of /ABC.{1,}DEF/.
alert tcp any any -> any any (content:"ABC"; content:"DEF"; distance:1;)
The within keyword is a content modifier that makes sure that at most N bytes
are between pattern matches using the content keyword ( See Section
). It's designed to be used in conjunction with the distance
(Section
) rule option.
This keyword allows values greater than or equal to pattern length being searched. The maximum allowed value for this keyword is 65535.
The value can also be set to a string value referencing a variable extracted by the byte_extract keyword in the same rule.
within:[<byte_count>|<var_name>];
This rule constrains the search of EFG to not go past 10 bytes past the ABC match.
alert tcp any any -> any any (content:"ABC"; content:"EFG"; within:10;)
The http_client_body keyword is a content modifier that restricts the search to the body of an HTTP client request.
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before 'http_client_body' is specified.
The amount of data that is inspected with this option depends on the post_depth config option of HttpInspect. Pattern matches with this keyword wont work when post_depth is set to -1.
http_client_body;
This rule constrains the search for the pattern "EFG" to the raw body of an HTTP client request.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_client_body;)
Note: The http_client_body modifier is not allowed to be used with the rawbytes modifier for the same content. |
The http_cookie keyword is a content modifier that restricts the search to the
extracted Cookie Header field (excluding the header name itself and the CRLF terminating
the header line) of a HTTP client request or a HTTP server response (per the configuration
of HttpInspect ). The Cookie buffer does not include the header
names (Cookie: for HTTP requests or Set-Cookie: for HTTP responses)
or leading spaces and the CRLF terminating the header line. These are included in the HTTP
header buffer.
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_cookie is specified. This keyword is dependent on the enable_cookie config option. The Cookie Header field will be extracted only when this option is configured. If enable_cookie is not specified, the cookie still ends up in HTTP header. When enable_cookie is not specified, using http_cookie is the same as using http_header.
The extracted Cookie Header field may be NORMALIZED, per the configuration of
HttpInspect (see ).
http_cookie;
This rule constrains the search for the pattern "EFG" to the extracted Cookie Header field of a HTTP client request.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_cookie;)
Note:
The http_cookie modifier is not allowed to be used with the rawbytes or fast_pattern modifiers for the same content.
|
The http_raw_cookie keyword is a content modifier that restricts the search to the
extracted UNNORMALIZED Cookie Header field of a HTTP client request or a HTTP server
response (per the configuration of HttpInspect ).
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_raw_cookie is specified. This keyword is dependent on the enable_cookie config option. The Cookie Header field will be extracted only when this option is configured.
http_raw_cookie;
This rule constrains the search for the pattern "EFG" to the extracted Unnormalized Cookie Header field of a HTTP client request.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_raw_cookie;)
Note:
The http_raw_cookie modifier is not allowed to be used with the rawbytes, http_cookie or fast_pattern modifiers for the same content.
|
The http_header keyword is a content modifier that restricts the search to the
extracted Header fields of a HTTP client request or a HTTP server response (per the
configuration of HttpInspect ).
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_header is specified.
The extracted Header fields may be NORMALIZED, per the configuration of
HttpInspect (see ).
http_header;
This rule constrains the search for the pattern "EFG" to the extracted Header fields of a HTTP client request or a HTTP server response.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_header;)
Note:
The http_header modifier is not allowed to be used with the rawbytes modifier for the same content.
|
The http_raw_header keyword is a content modifier that restricts the search to the
extracted UNNORMALIZED Header fields of a HTTP client request or a HTTP server
response (per the configuration of HttpInspect ).
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_raw_header is specified.
http_raw_header;
This rule constrains the search for the pattern "EFG" to the extracted Header fields of a HTTP client request or a HTTP server response.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_raw_header;)
Note:
The http_raw_header modifier is not allowed to be used with the rawbytes, http_header or fast_pattern modifiers for the same content.
|
The http_method keyword is a content modifier that restricts the search to the extracted Method from a HTTP client request.
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_method is specified.
http_method;
This rule constrains the search for the pattern "GET" to the extracted Method from a HTTP client request.
alert tcp any any -> any 80 (content:"ABC"; content:"GET"; http_method;)
Note:
The http_method modifier is not allowed to be used with the rawbytes or fast_pattern modifiers for the same content.
|
The http_uri keyword is a content modifier that restricts the search to the
NORMALIZED request URI field . Using a content rule option followed
by a http_uri modifier is the same as using a uricontent by itself (see:
).
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_uri is specified.
http_uri;
This rule constrains the search for the pattern "EFG" to the NORMALIZED URI.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_uri;)
Note:
The http_uri modifier is not allowed to be used with the rawbytes modifier for the same content.
|
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_raw_uri is specified.
http_raw_uri;
This rule constrains the search for the pattern "EFG" to the UNNORMALIZED URI.
alert tcp any any -> any 80 (content:"ABC"; content:"EFG"; http_raw_uri;)
Note:
The http_raw_uri modifier is not allowed to be used with the rawbytes, http_uri or fast_pattern modifiers for the same content.
|
The http_stat_code keyword is a content modifier that restricts the search to the extracted Status code field from a HTTP server response.
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_stat_code is specified.
The Status Code field will be extracted only if the extended_response_inspection is
configured for the HttpInspect (see ).
http_stat_code;
This rule constrains the search for the pattern "200" to the extracted Status Code field of a HTTP server response.
alert tcp any any -> any 80 (content:"ABC"; content:"200"; http_stat_code;)
Note:
The http_stat_code modifier is not allowed to be used with the rawbytes or fast_pattern modifiers for the same content.
|
The http_stat_msg keyword is a content modifier that restricts the search to the extracted Status Message field from a HTTP server response.
As this keyword is a modifier to the previous content keyword, there must be a content in the rule before http_stat_msg is specified.
The Status Message field will be extracted only if the extended_response_inspection is
configured for the HttpInspect (see ).
http_stat_msg;
This rule constrains the search for the pattern "Not Found" to the extracted Status Message field of a HTTP server response.
alert tcp any any -> any 80 (content:"ABC"; content:"Not Found"; http_stat_msg;)
Note:
The http_stat_msg modifier is not allowed to be used with the rawbytes or fast_pattern modifiers for the same content.
|
The http_encode keyword will enable alerting based on encoding type present
in a HTTP client request or a HTTP server response (per the configuration of
HttpInspect ).
There are several keywords associated with http_encode. The keywords 'uri', 'header' and 'cookie' determine the HTTP fields used to search for a particular encoding type. The keywords 'utf8', 'double_encode', 'non_ascii', 'uencode', 'iis_encode', 'ascii' and 'bare_byte' determine the encoding type which would trigger the alert. These keywords can be combined using a OR operation. Negation is allowed on these keywords.
The config option 'normalize_headers' needs to be turned on for rules to work
with the keyword 'header'. The keyword 'cookie' is dependent on config options
'enable_cookie' and 'normalize_cookies' (see ). This
rule option will not be able to detect encodings if the specified HTTP fields
are not NORMALIZED.
Option | Description |
uri | Check for the specified encoding type in HTTP client request URI field. |
header | Check for the specified encoding type in HTTP request or HTTP response header fields (depending on the packet flow) |
cookie | Check for the specified encoding type in HTTP request or HTTP response cookie header fields (depending on the packet flow) |
utf8 | Check for utf8 encoding in the specified buffer |
double_encode | Check for double encoding in the specified buffer |
non_ascii | Check for non-ASCII encoding in the specified buffer |
uencode | Check for u-encoding in the specified buffer |
bare_byte | Check for bare byte encoding in the specified buffer |
ascii | Check for ascii encoding in the specified buffer |
iis_encode | Check for IIS Unicode encoding in the specified buffer |
http_encode:<http buffer type>, [!]<encoding type> http_encode:[uri|header|cookie], [!][<utf8|double_encode|non_ascii|uencode|bare_byte|ascii|iis_encode>];
alert tcp any any -> any any (msg:"UTF8/UEncode Encoding present"; http_encode:uri,utf8|uencode;) alert tcp any any -> any any (msg:"No UTF8"; http_encode:uri,!utf8;)
Note:
Negation(!) and OR(|) operations cannot be used in conjunction with each other for the http_encode keyword. The OR and negation operations work only on the encoding type field and not on http buffer type field.
|
The fast_pattern keyword is a content modifier that sets the content within a rule to be used with the fast pattern matcher. The default behavior of fast pattern determination is to use the longest HTTP buffer content. If no HTTP buffer is present, then the fast pattern is the longest content. Given this behavior, it is useful if a shorter content is more "unique" than the longer content, meaning the shorter content is less likely to be found in a packet than the longer content.
The fast pattern matcher is used to select only those rules that have a chance of matching by using a content in the rule for selection and only evaluating that rule if the content is found in the payload. Though this may seem to be overhead, it can significantly reduce the number of rules that need to be evaluated and thus increases performance. The better the content used for the fast pattern matcher, the less likely the rule will needlessly be evaluated.
As this keyword is a modifier to the previous content keyword, there must be a content rule option in the rule before fast_pattern is specified. The fast_pattern option may be specified only once per rule.
Note: The fast_pattern modifier cannot be used with the following http content modifiers: http_cookie, http_raw_uri, http_raw_header, http_raw_cookie, http_method, http_stat_code, http_stat_msg. |
Note: The fast_pattern modifier can be used with negated contents only if those contents are not modified with offset, depth, distance or within. |
Note: The fast pattern matcher is always case insensitive. |
fast_pattern;
The optional argument only can be used to specify that the content should only be used for the fast pattern matcher and should not be evaluated as a rule option. This is useful, for example, if a known content must be located in the payload independent of location in the payload, as it saves the time necessary to evaluate the rule option. Note that (1) the modified content must be case insensitive since patterns are inserted into the pattern matcher in a case insensitive manner, (2) negated contents cannot be used and (3) contents cannot have any positional modifiers such as offset, depth, distance or within.
fast_pattern:only;
The optional argument <offset>,<length> can be used to specify that only a portion of the content should be used for the fast pattern matcher. This is useful if the pattern is very long and only a portion of the pattern is necessary to satisfy "uniqueness" thus reducing the memory required to store the entire pattern in the fast pattern matcher.
fast_pattern:<offset>,<length>;
Note: The optional arguments only and <offset>,<length> are mutually exclusive. |
This rule causes the pattern "IJKLMNO" to be used with the fast pattern matcher, even though it is shorter than the earlier pattern "ABCDEFGH".
alert tcp any any -> any 80 (content:"ABCDEFGH"; content:"IJKLMNO"; fast_pattern;)
This rule says to use the content "IJKLMNO" for the fast pattern matcher and that the content should only be used for the fast pattern matcher and not evaluated as a content rule option.
alert tcp any any -> any 80 (content:"ABCDEFGH"; content:"IJKLMNO"; nocase; fast_pattern:only;)
This rule says to use "JKLMN" as the fast pattern content, but still evaluate the content rule option as "IJKLMNO".
alert tcp any any -> any 80 (content:"ABCDEFGH"; content:"IJKLMNO"; fast_pattern:1,5;)
The uricontent keyword in the Snort rule language searches the NORMALIZED request URI field. This is equivalent to using the http_uri modifier to a content keyword. As such if you are writing rules that include things that are normalized, such as %2f or directory traversals, these rules will not alert. The reason is that the things you are looking for are normalized out of the URI buffer.
For example, the URI:
/scripts/..%c0%af../winnt/system32/cmd.exe?/c+ver
will get normalized into:
/winnt/system32/cmd.exe?/c+ver
Another example, the URI:
/cgi-bin/aaaaaaaaaaaaaaaaaaaaaaaaaa/..%252fp%68f?
will get normalized into:
/cgi-bin/phf?
When writing a uricontent rule, write the content that you want to find in the context that the URI will be normalized. For example, if Snort normalizes directory traversals, do not include directory traversals.
You can write rules that look for the non-normalized content by using the
content option. (See Section )
uricontent can be used with several of the modifiers available to the content keyword. These include:
This option works in conjunction with the HTTP Inspect preprocessor specified
in Section .
uricontent:[!]"<content string>";
Note:
uricontent cannot be modified by a rawbytes modifier or any of the other HTTP modifiers. If you wish to search the UNNORMALIZED request URI field, use the http_raw_uri modifier with a content option.
|
The urilen keyword in the Snort rule language specifies the exact length, the minimum length, the maximum length, or range of URI lengths to match. By default the raw uri buffer will be used. With the optional <uribuf> argument, you can specify whether the raw or normalized buffer are used.
urilen:min<>max[,<uribuf>]; urilen:[<|>]<number>[,<uribuf>]; <uribuf> : "norm" | "raw"
The following example will match URIs that are 5 bytes long:
urilen:5;
The following example will match URIs that are shorter than 5 bytes:
urilen:<5;
The following example will match URIs that are greater than 5 bytes and less than 10 bytes (inclusive):
urilen:5<>10;
The following example will match URIs that are greater than 500 bytes using the normalized URI buffer:
urilen:>500,norm;
The following example will match URIs that are greater than 500 bytes explicitly stating to use the raw URI buffer:
urilen:>500,raw;
This option works in conjunction with the HTTP Inspect preprocessor specified
in Section .
Verify that the payload has data at a specified location, optionally looking for data relative to the end of the previous content match.
isdataat:[!]<int>[, relative|rawbytes];
alert tcp any any -> any 111 (content:"PASS"; isdataat:50,relative; \ content:!"|0a|"; within:50;)
This rule looks for the string PASS exists in the packet, then verifies there is at least 50 bytes after the end of the string PASS, then verifies that there is not a newline character within 50 bytes of the end of the PASS string.
When the rawbytes modifier is specified with isdataat, it looks at the raw packet data, ignoring any decoding that was done by the preprocessors. This modifier will work with the relative modifier as long as the previous content match was in the raw packet data.
A ! modifier negates the results of the isdataat test. It will alert if a certain amount of data is not present within the payload. For example, the rule with modifiers content:"foo"; isdataat:!10,relative; would alert if there were not 10 bytes after "foo" before the payload ended.
The pcre keyword allows rules to be written using perl compatible regular expressions. For more detail on what can be done via a pcre regular expression, check out the PCRE web site http://www.pcre.org
pcre:[!]"(/<regex>/|m<delim><regex><delim>)[ismxAEGRUBPHMCOIDKYS]";
The post-re modifiers set compile time flags for the regular expression. See
tables ,
, and
for
descriptions of each modifier.
i | case insensitive |
s | include newlines in the dot metacharacter |
m | By default, the string is treated as one big line of characters. ^ and $ match at the beginning and ending of the string. When m is set, ^ and $ match immediately following or immediately before any newline in the buffer, as well as the very start and very end of the buffer. |
x | whitespace data characters in the pattern are ignored except when escaped or inside a character class |
A | the pattern must match only at the start of the buffer (same as ^ ) |
E | Set $ to match only at the end of the subject string. Without E, $ also matches immediately before the final character if it is a newline (but not before any other newlines). |
G | Inverts the "greediness" of the quantifiers so that they are not greedy by default, but become greedy if followed by "?". |
Note: The modifiers R (relative) and B (rawbytes) are not allowed with any of the HTTP modifiers such as U, I, P, H, D, M, C, K, S and Y. |
This example performs a case-insensitive search for the HTTP URI foo.php?id=<some numbers>
alert tcp any any -> any 80 (content:"/foo.php?id="; pcre:"/\/foo.php?id=[0-9]{1,10}/iU";)
Note: It is wise to have at least one content keyword in a rule that uses pcre. This allows the fast-pattern matcher to filter out non-matching packets so that the pcre evaluation is not performed on each and every packet coming across the wire. |
Note:
Snort's handling of multiple URIs with PCRE does not work as expected. PCRE when used without a uricontent only evaluates the first URI. In order to use pcre to inspect all URIs, you must use either a content or a uricontent.
|
Any relative or absolute content matches (without HTTP modifiers or rawbytes) and other payload detecting rule options that follow pkt_data in a rule will apply to the raw TCP/UDP payload or the normalized buffers (in case of telnet, smtp normalization) until the cursor (used for detection) is set again.
This rule option can be used several times in a rule.
pkt_data;
alert tcp any any -> any any(msg:"Absolute Match"; pkt_data; content:"BLAH"; offset:0; depth:10;) alert tcp any any -> any any(msg:"PKT DATA"; pkt_data; content:"foo"; within:10;) alert tcp any any -> any any(msg:"PKT DATA"; pkt_data; content:"foo";) alert tcp any any -> any any(msg:"PKT DATA"; pkt_data; pcre:"/foo/i";)
Any relative or absolute content matches (without HTTP modifiers or rawbytes) and payload detecting rule options that follow file_data in a rule will apply to this buffer until explicitly reset by other rule options.
This rule option can be used several time in a rule.
The argument mime to file_data is deprecated. The rule options file_data will itself point to the decoded MIME attachment.
file_data;
alert tcp any any -> any any(msg:"Absolute Match"; file_data; content:"BLAH"; offset:0; depth:10;) alert tcp any any -> any any(msg:"FILE DATA"; file_data; content:"foo"; within:10;) alert tcp any any -> any any(msg:"FILE DATA"; file_data; content:"foo";) alert tcp any any -> any any(msg:"FILE DATA"; file_data; pcre:"/foo/i";) The following rule searches for content "foo" within the file_data buffer and content "bar" within the entire packet payload. The rule option pkt_data will reset the cursor used for detection to the TCP payload. alert tcp any any -> any any(msg:"FILE DATA"; file_data; content:"foo"; pkt_data; content:"bar";)
This option is used to decode the base64 encoded data. This option is particularly useful in case of HTTP headers such as HTTP authorization headers. This option unfolds the data before decoding it.
base64_decode[:[bytes <bytes_to_decode>][, ][offset <offset>[, relative]]];
Option | Description |
bytes | Number of base64 encoded bytes to decode. This argument takes positive and non-zero values only. When this option is not specified we look for base64 encoded data till either the end of header line is reached or end of packet payload is reached. |
offset | Determines the offset relative to the doe_ptr when the option relative is specified or relative to the start of the packet payload to begin inspection of base64 encoded data. This argument takes positive and non-zero values only. |
relative | Specifies the inspection for base64 encoded data is relative to the doe_ptr. |
The above arguments to base64_decode are optional.
Note:
This option can be extended to protocols with folding similar to HTTP. If folding is not present the search for base64 encoded data will end when we see a carriage return or line feed or both without a following space or tab. This option needs to be used in conjunction with base64_data for any other payload detecting rule options to work on base64 decoded buffer. |
alert tcp $EXTERNAL_NET any -> $HOME_NET any \ (msg:"Base64 Encoded Data"; base64_decode; base64_data; \ content:"foo bar"; within:20;) alert tcp $EXTERNAL_NET any -> $HOME_NET any \ (msg:"Authorization NTLM"; content:"Authorization: NTLM"; base64_decode:relative; base64_data; content:"NTLMSSP"; ) alert tcp any any -> any any (msg:"Authorization NTLM"; \ content:"Authorization:"; http_header; \ base64_decode:bytes 12, offset 6, relative; base64_data; \ content:"NTLMSSP"; within:8;)
This option does not take any arguments. The rule option base64_decode needs to be specified before the base64_data option.
base64_data;
This option matches if there is base64 decoded buffer.
Note:
Fast pattern content matches are not allowed with this buffer. |
alert tcp any any -> any any (msg:"Authorization NTLM"; \ content:"Authorization:"; http_header; \ base64_decode:bytes 12, offset 6, relative; base64_data; \ content:"NTLMSSP"; within:8;)
Test a byte field against a specific value (with operator). Capable of testing binary values or converting representative byte strings to their binary equivalent and testing them.
For a more detailed explanation, please read Section .
byte_test:<bytes to convert>, [!]<operator>, <value>, <offset> \ [, relative][, <endian>][, string, <number type>][, dce] \ [, bitmask <bitmask_value>]; bytes = 1 - 10 operator = '<' | '=' | '>' | '<=' | '>=' | '&' | '^' value = 0 - 4294967295 offset = -65535 to 65535 bitmask_value = 1 to 4 byte hexadecimal value
Any of the operators can also include ! to check if the operator is not true. If ! is specified without an operator, then the operator is set to =.
Note:
Snort uses the C operators for each of these operators. If the & operator is used, then it would be the same as using if (data & value) { do_something();}
|
alert udp $EXTERNAL_NET any -> $HOME_NET any \ (msg:"AMD procedure 7 plog overflow"; \ content:"|00 04 93 F3|"; \ content:"|00 00 00 07|"; distance:4; within:4; \ byte_test:4, >, 1000, 20, relative;) alert tcp $EXTERNAL_NET any -> $HOME_NET any \ (msg:"AMD procedure 7 plog overflow"; \ content:"|00 04 93 F3|"; \ content:"|00 00 00 07|"; distance:4; within:4; \ byte_test:4, >, 1000, 20, relative;) alert udp any any -> any 1234 \ (byte_test:4, =, 1234, 0, string, dec; \ msg:"got 1234!";) alert udp any any -> any 1235 \ (byte_test:3, =, 123, 0, string, dec; \ msg:"got 123!";) alert udp any any -> any 1236 \ (byte_test:2, =, 12, 0, string, dec; \ msg:"got 12!";) alert udp any any -> any 1237 \ (byte_test:10, =, 1234567890, 0, string, dec; \ msg:"got 1234567890!";) alert udp any any -> any 1238 \ (byte_test:8, =, 0xdeadbeef, 0, string, hex; \ msg:"got DEADBEEF!";) alert tcp any any -> any any \ (byte_test:2, =, 568, 0, bitmask 0x3FF0; \ msg:"got 568 after applying bitmask 0x3FF0 on 2 bytes extracted";)
The byte_jump keyword allows rules to be written for length encoded protocols trivially. By having an option that reads the length of a portion of data, then skips that far forward in the packet, rules can be written that skip over specific portions of length-encoded protocols and perform detection in very specific locations.
The byte_jump option does this by reading some number of bytes, convert them to their numeric representation, move that many bytes forward and set a pointer for later detection. This pointer is known as the detect offset end pointer, or doe_ptr.
For a more detailed explanation, please read Section .
byte_jump:<bytes_to_convert>, <offset> [, relative][, multiplier <mult_value>] \ [, <endian>][, string, <number_type>][, align][, from_beginning][, from_end] \ [, post_offset <adjustment value>][, dce][, bitmask <bitmask_value>]; bytes = 1 - 10 offset = -65535 to 65535 mult_value = 0 - 65535 post_offset = -65535 to 65535 bitmask_value = 1 to 4 bytes hexadecimal value
alert udp any any -> any 32770:34000 (content:"|00 01 86 B8|"; \ content:"|00 00 00 01|"; distance:4; within:4; \ byte_jump:4, 12, relative, align; \ byte_test:4, >, 900, 20, relative; \ msg:"statd format string buffer overflow";) alert tcp any any -> any any (content:"Begin"; \ byte_jump:0, 0, from_end, post_offset -6; \ content:"end.."; distance:0; within:5; \ msg:"Content match from end of the payload";) alert tcp any any -> any any (content:"catalog"; \ byte_jump:2, 1, relative, post_offset 2, bitmask 0x03f0; \ byte_test:2, =, 968, 0, relative; \ msg:"Bitmask applied on the 2 bytes extracted for byte_jump";) alert tcp any any -> any any (content:"catalog"; \ byte_jump:1, 2, from_end, post_offset -5, bitmask 0x3c; \ byte_test:1, =, 106, 0, relative; \ msg:"Byte jump calculated from end of payload after bitmask applied";)
The byte_extract keyword is another useful option for writing rules against length-encoded protocols. It reads in some number of bytes from the packet payload and saves it to a variable. These variables can be referenced later in the rule, instead of using hard-coded values.
Note:
Only two byte_extract variables may be created per rule. They can be re-used in the same rule any number of times.
|
byte_extract:<bytes_to_extract>, <offset>, <name> [, relative] \ [, multiplier <multiplier value>][, <endian>][, string][, hex][, dec][, oct] \ [, align <align value>][, dce][, bitmask <bitmask>]; bytes_to_extract = 1 - 10 operator = '<' | '=' | '>' | '<=' | '>=' | '&' | '^' value = 0 - 4294967295 offset = -65535 to 65535 bitmask_value = 1 to 4 byte hexadecimal value
Option | Description |
bytes_to_extract | Number of bytes to pick up from the packet |
offset | Number of bytes into the payload to start processing |
name | Name of the variable. This will be used to reference the variable in other rule options. |
relative | Use an offset relative to last pattern match |
multiplier 2#2value3#3 | Multiply the bytes read from the packet by 2#2value3#3 and save that number into the variable. |
big | Process data as big endian (default) |
little | Process data as little endian |
dce | Use the DCE/RPC 2 preprocessor to determine the byte-ordering. The DCE/RPC 2 preprocessor must be enabled for this option to work. |
string | Data is stored in string format in packet |
hex | Converted string data is represented in hexadecimal |
dec | Converted string data is represented in decimal |
oct | Converted string data is represented in octal |
align 2#2value3#3 | Round the number of converted bytes up to the next 2#2value3#3-byte boundary. 2#2value3#3 may be 2 or 4. |
bitmask | Applies the AND operator on the value of bytes_to_extract argument. The result will be right-shifted by the number of bits equal to the number of trailing zeros in the mask. |
A byte_extract rule option detects nothing by itself. Its use is in extracting packet data for use in other rule options. Here is a list of places where byte_extract variables can be used:
Rule Option | Arguments that Take Variables |
content/uricontent | offset, depth, distance, within |
byte_test | offset, value |
byte_jump | offset |
isdataat | offset |
This example uses two variables to:
alert tcp any any -> any any (byte_extract:1, 0, str_offset; \ byte_extract:1, 1, str_depth; \ content:"bad stuff"; offset:str_offset; depth:str_depth; \ msg:"Bad Stuff detected within field";) alert tcp any any -> any any (content:"|04 63 34 35|"; offset:4; depth:4; \ byte_extract: 2, 0, var_match, relative, bitmask 0x03ff; \ byte_test: 2, =, var_match, 2, relative; \ msg:"Byte test value matches bitmask applied on bytes extracted";)
Perform a mathematical operation on an extracted value and a specified value or existing variable, and store the outcome in a new resulting variable. These resulting variables can be referenced later in the rule, instead of using hard-coded values.
byte_math:bytes <bytes_to_extract>, offset <offset_value>, oper <operator>, rvalue <r_value>, result <result_variable> [, relative] [, endian <endian>] [, string <number type>][, dce] [, bitmask <bitmask_value>]; bytes_to_extract = 1 - 10 operator = '+' | '-' | '*' | '/' | '<<' | '>>' r_value = 0 - 4294967295 | byte extract variable offset_value = -65535 to 65535 bitmask_value = 1 to 4 byte hexadecimal value result_variable = Result Variable name
Rule Option | Arguments that take result variable |
content | offset, depth, distance, within |
byte_test | offset, value |
byte_jump | offset |
isdataat | offset |
alert udp $EXTERNAL_NET any -> $HOME_NET any \ (msg:"Perform Arithmetic Operation on the extracted bytes"; \ content:"|00 04 93 F3|"; \ content:"|00 00 00 07|"; distance:4; within:4; \ byte_math:bytes 4, offset 0, oper +, rvalue 248, result var, relative; \ byte_test:4, >, var, 2, relative;) alert tcp $EXTERNAL_NET any -> $HOME_NET any \ (msg:"Bitwise shift operator"; \ content:"|00 00 00 07|"; distance:4; within:4; \ byte_extract: 1, 0, extracted_val, relative; \ byte_math: bytes 1, offset 2, oper >>, rvalue extracted_val, result var, relative; \ byte_test:2, =, var, 0, relative;) alert udp any any -> any 1234 \ (content: "Packets start"; \ byte_math: bytes 2, offset 0, oper -, rvalue 100, result var, relative, bitmask 0x7FF0; \ content: "Packets end"; distance: 2; within var; \ msg:"Content match with bitmask applied to the bytes extracted";) alert udp any any -> any 1235 \ (byte_extract: 4, 3, extracted_val, relative; \ byte_math: bytes 5, offset 0, oper +, rvalue extracted_val, result var, string hex; \ byte_test:5, =, var, 4, string, hex; \ msg:"String operator used with math rule option";)
The ftpbounce keyword detects FTP bounce attacks.
ftpbounce;
alert tcp $EXTERNAL_NET any -> $HOME_NET 21 (msg:"FTP PORT bounce attempt"; \ flow:to_server,established; content:"PORT"; nocase; ftpbounce; pcre:"/^PORT/smi";\ classtype:misc-attack; sid:3441; rev:1;)
The ASN.1 detection plugin decodes a packet or a portion of a packet, and looks for various malicious encodings.
Multiple options can be used in an 'asn1' option and the implied logic is boolean OR. So if any of the arguments evaluate as true, the whole option evaluates as true.
The ASN.1 options provide programmatic detection capabilities as well as some more dynamic type detection. If an option has an argument, the option and the argument are separated by a space or a comma. The preferred usage is to use a space between option and argument.
asn1:[bitstring_overflow][, double_overflow][, oversize_length <value>][, absolute_offset <value>|relative_offset <value>];
Option | Description |
bitstring_overflow | Detects invalid bitstring encodings that are known to be remotely exploitable. |
double_overflow | Detects a double ASCII encoding that is larger than a standard buffer. This is known to be an exploitable function in Microsoft, but it is unknown at this time which services may be exploitable. |
oversize_length 2#2value3#3 | Compares ASN.1 type lengths with the supplied argument. The syntax looks like, ``oversize_length 500''. This means that if an ASN.1 type is greater than 500, then this keyword is evaluated as true. This keyword must have one argument which specifies the length to compare against. |
absolute_offset 2#2value3#3 | This is the absolute offset from the beginning of the packet. For example, if you wanted to decode snmp packets, you would say ``absolute_offset 0''. absolute_offset has one argument, the offset value. Offset may be positive or negative. |
relative_offset 2#2value3#3 |
This is the relative offset from the last content match, pcre or byte_jump.
relative_offset has one argument, the offset number. So if you
wanted to start decoding an ASN.1 sequence right after the content ``foo'',
you would specify |
alert udp any any -> any 161 (msg:"Oversize SNMP Length"; \ asn1:oversize_length 10000, absolute_offset 0;) alert tcp any any -> any 80 (msg:"ASN1 Relative Foo"; content:"foo"; \ asn1:bitstring_overflow, relative_offset 0;)
The CVS detection plugin aids in the detection of: Bugtraq-10384, CVE-2004-0396: "Malformed Entry Modified and Unchanged flag insertion". Default CVS server ports are 2401 and 514 and are included in the default ports for stream reassembly.
Note:
This plugin cannot do detection over encrypted sessions, e.g. SSH (usually port 22).
|
cvs:<option>;
Option | Description |
invalid-entry | Looks for an invalid Entry string, which is a way of causing a heap overflow (see CVE-2004-0396) and bad pointer dereference in versions of CVS 1.11.15 and before. |
alert tcp any any -> any 2401 (msg:"CVS Invalid-entry"; \ flow:to_server,established; cvs:invalid-entry;)
See the DCE/RPC 2 Preprocessor section for a description and
examples of using this rule option.
See the DCE/RPC 2 Preprocessor section for a description and
examples of using this rule option.
See the DCE/RPC 2 Preprocessor section for a description and
examples of using this rule option.
See the SIP Preprocessor section for a description and
examples of using this rule option.
See the SIP Preprocessor section for a description and
examples of using this rule option.
See the SIP Preprocessor section for a description and
examples of using this rule option.
See the SIP Preprocessor section for a description and
examples of using this rule option.
See the GTP Preprocessor section for a description and
examples of using this rule option.
See the GTP Preprocessor section for a description and
examples of using this rule option.
See the GTP Preprocessor section for a description and
examples of using this rule option.
See the SSL/TLS Preprocessor section for a description and examples of
using this rule option.
See the SSL/TLS Preprocessor section for a description and examples of
using this rule option.
Keyword | Description |
content | The content keyword allows the user to set rules that search for specific content in the packet payload and trigger response based on that data. |
rawbytes | The rawbytes keyword allows rules to look at the raw packet data, ignoring any decoding that was done by preprocessors. |
depth | The depth keyword allows the rule writer to specify how far into a packet Snort should search for the specified pattern. |
offset | The offset keyword allows the rule writer to specify where to start searching for a pattern within a packet. |
distance | The distance keyword allows the rule writer to specify how far into a packet Snort should ignore before starting to search for the specified pattern relative to the end of the previous pattern match. |
within | The within keyword is a content modifier that makes sure that at most N bytes are between pattern matches using the content keyword. |
uricontent | The uricontent keyword in the Snort rule language searches the normalized request URI field. |
isdataat | The isdataat keyword verifies that the payload has data at a specified location. |
pcre | The pcre keyword allows rules to be written using perl compatible regular expressions. |
byte_test | The byte_test keyword tests a byte field against a specific value (with operator). |
byte_jump | The byte_jump keyword allows rules to read the length of a portion of data, then skip that far forward in the packet. |
ftpbounce | The ftpbounce keyword detects FTP bounce attacks. |
asn1 | The asn1 detection plugin decodes a packet or a portion of a packet, and looks for various malicious encodings. |
cvs | The cvs keyword detects invalid entry strings. |
dce_iface | |
dce_opnum | |
dce_stub_data | |
sip_method | |
sip_stat_code | |
sip_header | |
sip_body | |
gtp_type | |
gtp_info | |
gtp_version |