]> git.ipfire.org Git - thirdparty/suricata-update.git/commitdiff
matching: match on rule metadata
authorJason Ish <jason.ish@oisf.net>
Sat, 29 Oct 2022 04:55:20 +0000 (22:55 -0600)
committerJason Ish <jason.ish@oisf.net>
Fri, 25 Nov 2022 17:38:24 +0000 (11:38 -0600)
Allow metadata matching for enable and disable. For example:

    metadata: deployment perimeter

will match rules with "metadata: deployment Perimeter".

Match is case insensitive.

Ticket: #5561

CHANGELOG.md
doc/update.rst
suricata/update/configs/disable.conf
suricata/update/configs/enable.conf
suricata/update/matchers.py
tests/test_matchers.py

index 095de5949574e7d3e1554301812d51b705f972b7..ec4cbc6a9d897802a3d0f3766cb029882122b63f 100644 (file)
@@ -15,6 +15,8 @@
   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
index 19ab525756c0b91a6ac8717aeb673b25f3e72056..c3db62e30875ffaa3cf295574792251c6424067b 100644 (file)
@@ -241,6 +241,24 @@ are allowed::
   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
 ---------------
 
index 7639000073ea4c185c820b53c42fb59130dd6ce1..59d0e18a195538f4fe86fc846dab1b6fa3c91938 100644 (file)
@@ -13,3 +13,7 @@
 # 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
index e549b4bb8720641703df50d7dfe4e33271e62e3c..ad7b4e2ae4e76e4a8c2fc51f46edb8e54302291a 100644 (file)
@@ -13,3 +13,7 @@
 # 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
index fae83f74188fbf02fff4c371cafc91c84793deca..e886c79784e8b56b2f52293fc7dbf7235bdda54b 100644 (file)
@@ -184,6 +184,34 @@ class ReRuleMatcher(object):
         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.
 
@@ -296,4 +324,8 @@ def parse_rule_match(match):
     if matcher:
         return matcher
 
+    matcher = MetadataRuleMatch.parse(match)
+    if matcher:
+        return matcher
+
     return None
index 7acec5a3d349d6fab6e8cc682833fd596a2ef8c6..ad64a540283b867fdd556de7730d5ac584406ef4 100644 (file)
@@ -119,3 +119,17 @@ class MetadataAddTestCase(unittest.TestCase):
         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))