Skip to content

Commit

Permalink
TextQueryBackend optionally allows special characters in startswith, …
Browse files Browse the repository at this point in the history
…endswith, and contains expressions
  • Loading branch information
thomaspatzke committed Oct 14, 2024
1 parent dd25d6e commit 20bc3f2
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 5 deletions.
19 changes: 14 additions & 5 deletions sigma/conversion/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,8 +807,11 @@ class variables. If this is not sufficient, the respective methods can be implem

# String matching operators. if none is appropriate eq_token is used.
startswith_expression: ClassVar[Optional[str]] = None
startswith_expression_allow_special: ClassVar[bool] = False
endswith_expression: ClassVar[Optional[str]] = None
endswith_expression_allow_special: ClassVar[bool] = False
contains_expression: ClassVar[Optional[str]] = None
contains_expression_allow_special: ClassVar[bool] = False
wildcard_match_expression: ClassVar[Optional[str]] = (
None # Special expression if wildcards can't be matched with the eq_token operator.
)
Expand Down Expand Up @@ -1309,9 +1312,10 @@ def convert_condition_field_eq_val_str(
self.startswith_expression
is not None # 'startswith' operator is defined in backend
and cond.value.endswith(SpecialChars.WILDCARD_MULTI) # String ends with wildcard
and not cond.value[
:-1
].contains_special() # Remainder of string doesn't contains special characters
and (
self.startswith_expression_allow_special
or not cond.value[:-1].contains_special()
) # Remainder of string doesn't contains special characters or it's allowed
):
expr = (
self.startswith_expression
Expand All @@ -1320,15 +1324,20 @@ def convert_condition_field_eq_val_str(
elif ( # Same as above but for 'endswith' operator: string starts with wildcard and doesn't contains further special characters
self.endswith_expression is not None
and cond.value.startswith(SpecialChars.WILDCARD_MULTI)
and not cond.value[1:].contains_special()
and (
self.endswith_expression_allow_special or not cond.value[1:].contains_special()
)
):
expr = self.endswith_expression
value = cond.value[1:]
elif ( # contains: string starts and ends with wildcard
self.contains_expression is not None
and cond.value.startswith(SpecialChars.WILDCARD_MULTI)
and cond.value.endswith(SpecialChars.WILDCARD_MULTI)
and not cond.value[1:-1].contains_special()
and (
self.contains_expression_allow_special
or not cond.value[1:-1].contains_special()
)
):
expr = self.contains_expression
value = cond.value[1:-1]
Expand Down
68 changes: 68 additions & 0 deletions tests/test_conversion_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,29 @@ def test_convert_value_str_startswith_further_wildcard(test_backend):
)


def test_convert_value_str_startswith_further_wildcard_allowed(test_backend, monkeypatch):
monkeypatch.setattr(test_backend, "startswith_expression_allow_special", True)
assert (
test_backend.convert(
SigmaCollection.from_yaml(
"""
title: Test
status: test
logsource:
category: test_category
product: test_product
detection:
sel:
fieldA|startswith: "va*lue"
field A|startswith: "va*lue"
condition: sel
"""
)
)
== ['mappedA startswith "va*lue" and \'field A\' startswith "va*lue"']
)


def test_convert_value_str_startswith_expression_not_defined(test_backend, monkeypatch):
monkeypatch.setattr(test_backend, "startswith_expression", None)
assert (
Expand Down Expand Up @@ -416,6 +439,29 @@ def test_convert_value_str_endswith_further_wildcard(test_backend):
)


def test_convert_value_str_endswith_further_wildcard_allowed(test_backend, monkeypatch):
monkeypatch.setattr(test_backend, "endswith_expression_allow_special", True)
assert (
test_backend.convert(
SigmaCollection.from_yaml(
"""
title: Test
status: test
logsource:
category: test_category
product: test_product
detection:
sel:
fieldA|endswith: "va*lue"
field A|endswith: "va*lue"
condition: sel
"""
)
)
== ['mappedA endswith "va*lue" and \'field A\' endswith "va*lue"']
)


def test_convert_value_str_endswith_expression_not_defined(test_backend, monkeypatch):
monkeypatch.setattr(test_backend, "endswith_expression", None)
assert (
Expand Down Expand Up @@ -503,6 +549,28 @@ def test_convert_value_str_contains_further_wildcard(test_backend):
)


def test_convert_value_str_contains_further_wildcard_allowed(test_backend, monkeypatch):
monkeypatch.setattr(test_backend, "contains_expression_allow_special", True)
assert (
test_backend.convert(
SigmaCollection.from_yaml(
"""
title: Test
status: test
logsource:
category: test_category
product: test_product
detection:
sel:
fieldA|contains: "va*lue"
condition: sel
"""
)
)
== ['mappedA contains "va*lue"']
)


def test_convert_value_str_wildcard_to_regex(test_backend, monkeypatch):
monkeypatch.setattr(test_backend, "wildcard_match_expression", '{field} match "{regex}"')
assert (
Expand Down

0 comments on commit 20bc3f2

Please sign in to comment.