Skip to content

Commit

Permalink
fixing multiple regexes on the same field
Browse files Browse the repository at this point in the history
  • Loading branch information
arblade committed Mar 23, 2024
1 parent f3c8a88 commit 1a63781
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
47 changes: 34 additions & 13 deletions sigma/backends/splunk/splunk.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,46 @@ class SplunkDeferredRegularExpression(DeferredTextQueryExpression):


class SplunkDeferredORRegularExpression(DeferredTextQueryExpression):
instance_count = 0
field_counts = {}
default_field = "_raw"
operators = {
True: "!=",
False: "=",
}

def __init__(self, state, field, arg) -> None:
SplunkDeferredORRegularExpression.instance_count += 1
current_num_instance = str(SplunkDeferredORRegularExpression.instance_count)
SplunkDeferredORRegularExpression.add_field(field)
index_suffix = SplunkDeferredORRegularExpression.get_index_suffix(field)
self.template = (
'rex field={field} "(?<{field}Match'
+ current_num_instance
+ '>{value})" \n| eval {field}Condition'
+ current_num_instance
+ index_suffix
+ '>{value})"\n| eval {field}Condition'
+ index_suffix
+ "=if(isnotnull({field}Match"
+ current_num_instance
+ index_suffix
+ '), "true", "false")'
)
return super().__init__(state, field, arg)

@classmethod
def add_field(cls, field):
cls.field_counts[field] = (
cls.field_counts.get(field, 0) + 1
) # increment the field count

@classmethod
def get_index_suffix(cls, field):

index_suffix = cls.field_counts.get(field, 0)
if index_suffix == 1:
# return nothing for the first field use
return ""
return str(index_suffix)

@classmethod
def reset(cls):
cls.field_counts = {}


class SplunkDeferredCIDRExpression(DeferredTextQueryExpression):
template = 'where {op}cidrmatch("{value}", {field})'
Expand Down Expand Up @@ -230,7 +249,7 @@ def convert_condition_field_eq_val_re(
cond_true = ConditionFieldEqualsValueExpression(
cond.field
+ "Condition"
+ str(SplunkDeferredORRegularExpression.instance_count),
+ str(SplunkDeferredORRegularExpression.get_index_suffix(cond.field)),
SigmaString("true"),
)
# returning fieldX=true
Expand Down Expand Up @@ -262,11 +281,10 @@ def finalize_query(
state: ConversionState,
output_format: str,
) -> Union[str, DeferredQueryExpression]:
# need to reset the instances count of deferred oring expression classes
SplunkDeferredORRegularExpression.instance_count = 0

if state.has_deferred():
deferred_regex_or_expressions = []
no_regex_oring_deferred_expression = []
no_regex_oring_deferred_expressions = []

for index, deferred_expression in enumerate(state.deferred):

Expand All @@ -275,11 +293,14 @@ def finalize_query(
deferred_expression.finalize_expression()
)
else:
no_regex_oring_deferred_expression.append(deferred_expression)
no_regex_oring_deferred_expressions.append(deferred_expression)

if len(deferred_regex_or_expressions) > 0:
SplunkDeferredORRegularExpression.reset() # need to reset class for potential future conversions
# remove deferred oring regex expressions from the state
state.deferred = no_regex_oring_deferred_expression
# as they will be taken into account by the super().finalize_query
state.deferred = no_regex_oring_deferred_expressions

return super().finalize_query(
rule,
self.deferred_start
Expand Down
4 changes: 2 additions & 2 deletions tests/test_backend_splunk.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ def test_splunk_regex_query_implicit_or(splunk_backend: SplunkBackend):
)
)
== [
'\n| rex field=fieldA "(?<fieldAMatch>foo.*bar)" \n| eval fieldACondition=if(isnotnull(fieldAMatch), "true", "false")\n| rex field=fieldB "(?<fieldBMatch>boo.*foo)" \n| eval fieldBCondition=if(isnotnull(fieldAConditionMatch), "true", "false")\n| search (fieldACondition="true" OR fieldBCondition="true") fieldB="foo" fieldC="bar"'
'\n| rex field=fieldA "(?<fieldAMatch>foo.*bar)"\n| eval fieldACondition=if(isnotnull(fieldAMatch), "true", "false")\n| rex field=fieldA "(?<fieldAMatch2>boo.*foo)"\n| eval fieldACondition2=if(isnotnull(fieldAMatch2), "true", "false")\n| search fieldACondition="true" OR fieldACondition2="true" fieldB="foo" fieldC="bar"'
]
)

Expand All @@ -219,7 +219,7 @@ def test_splunk_regex_query_explicit_or(splunk_backend: SplunkBackend):
)
)
== [
'\n| rex field=fieldA "(?<fieldAMatch>foo.*bar)" \n| eval fieldACondition=if(isnotnull(fieldAMatch), "true", "false")\n| rex field=fieldB "(?<fieldBMatch>boo.*foo)" \n| eval fieldBCondition=if(isnotnull(fieldBMatch), "true", "false")\n| search fieldACondition="true" OR fieldBCondition="true"'
'\n| rex field=fieldA "(?<fieldAMatch>foo.*bar)"\n| eval fieldACondition=if(isnotnull(fieldAMatch), "true", "false")\n| rex field=fieldB "(?<fieldBMatch>boo.*foo)"\n| eval fieldBCondition=if(isnotnull(fieldBMatch), "true", "false")\n| search fieldACondition="true" OR fieldBCondition="true"'
]
)

Expand Down

0 comments on commit 1a63781

Please sign in to comment.