1 A Simple Rule
alert tcp 202.110.8.1 any -> 122.111.90.8 80 (msg:”Web Access”; sid:1)
- alert: indicates an alert will be triggered if this rule is matched
- tcp: protocol type
- IP address: source/destination IP address
- any/80: port number
- -> : directional operator, there is also a bidirectional operator <>
- msg: message printed in alerts and log entries
- sid: Snort rule id
This rule is straightforward. Snort uses rules to analyze packets in real time and log network traffic, functioning as a Network Intrusion Detection/Prevention System (NIDS/NIPS).
2 Snort Directory Structure
It’s recommended to configure Snort’s directory structure as follows:
/etc/snort
├── barnyard2.conf #barnyard2 log analysis tool configuration file
├── snort.conf #snort configuration file (key file)
├── threshold.conf #event filtering configuration file
├── classification.config #rule classification configuration file (classtype)
├── reference.config #external reference configuration file (reference)
├── gen-msg.map #generate id and message mapping file
├── sid-msg.map #snort id and message mapping file
├── unicode.map #preprocessor http_inspect encoding translation file
├── preproc_rules #preprocessor and decoder rule sets
│ ├── decoder.rules
│ ├── preprocessor.rules
│ └── sensitive-data.rules
├── rules #Snort rule sets (key files)
│ ├── web-iis.rules
│ ├── web-php.rules
More…
├── so_rules #Share Object rule sets
│ ├── browser-ie.rules
│ ├── browser-other.rules
More…
3 Configuration File – snort.conf
This file is the core file for Snort configuration, including the following parts:
1) Set the network variables. #Define network addresses for easier rule usage
2) Configure the decoder #Configure the decoder
3) Configure the base detection engine #Configure the base detection engine
4) Configure dynamic loaded libraries #Configure dynamic load libraries
5) Configure preprocessors #Configure preprocessors
6) Configure output plugins #Configure output plugins
7) Customize your rule set #Customize your rule set
8) Customize preprocessor and decoder rule set #Customize preprocessor and decoder rule set
9) Customize shared object rule set #Customize shared object rule set
4 Snort Architecture
Packet Sniffing and Decoding Module: Responsible for packet capturing and decoding based on TCP/IP protocols.
Preprocessor Module: 1. Packet reassembly preprocessor prevents fragmented attack info from bypassing Snort detection; 2. Protocol normalization preprocessor decodes protocols into a standard format for detection; 3. Protocol anomaly detection preprocessor.
Detection Engine Module: Matches packets against rules in three-dimensional linked lists and triggers alerts based on matches.
Alert/Logging Module: Transmits packets to the alert module for processing (database, log) as per rules.
5 Decoder and Preprocessor Modules
5.1 Module Overview
Both modules process packets before they reach the detection engine, hence they are discussed together.
The decoder module decodes raw network data packets by network protocol stack and saves the data in structures for the preprocessor to handle.
Post-decoding, packets undergo preprocessing for the detection engine to match rules. Preprocessors address IDS evading techniques:
- Inspect or modify suspicious packets to ensure proper interpretation by the detection engine.
- Traffic normalization for accurate signature matching by the detection engine.
Known IDS evasion techniques include:
- Polymorphic URL encoding
- Polymorphic shellcode
- Session splitting
- IP fragmentation
Snort includes three main types of preprocessors:
Packet Reassembly Preprocessors: frag3 (IP fragmentation reassembly and attack detection), stream (TCP stream state maintenance and session reassembly)
Protocol Normalization Preprocessors: http_inspect (HTTP traffic normalization), rpcDecode (RPC call normalization)
Anomaly Detection Preprocessors: ARP spoof detection, sfPortscan (port scan detection)
5.2 Module Configuration
Configuration requires two steps, both in snort.conf.
- Configure decoder or preprocessor parameters in snort.conf.
- Enable detection rules in snort.conf.
5.2.1 Decoder Configuration Example
Configure the decoder
config disable_decode_alerts #Disable decode alerts
config enable_decode_oversized_alerts
# Trigger alert if packet's length exceeds protocol length fields
# Stop generic decode eventsFormat:
config decoder [option]
, use # for commentsEnable decoder detection rules
include $PREPROC_RULE_PATH/decoder.rules
Use include keyword in snort.conf to incorporate configuration and rule files.
Decoder rule example – detect abnormal IP length in decoder.rules:
alert ( msg:"DECODE_IPV4_DGRAM_GT_IPHDR"; sid:6; gid:116; rev:1; metadata:rule-type decode; classtype:protocol-command-decode;)
5.2.2 Preprocessor http_insepect Configuration Example
Default configuration for http_inspect:
preprocessor http_inspect: global iis_unicode_map unicode.map 1252 compress_depth 65535 decompress_depth 65535
#unicode.map decodes unicode in http_inspect preprocessor
preprocessor http_inspect_server: server default \
http_methods { GET POST PUT SEARCH MKCOL ...} \
...
enable_cookie #Extract cookies from HTTP requests/responses for rule matching
normalize javascript #Decode javascript in tags...Enable preprocessor rules
#include $PREPROC_RULE_PATH/preprocessor.rules
Example of a decoder rule:
alert ( msg:"DECODE_TCP_INVALID_OFFSET"; sid:46; gid:116; rev:1; metadata:rule-type decode; reference:cve,2004-0816; classtype:bad-unknown;)
The rule identified here is different from the previous one that was observed; it lacks information such as source/destination IP and port details, indicating that this rule is automatically triggered by the decoder without user intervention. Generally, we don’t need to modify the rules of decoders or preprocessors; we only need to add, configure, or delete plugins in the snort.conf file.
6 Detection Engine Module
Rule Structure:
alert tcp 202.110.8.1 any -> 122.111.90.8 80 (msg:”Web Access”; sid:1)
6.1 Rule Header
Action: In Snort, there are five types of actions: alert, log, pass, activate and dynamic.
- alert: Generates an alert and then logs the packet.
- log: Logs the packet.
- pass: Drops the packet.
- activate: Generates an alert and activates another dynamic rule.
- dynamic: Remains idle until activated by an activate rule, then acts as a log rule.
Protocol: Snort currently supports analysis of four protocols: TCP, UDP, ICMP, and IP. More protocols might be supported in the future, such as ARP, IGRP, GRE, OSPF, RIP, IPX, etc.
IP Address:
-
- An address consists of either a direct IP address or a CIDR block. IP address lists can also be specified, which are composed of multiple IP addresses and CIDR blocks separated by commas and enclosed in square brackets [].
- The negation operator is represented by !.
- The keyword “any” can be used to define any address.
For example:
alert tcp ![192.168.1.0/24,10.1.1.0/16] any -> 192.168.2.1 80 (msg:”notice!”; content|xxxx|;)
Direction Operator: The direction operator -> indicates the direction of the flow to which the rule applies. The IP address and port number to the left of the direction operator are considered the source, while those to the right are the destination. There is also a bidirectional operator <>.
Port Number:
- Port numbers can be represented in several ways, including any port, static port definitions, ranges, and using the negation operator.
- Static port definitions represent a single port number, such as 111 for portmapper, 23 for telnet, 80 for HTTP, etc.
- Port ranges are represented using the range operator “:”. For example,
80:, :1024, 80:1024
.
6.2 Rule Options
Rule options are categorized into four types:
- General rule options
- Payload detection rule options
- Non-payload detection rule options
- Post-detection rule options
6.2.1 General Rule Options
sid: Snort ID. This keyword is used to uniquely identify a Snort rule. The range of sids is allocated as follows:
<100 # Reserved for future use
100-1,000,000 # Included in Snort distribution
>1,000,000 # Used for local rulesmsg: Indicates a message. However, the msg in the rule itself is not functional; the relationship between the sid and msg is looked up in sid-msg.map.
sid-msg.map: Format: sid || msg
Example: 384 || PROTOCOL-ICMP PING
In /etc/snort/rules/protocol-icmp.rules, we find the rule:
alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"PROTOCOL-ICMP PING"; icode:0; itype:8; metadata:ruleset community; classtype:misc-activity; sid:384; rev:8;)
This file maps sid to msg. Without this file, an alert would not have a corresponding message.
This file allows customization of alert messages in conjunction with custom rules. Snort alerts follow the format Snort Alert[gid: sid: rev]. This indicates that a rule requires these three components to be uniquely identified; relying solely on sid is not sufficient.
gid: Generate ID. This indicates the part of Snort that triggers the rule, such as the decoder, preprocessor, or Snort’s own rules.
You can view the /usr/local/share/doc/snort/generators file (which is not a configuration file):
rules_subsystem 1 # Snort Rules Engine
rpc_decode 106 # RPC Preprocessor
stream4 111 # Stream4 Preprocessor
ftp 125 # FTP DecoderGids for decoder and preprocessor are not listed here in full, but we can see that Snort Rule Engine has a gid of 1 by default, indicating both custom rules and Snort’s own rules in /etc/snort/rules. Decoders and preprocessors also have sids. Here is an example:
In /etc/snort/rules/protocol-icmp.rules, a rule:
alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"PROTOCOL-ICMP Traceroute"; icode:0; itype:30; metadata:ruleset community; classtype:misc-activity; sid:456; rev:8;)
Default gid is 1
In /etc/snort/preproc_rules/decoder.rules, another rule:
alert (msg:"DECODE_IP6_EXCESS_EXT_HDR"; sid:456; gid:116; rev:1; metadata:rule-type decode; classtype:misc-activity;)
Sid 456 exists in both rules, so gid is required for differentiation.
gen-msg.map: Similar to sid-msg.map, logically it includes sid-msg.map (sid-msg.map is equivalent to gid of 1 by default).
Format: generatorid || alertid (sid) || MSG
Example:
1 || 1 || snort general alert
129 || 2 || stream5: Data on SYN packet
116 || 271 || snort_decoder: WARNING: IPv6 header claims to not be IPv6
116 || 456 || snort_decoder: WARNING: too many IPV6 extension headersUsing the second rule from the gid section as an example, if it is triggered, it would alert “snort_decoder: WARNING: too many IPV6 extension headers” instead of “DECODE_IP6_EXCESS_EXT_HDR”. Hence, msg in the rule only indicates, while actual alert messages are mapped using sid-msg.map and gen-msg.map.
rev: This keyword identifies the version of a modified rule. It must be used with sid and gid to uniquely identify a rule. Thus, the unique elements sid, gid, and rev are fully explained.
reference: External attack reference. This keyword allows a rule to include an external attack identification system. This plugin currently supports several specific systems, used by output plugins to provide additional information about the generated alert.
reference.config: Format: config reference: system URL
Example:
config reference: cve http://cve.mitre.org/cgi-bin/cvename.cgi?name=
defines some security websites’ URLs. If the rule defines reference: cve,1001, it adds 1001 to the end of the URL to form http://cve.mitre.org/cgi-bin/cvename.cgi?name=1001, and clicking the reference in the alert would navigate to the specific website.Note: reference needs to be mapped to sid in sid-msg.map to be functional, similar to msg.
classtype: Classification type for rules. This keyword categorizes alerts into different attack types. Using this keyword and priority, users can assign priorities to each rule class.
priority: Sets the priority of the classtype. classtype and priority are used together, connected via the classification.config file.
classification.config: Format:
config classification: shortname, short description, priority
Example:
config classification: attempted-admin, Attempted Administrator Privilege Gain, 1
This file lists default values; the priority keyword can be used in rules to override priority.
Example:
alert tcp any any -> any 80 (msg:"EXPLOIT ntpdx overflow"; dsize:>128; classtype:attempted-admin; priority:10);
metadata
Custom information can be added to the rules, usually in the form of key-value pairs. The general rule option only labels and categorizes a rule, without actual filtering and detection.
6.2.2 Payload Detection Rule Options
-
-
content content is one of Snort’s important keywords. It specifies the pattern to search for in the payload of the packet. Its option data can contain a mix of text and binary data. Binary data is usually enclosed in pipe symbols “|”, represented in bytecode, which is the hexadecimal form of the binary data.
For example:
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”;)content has many modifiers:
nocase Case-insensitive string match
rawbytes Match raw packet data
depth Match depth
offset Starting offset for match
distance Distance between content matches
within Maximum distance between content matches
http_cookie Match cookies
http_raw_cookie Match raw (non-normalized) cookies
http_header Match headers
http_raw_header Match raw (non-normalized) headers
http_method Match HTTP methods
http_url Match URLs
http_raw_url Match raw (non-normalized) URLs
http_stat_code Match HTTP status codes
http_stat_msg Match HTTP status messages
http_encode Match encoding formatsThe http-prefixed modifiers need to be used in conjunction with the http_inspect preprocessor introduced earlier.
pcre Allows users to use regular expressions compatible with the PERL language.
Format:
pcre:[!]"(//|m)[ismxAEGRUBPHMCOIDKY]
Example:
alert tcp any any -> any 80 (content:“/foo.php?id="; pcre:"/\/foo.php?id=[0-9]{1,10}/iU";)
For details on regular expressions, consult the snort_manual.
protected_content Uses hash algorithms to encrypt the content in queries, protecting the rule’s privacy.
Format:
protected_content:[!]"", length:orig_len[, hash:md5|sha256|sha512];
rawbytes Ignores the decoder and preprocessors’ operations, directly matching raw network packets.
-
The above are just some commonly used payload detection rule options. For more keywords, consult the snort_manual.
6.2.3 Non-Payload Detection Rule Options
fragoffset IP fragment offset
ttl IP Time-to-Live
tos IP Type of Service
id IP identification
ipopst IP options
fragbits IP fragment flags
dsize Packet payload size
flags TCP flags
seq TCP sequence number
ack TCP acknowledgment number
window TCP window size
icmp_id ICMP identification
These rule options match specific fields in the packet frame structure.
6.2.4 Post-Detection Rule Options
logto Log output path
session Capture user data from TCP sessions
resp Terminate malicious requests by sending responses
react Not just log the specific packet triggering the rule
tag Not just log the specific packet triggering the rule
activates Activate action
activates_by Dynamic action
count Number of packets that the dynamic rule can match once triggered
replace Replace content
detection-filter Detection filtering
6.3 Detection Engine Module Configuration
-
-
Write rules in the *.rules files under /etc/rules directory
Include the corresponding rules in snort.conf
Example:
include $RULE_PATH/local.rules
#include $RULE_PATH/app-detect.rules
#include $RULE_PATH/attack-responses.rules
#include $RULE_PATH/backdoor.rules
#include $RULE_PATH/bad-traffic.rules
#include $RULE_PATH/blacklist.rules
-
7 Snort Alert/Log Module
7.1 Output Module Configuration
The output module configuration is in the snort.conf file under Configure output plugins. Multiple output formats are supported. The following example configures Snort to log alerts in unified2 format, and uses barnyard2 to parse unified2 files and log alerts into the database.
Set the log path:
config logdir:/var/log/snort
Set the output format to unified2:
output unified2: filename snort.log, limit 128
barnyard2.conf
The barnyard2 configuration role is to log unified2 format data into the database.
Link to snort log:
config waldo_file: /var/log/snort/barnyard.waldo
Configure the database:
output database: log, mysql, user=snort password=123456 dbname=snort host=localhost
7.2 Database
-
schema
vseq: Database schema ID
ctime: Database creation timeInformation table, not linked to other database contents.
sensor
sid: Sensor ID
hostname: User name of the sensor
interface: Network interface of the sensor
filter: Filtering rules for the sensor
detail: Level of detail in sensor's monitoring mode
encoding: Data representation format
last_cid: Last captured alert ID for each siddetail
0 - fast: Quick detection
1 - full: Comprehensive detectionDetection level of the sensor.
encoding
0 - Hex
1 - base64
2 - ASCIIData representation formats in the packet.
event
sid: Sensor ID
cid: Event ID - unique within sid
signature: Corresponding signature ID in the signature table
timestamp: System time of the alert eventThe core table, each event represents a packet.
signature
sig_id: Unique rule ID
sig_name: Alert name (message in alert statement)
sig_class_id: Classification ID in sig_class table
sig_priority: Alert priority
sig_rev: Rule revision number
sig_sid: Snort rule ID
sig_gid: Generator IDStores Snort rules, mapping sig_sid, sig_gid, and sig_rev to sid, gid, and rev in the rules.
sig_reference
sig_id: Corresponding signature ID
ref_id: Corresponding reference ID
ref_seq: Reference sequence numberLinks signature to reference information.
reference
ref_id: Main ID
ref_system_id: Reference system ID
ref_tag: Parameters following cve or bugtraq in rulesreference_system
ref_system_id: Main ID
ref_system_name: Name of the reference system (e.g., cve, url)sig_class
sig_class_id: Classification ID
sig_class_name: Classification nameClassification information for alert signatures.
iphdr
tcphdr
udphdr
icmphdr
data data_payload: Packet payload
When the protocol in the rule is TCP, the data_payload contains the content following TCP
When the protocol in the rule is ICMP, the data_payload contains the value of the data field in the ICMP header
opt IP and OPT options