From: Anna Norokh -X (anorokh - SOFTSERVE INC at Cisco) Date: Wed, 20 Sep 2023 13:01:26 +0000 (+0000) Subject: Pull request #3996: parser: add file_id rule syntax evaluation X-Git-Tag: 3.1.71.0~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bf2db2daa4013577e99f08220efb959182bbdd63;p=thirdparty%2Fsnort3.git Pull request #3996: parser: add file_id rule syntax evaluation Merge in SNORT/snort3 from ~ANOROKH/snort3:contentless_file_id to master Squashed commit of the following: commit 62f56f702475340468f31ab8a7f1a0fcbdc3c943 Author: Anna Norokh 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 --- diff --git a/doc/user/concepts.txt b/doc/user/concepts.txt index 358b2540f..e44488786 100644 --- a/doc/user/concepts.txt +++ b/doc/user/concepts.txt @@ -267,7 +267,7 @@ Fast patterns are content strings that have the fast_pattern option or 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. diff --git a/doc/user/file_processing.txt b/doc/user/file_processing.txt index 08754aca6..6c7f65ead 100644 --- a/doc/user/file_processing.txt +++ b/doc/user/file_processing.txt @@ -59,19 +59,19 @@ There are 3 steps to enable file processing: ==== 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 @@ -79,6 +79,9 @@ at content at particular file offset to identify the file type. In this 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 diff --git a/src/detection/fp_detect.cc b/src/detection/fp_detect.cc index 5069726a2..694a85a5b 100644 --- a/src/detection/fp_detect.cc +++ b/src/detection/fp_detect.cc @@ -274,7 +274,6 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p) ** 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. ** @@ -282,8 +281,7 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p) int fpAddMatch(OtnxMatchData* omd, const OptTreeNode* otn) { RuleTreeNode* rtn = getRtnFromOtn(otn); - if ( not rtn ) - return 2; + assert(rtn); unsigned evalIndex = rtn->listhead->ruleListNode->evalIndex; diff --git a/src/file_api/dev_notes.txt b/src/file_api/dev_notes.txt index c2867273b..f4b4bf574 100644 --- a/src/file_api/dev_notes.txt +++ b/src/file_api/dev_notes.txt @@ -16,3 +16,4 @@ threads to improve performance when multiple disks are used. * 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. diff --git a/src/parser/parse_rule.cc b/src/parser/parse_rule.cc index d6e8eae7d..7ee3a256b 100644 --- a/src/parser/parse_rule.cc +++ b/src/parser/parse_rule.cc @@ -94,6 +94,8 @@ static std::string s_type; 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 @@ -1014,7 +1016,17 @@ void parse_rule_opt_end(SnortConfig* sc, const char* key, OptTreeNode* otn) 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++; @@ -1157,6 +1169,28 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn) 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);