Merge in SNORT/snort3 from ~ANOROKH/snort3:contentless_file_id to master
Squashed commit of the following:
commit
62f56f702475340468f31ab8a7f1a0fcbdc3c943
Author: Anna Norokh <anorokh@cisco.com>
Date: Wed Sep 13 11:03:31 2023 +0300
parser: add file_id rule syntax evaluation
* drop ParseError in case of file_id rule without file_meta,
fast-pattern(content,regex) or file_data option;
* update file_id docs;
* detection: replace rtn hard check with assert
which have been selected by Snort automatically to be used as a fast
pattern. Snort will by default choose the longest pattern in the rule
since that is likely to be most unique. That is not always the case so add
-fast_pattern to the appropriate content option for best performance. The
+fast_pattern to the appropriate content or regex option for best performance. The
ideal fast pattern is one which, if found, is very likely to result in a
rule match. Fast patterns that match frequently for unrelated traffic will
cause Snort to work hard with little to show for it.
==== Pre-packaged File Magic Rules
A set of file magic rules is packaged with Snort. They can be located at
-"lua/file_magic.lua". To use this feature, it is recommended that these
+"lua/file_magic.rules". To use this feature, it is recommended that these
pre-packaged rules are used; doing so requires that you include
the file in your Snort configuration as such (already in snort.lua):
- dofile('magic.lua')
+ file_id = { rules_file = 'file_magic.rules' }
Example:
- { type = "GIF", id = 62, category = "Graphics", rev = 1,
- magic = { { content = "| 47 49 46 38 37 61 |",offset = 0 } } },
+ file_id (msg:"GIF"; file_meta:type GIF, id 62, category "Graphics";
+ file_data; content:"| 47 49 46 38 37 61 |", depth 6, offset 0; gid:4; sid:56; rev:1;)
- { type = "GIF", id = 63, category = "Graphics", rev = 1,
- magic = { { content = "| 47 49 46 38 39 61 |",offset = 0 } } },
+ file_id (msg:"GIF"; file_meta:type GIF, id 63, category 'Graphics";
+ file_data; content:"| 47 49 46 38 39 61 |", depth 6, offset 0; gid:4; sid:57; rev:1;)
The previous two rules define GIF format, because two file magics are
different. File magics are specified by content and offset, which look
case, two magics look at the beginning of the file. You can use character
if it is printable or hex value in between "|".
+Note that `file_meta` and a fast-pattern option (content, regex) are required
+for each file_id rule.
+
==== File Policy
You can enabled file type, file signature, or file capture by configuring
** OptTreeNode * - the otn to add.
**
** FORMAL OUTPUTS
-** int - 2 No rule tree node found for given policy ID.
** int - 1 max_events variable hit.
** int - 0 successful.
**
int fpAddMatch(OtnxMatchData* omd, const OptTreeNode* otn)
{
RuleTreeNode* rtn = getRtnFromOtn(otn);
- if ( not rtn )
- return 2;
+ assert(rtn);
unsigned evalIndex = rtn->listhead->ruleListNode->evalIndex;
* File libraries: provides file type identification and file signature
calculation
+* file_id: file rules must contain `file_meta` and at least one fast-pattern option.
static std::string s_body;
static bool action_file_id = false;
+static bool fp_file_id = false;
+static bool only_file_data = true;
static bool strict_rtn_reduction = false;
struct SoRule
CursorActionType cat = ips ? ips->get_cursor_type() : CAT_NONE;
if ( cat > CAT_ADJUST )
+ {
buf_is_set = true;
+ if ( action_file_id and strcmp(ips->get_name(), "file_data") )
+ only_file_data = false;
+ }
+
+ if ( ips and action_file_id )
+ {
+ if ( !strcmp(ips->get_name(), "content") or !strcmp(ips->get_name(), "regex") )
+ fp_file_id = true;
+ }
if ( type != OPT_TYPE_META )
otn->num_detection_opts++;
return;
}
+ if ( action_file_id )
+ {
+ if ( !otn->sigInfo.file_id )
+ ParseError("file_id rule %u:%u:%u requires file_meta option", otn->sigInfo.gid,
+ otn->sigInfo.sid, otn->sigInfo.rev);
+
+ if ( !fp_file_id )
+ ParseError("file_id rule %u:%u:%u requires a fast-pattern option",
+ otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+
+ if ( buf_is_set and !only_file_data )
+ ParseError("file_id rule %u:%u:%u disallows IPS buffers that are not file_data",
+ otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+
+ if ( !buf_is_set )
+ ParseError("file_id rule %u:%u:%u requires file_data option",
+ otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+
+ only_file_data = true;
+ fp_file_id = false;
+ }
+
RuleTreeNode* tmp = s_so_rule ? s_so_rule->rtn : &rtn;
RuleTreeNode* new_rtn = transfer_rtn(tmp);
addRtnToOtn(sc, otn, new_rtn);