https://redmine.openinfosecfoundation.org/issues/5141
- Allow checksum URL to be specified by the index:
https://redmine.openinfosecfoundation.org/issues/5684
+- Metadata rule matching for disable, enable and drop:
+ https://redmine.openinfosecfoundation.org/issues/5561
## 1.2.5 - 2022-09-22
- Update entrypoint search path when not installed with distutils. This is
filename:rules/*deleted*
filename:*/emerging-dos.rules
+Metadata Matching
+-----------------
+
+Rules can be enabled or disabled based on the metadata fields
+contained in the rule, for example::
+
+ metadata: deployment perimeter
+
+Will match rules that have a metadata field of "deployment" with the
+value of "perimeter" (case insensitive). This will match on a rule
+with the provided metadata::
+
+ metadata:affected_product Any, attack_target Any, deployment Perimeter
+
+.. note:: Metadata matching can only be used to enable, disable or
+ convert rules to drop. It is not available for rule
+ modification.
+
Modifying Rules
---------------
# group:emerging-icmp.rules
# group:emerging-dos
# group:emerging*
+
+# Disable all rules with a metadata of "deployment perimeter". Note that metadata
+# matches are case insensitive.
+# metadata: deployment perimeter
\ No newline at end of file
# group:emerging-icmp.rules
# group:emerging-dos
# group:emerging*
+
+# Enable all rules with a metadata of "deployment perimeter". Note that metadata
+# matches are case insensitive.
+# metadata: deployment perimeter
\ No newline at end of file
return None
+class MetadataRuleMatch(object):
+ """ Matcher that matches on key/value style metadata fields. Case insensitive. """
+
+ def __init__(self, key, value):
+ self.key = key
+ self.value = value
+
+ def match(self, rule):
+ for entry in rule.metadata:
+ parts = entry.strip().split(" ", 1)
+ if parts[0].strip().lower() == self.key and parts[1].strip().lower() == self.value:
+ print(rule)
+ return True
+ return False
+
+ @classmethod
+ def parse(cls, buf):
+ print(buf)
+ if buf.startswith("metadata:"):
+ buf = buf.split(":", 1)[1].strip()
+ parts = buf.split(" ", 1)
+ if len(parts) == 2:
+ key = parts[0].strip().lower()
+ val = parts[1].strip().lower()
+ return cls(key, val)
+ return None
+
+
class ModifyRuleFilter(object):
"""Filter to modify an idstools rule object.
if matcher:
return matcher
+ matcher = MetadataRuleMatch.parse(match)
+ if matcher:
+ return matcher
+
return None
new_rule = metadata_filter.run(rule)
self.assertIsNotNone(new_rule)
self.assertTrue(new_rule.format().find("evebox.action") > -1)
+
+class MetadataMatchTestCase(unittest.TestCase):
+
+ def test_match_metadata(self):
+ """
+ Looking for: deployment Perimeter
+ """
+ rule_string = b"""alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"ET WEB_SPECIFIC_APPS PHPStudy Remote Code Execution Backdoor"; flow:established,to_server; http.method; content:"GET"; http.header; content:"Accept-Charset|3a 20|"; fast_pattern; nocase; pcre:"/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})\\x0d\\x0a/R"; reference:url,www.cnblogs.com/-qing-/p/11575622.html; reference:url,www.uedbox.com/post/59265/; classtype:attempted-admin; sid:2028629; rev:1; metadata:affected_product Web_Server_Applications, attack_target Server, created_at 2019_09_25, deployment Perimeter, former_category WEB_SPECIFIC_APPS, performance_impact Significant, signature_severity Major, updated_at 2019_09_25;)"""
+ rule = suricata.update.rule.parse(rule_string)
+ self.assertIsNotNone(rule)
+ filter_string = "metadata: deployment perimeter"
+ metadata_filter = matchers_mod.MetadataRuleMatch.parse(filter_string)
+ self.assertIsNotNone(metadata_filter)
+ self.assertTrue(metadata_filter.match(rule))