forked from SigmaHQ/pySigma-validators-sigmaHQ
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcondition.py
More file actions
114 lines (90 loc) · 4.57 KB
/
Copy pathcondition.py
File metadata and controls
114 lines (90 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import re
from dataclasses import dataclass
from typing import ClassVar, List
from sigma.correlations import SigmaCorrelationRule
from sigma.rule import SigmaRule
from sigma.validators.base import (
SigmaRuleValidator,
SigmaValidationIssue,
SigmaValidationIssueSeverity,
)
@dataclass
class SigmahqOfthemConditionIssue(SigmaValidationIssue):
description: ClassVar[str] = "Rule uses the ' of them' keyword in the condition with only one \
selection in the detection section"
severity: ClassVar[SigmaValidationIssueSeverity] = SigmaValidationIssueSeverity.LOW
class SigmahqOfthemConditionValidator(SigmaRuleValidator):
"""Check use of the ' of them' keyword with only a single selection in the detection section"""
re_of_them: ClassVar[re.Pattern] = re.compile(r"\s+of\s+them")
def validate(self, rule: SigmaRule | SigmaCorrelationRule) -> List[SigmaValidationIssue]:
if isinstance(rule, SigmaCorrelationRule):
return [] # Correlation rules do not have detections
detection = getattr(rule, "detection", None)
if (
detection is not None
and hasattr(detection, "condition")
and hasattr(detection, "detections")
and any(self.re_of_them.search(condition) for condition in detection.condition)
and len(detection.detections) == 1
):
return [SigmahqOfthemConditionIssue([rule])]
else:
return []
@dataclass
class SigmahqOfselectionConditionIssue(SigmaValidationIssue):
description: ClassVar[str] = "Rule uses the 'All/X of ' format in the condition with only one \
selection in the detection section"
severity: ClassVar[SigmaValidationIssueSeverity] = SigmaValidationIssueSeverity.LOW
selection: str
class SigmahqOfselectionConditionValidator(SigmaRuleValidator):
"""Check use of the 'All/X of ' format with only one selection in the detection section"""
re_x_of_them: ClassVar[re.Pattern] = re.compile(r"(?:\d+|all)\s+of\s+([^\s]+)")
def validate(self, rule: SigmaRule | SigmaCorrelationRule) -> List[SigmaValidationIssue]:
if isinstance(rule, SigmaCorrelationRule):
return [] # Correlation rules do not have detections
detection = getattr(rule, "detection", None)
if (
detection is not None
and hasattr(detection, "condition")
and hasattr(detection, "detections")
):
for condition in detection.condition:
if self.re_x_of_them.search(condition):
all_name = self.re_x_of_them.findall(condition)
for name in all_name:
if name.startswith("filter_") and name.endswith("_*"):
continue
if name.startswith("selection_") and name.endswith("_*"):
continue
if name.endswith("_*"):
selection_count = 0
for selection_name in detection.detections:
if re.match(name, selection_name):
selection_count += 1
if selection_count < 2: # noqa: PLR2004
return [SigmahqOfselectionConditionIssue([rule], name)]
return []
@dataclass
class SigmahqMissingAsteriskConditionIssue(SigmaValidationIssue):
description: ClassVar[str] = (
"Rule uses a '1/all of ' keyword in the condition without an asterisk"
)
severity: ClassVar[SigmaValidationIssueSeverity] = SigmaValidationIssueSeverity.MEDIUM
selection: str
class SigmahqMissingAsteriskConditionValidator(SigmaRuleValidator):
"""Check the use of the '1/all of ' keyword without an asterisk in the condition"""
re_x_of: ClassVar[re.Pattern] = re.compile(r"\s+of\s+([^\s\)]+)")
def validate(self, rule: SigmaRule | SigmaCorrelationRule) -> List[SigmaValidationIssue]:
if isinstance(rule, SigmaCorrelationRule):
return [] # Correlation rules do not have detections
detection = getattr(rule, "detection", None)
if detection is not None and hasattr(detection, "condition"):
for condition in detection.condition:
if self.re_x_of.search(condition):
all_name = self.re_x_of.findall(condition)
for name in all_name:
if name == "them":
continue
if not name.endswith("*"):
return [SigmahqMissingAsteriskConditionIssue([rule], name)]
return []