Source code for suricata_check.checkers.styleguide.state

  1"""`StateChecker`."""
  2
  3import logging
  4
  5import idstools.rule
  6
  7from suricata_check.checkers.interface import CheckerInterface
  8from suricata_check.utils.checker import (
  9    get_rule_suboptions,
 10    is_rule_option_always_equal_to_regex,
 11    is_rule_option_always_put_before,
 12    is_rule_option_set,
 13    is_rule_suboption_set,
 14)
 15from suricata_check.utils.checker_typing import ISSUES_TYPE, Issue
 16from suricata_check.utils.regex import get_regex_provider
 17
 18_regex_provider = get_regex_provider()
 19
 20_S510_REGEX = _regex_provider.compile(
 21    r"^((set|isset|toggle|unset|isnotset),[A-Z]+\.\w+)|(noalert)$",
 22    _regex_provider.IGNORECASE,
 23)
 24
 25_S520_REGEX = _regex_provider.compile(
 26    r"^((set|isset|toggle|unset|isnotset),[A-Z]+\.\w+)|(noalert),.*$",
 27    _regex_provider.IGNORECASE,
 28)
 29
 30_logger = logging.getLogger(__name__)
 31
 32
[docs] 33class StateChecker(CheckerInterface): 34 """The `StateChecker` contains several checks for Suricata options relating to the connection or detection state. 35 36 Codes S500-S510 report on non-standard usages of `flow` 37 Codes S510-S520 report on non-standard usages of `flowbits` 38 Codes S520-S530 report on non-standard usages of `xbits` 39 """ 40 41 codes = { 42 "S500": {"severity": logging.INFO}, 43 "S501": {"severity": logging.INFO}, 44 "S510": {"severity": logging.INFO}, 45 "S511": {"severity": logging.INFO}, 46 "S520": {"severity": logging.INFO}, 47 "S521": {"severity": logging.INFO}, 48 "S522": {"severity": logging.INFO}, 49 } 50 51 def _check_rule( 52 self: "StateChecker", 53 rule: idstools.rule.Rule, 54 ) -> ISSUES_TYPE: 55 issues: ISSUES_TYPE = [] 56 57 if is_rule_option_set(rule, "flow") and not is_rule_option_always_put_before( 58 rule, 59 "established", 60 ["to_server", "to_client", "from_server", "from_client"], 61 sequence=[suboption[0] for suboption in get_rule_suboptions(rule, "flow")], 62 ): 63 issues.append( 64 Issue( 65 code="S500", 66 message="""\ 67The rule specifies the connection state after the connection direction in the `flow` option. 68Consider specifying the connection state first like `established,to_server`.\ 69""", 70 ), 71 ) 72 73 if is_rule_suboption_set(rule, "flow", "from_client") or is_rule_suboption_set( 74 rule, "flow", "from_server" 75 ): 76 issues.append( 77 Issue( 78 code="S501", 79 message="""\ 80The rule has set `from_client` or `from_server` as a `flow` option. 81Consider using `to_client` or `to_server` instead.\ 82""", 83 ), 84 ) 85 86 if is_rule_option_always_equal_to_regex(rule, "flowbits", _S510_REGEX) is False: 87 issues.append( 88 Issue( 89 code="S510", 90 message="""\ 91The rule sets flowbits with a non-standard name. 92Consider using `RULESET.description` as name for the flowbit.\ 93""", 94 ), 95 ) 96 97 if ( 98 ( 99 is_rule_suboption_set(rule, "flowbits", "set") 100 or is_rule_suboption_set(rule, "flowbits", "unset") 101 ) 102 and not ( 103 is_rule_suboption_set(rule, "flowbits", "isset") 104 or is_rule_suboption_set(rule, "flowbits", "isnotset") 105 ) 106 and not ( 107 is_rule_option_set(rule, "noalert") 108 or is_rule_suboption_set(rule, "flowbits", "noalert") 109 ) 110 ): 111 issues.append( 112 Issue( 113 code="S511", 114 message="""\ 115The rule (un)sets a flowbit but does not use the noalert option. 116Consider using the noalert option to prevent unnecessary alerts.\ 117""", 118 ), 119 ) 120 121 if is_rule_option_always_equal_to_regex(rule, "xbits", _S520_REGEX) is False: 122 issues.append( 123 Issue( 124 code="S520", 125 message="""\ 126The rule sets xbits with a non-standard name. 127Consider using `RULESET.description` as name for the xbit.\ 128""", 129 ), 130 ) 131 132 if ( 133 ( 134 is_rule_suboption_set(rule, "xbits", "set") 135 or is_rule_suboption_set(rule, "xbits", "unset") 136 ) 137 and not is_rule_option_set(rule, "noalert") 138 and not ( 139 is_rule_suboption_set(rule, "xbits", "isset") 140 or is_rule_suboption_set(rule, "xbits", "isnotset") 141 ) 142 ): 143 issues.append( 144 Issue( 145 code="S521", 146 message="""\ 147The rule (un)sets a xbit but does not use the noalert option. 148Consider using the noalert option to prevent unnecessary alerts.\ 149""", 150 ), 151 ) 152 153 if (is_rule_suboption_set(rule, "xbits", "set")) and not is_rule_suboption_set( 154 rule, "xbits", "expire" 155 ): 156 issues.append( 157 Issue( 158 code="S522", 159 message="""\ 160The rule sets a xbit but does not explcitly set the expire option. 161Consider setting the expire option to indicate for how long the xbit remains relevant.\ 162""", 163 ), 164 ) 165 166 return issues