Skip to content

Commit

Permalink
Option in ReplaceStringTransformation to skip special characters
Browse files Browse the repository at this point in the history
  • Loading branch information
thomaspatzke committed Sep 8, 2024
1 parent df1b714 commit 483a83a
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 7 deletions.
22 changes: 15 additions & 7 deletions sigma/processing/transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,14 +762,17 @@ def apply(
class ReplaceStringTransformation(StringValueTransformation):
"""
Replace string part matched by regular expresssion with replacement string that can reference
capture groups. It operates on the whole string representation of the SigmaString value.
Therefore, it is able to replace special characters like wildcards too.
capture groups. Normally, the replacement operates on the plain string representation of the
SigmaString. This allows also to include special characters and placeholders in the replacement.
By enabling the skip_special parameter, the replacement is only applied to the plain string
parts of a SigmaString and special characters and placeholders are left untouched.
This is basically an interface to re.sub() and can use all features available there.
The replacement is implemented with re.sub() and can use all features available there.
"""

regex: str
replacement: str
skip_special: bool = False

def __post_init__(self):
super().__post_init__()
Expand All @@ -782,10 +785,15 @@ def __post_init__(self):

def apply_string_value(self, field: str, val: SigmaString) -> SigmaString:
if isinstance(val, SigmaString):
sigma_string_plain = str(val)
replaced = self.re.sub(self.replacement, sigma_string_plain)
postprocessed_backslashes = re.sub(r"\\(?![*?])", r"\\\\", replaced)
return SigmaString(postprocessed_backslashes)
if self.skip_special:
return val.map_parts(
lambda s: self.re.sub(self.replacement, s), lambda p: isinstance(p, str)
)
else:
sigma_string_plain = str(val)
replaced = self.re.sub(self.replacement, sigma_string_plain)
postprocessed_backslashes = re.sub(r"\\(?![*?])", r"\\\\", replaced)
return SigmaString(postprocessed_backslashes)


@dataclass
Expand Down
30 changes: 30 additions & 0 deletions tests/test_processing_transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,36 @@ def test_replace_string_specials(dummy_pipeline):
)


def test_replace_string_skip_specials(dummy_pipeline):
sigma_rule = SigmaRule.from_dict(
{
"title": "Test",
"logsource": {"category": "test"},
"detection": {
"test": [
{
"field1": "*\\value",
"field2": 123,
}
],
"condition": "test",
},
}
)
transformation = ReplaceStringTransformation("^.*\\\\", "/", True)
transformation.apply(dummy_pipeline, sigma_rule)
assert sigma_rule.detection.detections["test"] == SigmaDetection(
[
SigmaDetection(
[
SigmaDetectionItem("field1", [], [SigmaString("*/value")]),
SigmaDetectionItem("field2", [], [SigmaNumber(123)]),
]
)
]
)


def test_replace_string_backslashes(dummy_pipeline):
sigma_rule = SigmaRule.from_dict(
{
Expand Down

0 comments on commit 483a83a

Please sign in to comment.