From da30266c60bcef34d6a6d338a7e134212efb319c Mon Sep 17 00:00:00 2001 From: bar Date: Tue, 21 Jul 2020 17:21:14 +0300 Subject: [PATCH 01/10] ImageLoaded mapping added --- tools/config/stix-windows.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/config/stix-windows.yml b/tools/config/stix-windows.yml index b3026badb..30281befd 100644 --- a/tools/config/stix-windows.yml +++ b/tools/config/stix-windows.yml @@ -84,7 +84,7 @@ fieldmappings: Image: - process:image_ref.name ImageLoadedTempPath: - - process:image_ref.x_temp_path + - process:extensions.windows-service-ext.service_dll_refs[*].x_temp_path ImageName: - process:image_ref.name ImagePath: @@ -101,9 +101,9 @@ fieldmappings: IntegrityLevel: - x-windows:integritylevel LoadedImage: - - process:image_ref.name + - process:extensions.windows-service-ext.service_dll_refs[*].name LoadedImageName: - - process:image_ref.name + - process:extensions.windows-service-ext.service_dll_refs[*].name LogonType: - x-windows:logontype MD5Hash: @@ -248,9 +248,9 @@ fieldmappings: event_data.Image: - process:image_ref.name event_data.ImageLoaded: - - process:image_ref.name + - process:extensions.windows-service-ext.service_dll_refs[*].name ImageLoaded: - - process:image_ref.name + - process:extensions.windows-service-ext.service_dll_refs[*].name event_data.ImagePath: - process:image_ref.name event_data.ParentCommandLine: From 0543ec1ae3e1d00fde2bf1bb8a5e3339afef2d01 Mon Sep 17 00:00:00 2001 From: bar Date: Tue, 21 Jul 2020 19:49:26 +0300 Subject: [PATCH 02/10] mapping update, removed unused fields --- tools/config/stix-windows.yml | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/tools/config/stix-windows.yml b/tools/config/stix-windows.yml index 30281befd..1083cbcef 100644 --- a/tools/config/stix-windows.yml +++ b/tools/config/stix-windows.yml @@ -21,8 +21,6 @@ fieldmappings: - user-account:x_security_id CallTrace: - x-windows:calltrace - ChangedAttributes: - - x-windows:changedattributes ClientIP: - ipv4-addr:value - ipv6-addr:value @@ -116,8 +114,6 @@ fieldmappings: - x-windows:objectname ObjectType: - x-windows:objecttype - PSEncodedCommand: - - x-windows:psencodedcommand ParentCommandLine: - process:parent_ref.command_line ParentImage: @@ -152,26 +148,19 @@ fieldmappings: - x-windows:queryresults QueryStatus: - x-windows:querystatus - Realm: - - x-windows:realm - RecordNumber: - - x-windows:recordnumber RegistryKey: - windows-registry-key:key RegistryValueData: - windows-registry-key:values[*].data RegistryValueName: - windows-registry-key:values[*].name - RunLevel: - - x-windows:runlevel SAMAccountName: - - x-windows:samaccountname + - user-account:account_login + - user-account:display_name SHA1Hash: - file:hashes.SHA-1 SHA256Hash: - file:hashes.SHA-256 - Scope: - - x-windows:scope ServiceFileName: - process:extensions.windows-service-ext.service_dll_refs[*].name ServiceName: @@ -233,12 +222,6 @@ fieldmappings: - user-account:user_id UserDomain: - user-account:x_domain - UserPrincipalName: - - x-windows:userprincipalname - UserRight: - - x-windows:userright - UserWorkstations: - - x-windows:userworkstations event-id: - x-event:id eventId: From 5019f2f1601b247aa67debc453c3cb22d39c3388 Mon Sep 17 00:00:00 2001 From: bar Date: Wed, 22 Jul 2020 21:41:46 +0300 Subject: [PATCH 03/10] added mapping for stix web, cloud, linux --- tools/config/stix-linux.yml | 36 +++++++++++++++++++++++++++++++ tools/config/stix.yml | 43 ++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tools/config/stix-linux.yml diff --git a/tools/config/stix-linux.yml b/tools/config/stix-linux.yml new file mode 100644 index 000000000..e374f29b2 --- /dev/null +++ b/tools/config/stix-linux.yml @@ -0,0 +1,36 @@ +title: STIX for Linux Logs +backends: + - stix +order: 40 +logsources: + linux: + product: linux +fieldmappings: + type: + - x-event:action + keywords: + - x-sigma:keywords + a0: + - process:command_line + a1: + - process:command_line + name: + - file:name + a3: + - process:command_line + key: + - x-sigma:keywords + exe: + - file:name + a2: + - process:command_line + SYSCALL: + - x-event:action + pam_message: + - x-event:action + pam_user: + - user-account:user_id + pam_rhost: + - x-host:name + USER: + - user-account:user_id \ No newline at end of file diff --git a/tools/config/stix.yml b/tools/config/stix.yml index c6d13293c..7cdad7e78 100644 --- a/tools/config/stix.yml +++ b/tools/config/stix.yml @@ -91,4 +91,45 @@ fieldmappings: username: - user-account:user_id utf8_payload: - - artifact:payload_bin \ No newline at end of file + - artifact:payload_bin + + # Web mapping + c-uri: + - url:value + keywords: + - x-sigma:keywords + cs-method: + - http-request-ext:request_method + sc-status: + - x-web:status_code + clientip: + - ipv4-addr:value + - ipv6-addr:value + - network-traffic:src_ref.value + + # Cloud mapping + eventSource: + - x-host:name + eventName: + - x-event:action + requestParameters.attribute: + - x-cloud:request_parameters + responseElements.publiclyAccessible: + - x-cloud:publicly_accessible + errorMessage: + - x-error:message + errorCode: + - x-error:code + responseElements: + - x-cloud:response_elements + requestParameters.userData: + - x-cloud:request_parameters + userIdentity.type: + - user-account:account_login + eventType: + - x-event:action + userIdentity.arn: + - user-account:account_login + - user-account:display_name + responseElements.pendingModifiedValues.masterUserPassword: + - user-account:credential From 30ff22776a0bd7644090ad5d79fe061e6ee9fed6 Mon Sep 17 00:00:00 2001 From: Simran Soin Date: Thu, 23 Jul 2020 09:41:33 -0400 Subject: [PATCH 04/10] Fix NOT bug --- tools/sigma/backends/base.py | 31 +++++++++++++++------------ tools/sigma/backends/qradar.py | 6 +++++- tools/sigma/backends/stix.py | 39 +++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/tools/sigma/backends/base.py b/tools/sigma/backends/base.py index 1ef7e175a..b9671fd22 100644 --- a/tools/sigma/backends/base.py +++ b/tools/sigma/backends/base.py @@ -154,10 +154,12 @@ class BaseBackend: pass return query - def generateNode(self, node): + def generateNode(self, node, currently_within_NOT_node=False): if type(node) == sigma.parser.condition.ConditionAND: return self.applyOverrides(self.generateANDNode(node)) elif type(node) == sigma.parser.condition.ConditionOR: + if currently_within_NOT_node: + return self.applyOverrides(self.generateANDNode(node)) return self.applyOverrides(self.generateORNode(node)) elif type(node) == sigma.parser.condition.ConditionNOT: return self.applyOverrides(self.generateNOTNode(node)) @@ -246,8 +248,8 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): sort_condition_lists = False # Sort condition items for AND and OR conditions - def generateANDNode(self, node): - generated = [ self.generateNode(val) for val in node ] + def generateANDNode(self, node, currently_within_NOT_node=False): + generated = [ self.generateNode(val, currently_within_NOT_node) for val in node ] filtered = [ g for g in generated if g is not None ] if filtered: if self.sort_condition_lists: @@ -256,8 +258,8 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): else: return None - def generateORNode(self, node): - generated = [ self.generateNode(val) for val in node ] + def generateORNode(self, node, currently_within_NOT_node): + generated = [ self.generateNode(val, currently_within_NOT_node) for val in node ] filtered = [ g for g in generated if g is not None ] if filtered: if self.sort_condition_lists: @@ -266,33 +268,34 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): else: return None - def generateNOTNode(self, node): - generated = self.generateNode(node.item) + def generateNOTNode(self, node, currently_within_NOT_node): + currently_within_NOT_node = True + generated = self.generateNode(node.item, currently_within_NOT_node) if generated is not None: - return self.notToken + generated + return generated else: return None - def generateSubexpressionNode(self, node): - generated = self.generateNode(node.items) + def generateSubexpressionNode(self, node, currently_within_NOT_node): + generated = self.generateNode(node.items, currently_within_NOT_node) if generated: return self.subExpression % generated else: return None - def generateListNode(self, node): + def generateListNode(self, node, currently_within_NOT_node): if not set([type(value) for value in node]).issubset({str, int}): raise TypeError("List values must be strings or numbers") return self.listExpression % (self.listSeparator.join([self.generateNode(value) for value in node])) - def generateMapItemNode(self, node): + def generateMapItemNode(self, node, currently_within_NOT_node): fieldname, value = node transformed_fieldname = self.fieldNameMapping(fieldname, value) if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): return self.mapExpression % (transformed_fieldname, self.generateNode(value)) elif type(value) == list: - return self.generateMapItemListNode(transformed_fieldname, value) + return self.generateMapItemListNode(transformed_fieldname, value, currently_within_NOT_node) elif isinstance(value, SigmaTypeModifier): return self.generateMapItemTypedNode(transformed_fieldname, value) elif value is None: @@ -300,7 +303,7 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): else: raise TypeError("Backend does not support map values of type " + str(type(value))) - def generateMapItemListNode(self, fieldname, value): + def generateMapItemListNode(self, fieldname, value, currently_within_NOT_node): return self.mapListValueExpression % (fieldname, self.generateNode(value)) def generateMapItemTypedNode(self, fieldname, value): diff --git a/tools/sigma/backends/qradar.py b/tools/sigma/backends/qradar.py index f29024af1..825332215 100644 --- a/tools/sigma/backends/qradar.py +++ b/tools/sigma/backends/qradar.py @@ -58,10 +58,14 @@ class QRadarBackend(SingleTextQueryBackend): """Remove quotes in text""" return value.replace("\'","\\\'") - def generateNode(self, node): + def generateNode(self, node, currently_within_NOT_node=False): if type(node) == sigma.parser.condition.ConditionAND: + if currently_within_NOT_node: + return self.generateORNode(node) return self.generateANDNode(node) elif type(node) == sigma.parser.condition.ConditionOR: + if currently_within_NOT_node: + return self.generateANDNode(node) return self.generateORNode(node) elif type(node) == sigma.parser.condition.ConditionNOT: return self.generateNOTNode(node) diff --git a/tools/sigma/backends/stix.py b/tools/sigma/backends/stix.py index 82e7b3fd5..539da0434 100644 --- a/tools/sigma/backends/stix.py +++ b/tools/sigma/backends/stix.py @@ -26,15 +26,24 @@ class STIXBackend(SingleTextQueryBackend): def cleanValue(self, value): return value - def generateMapItemListNode(self, key, value): + def generateMapItemListNode(self, key, value, currently_within_NOT_node): items_list = list() for item in value: if type(item) == str and "*" in item: item = item.replace("*", "%") - items_list.append('%s LIKE %s' % (self.cleanKey(key), self.generateValueNode(item))) + if currently_within_NOT_node: + items_list.append('%s NOT LIKE %s' % (self.cleanKey(key), self.generateValueNode(item))) + else: + items_list.append('%s LIKE %s' % (self.cleanKey(key), self.generateValueNode(item))) else: - items_list.append('%s = %s' % (self.cleanKey(key), self.generateValueNode(item))) - return '('+" OR ".join(items_list)+')' + if currently_within_NOT_node: + items_list.append('%s != %s' % (self.cleanKey(key), self.generateValueNode(item))) + else: + items_list.append('%s = %s' % (self.cleanKey(key), self.generateValueNode(item))) + if currently_within_NOT_node: + return '(' + " AND ".join(items_list) + ')' + else: + return '('+" OR ".join(items_list)+')' def generateMapItemTypedNode(self, key, value): if type(value) == SigmaRegularExpressionModifier: @@ -48,18 +57,20 @@ class STIXBackend(SingleTextQueryBackend): else: raise NotImplementedError("Type modifier '{}' is not supported by backend".format(value.identifier)) - def generateMapItemNode(self, node): + def generateMapItemNode(self, node, currently_within_NOT_node): key, value = node if ":" not in key: key = "%s:%s" % (self.sigmaSTIXObjectName, str(key).lower()) if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): if type(value) == str and "*" in value: value = value.replace("*", "%") + if currently_within_NOT_node: + return "%s NOT LIKE %s" % (self.cleanKey(key), self.generateValueNode(value)) return "%s LIKE %s" % (self.cleanKey(key), self.generateValueNode(value)) elif type(value) in (str, int): return self.mapExpression % (self.cleanKey(key), self.generateValueNode(value)) elif type(value) == list: - return self.generateMapItemListNode(key, value) + return self.generateMapItemListNode(key, value, currently_within_NOT_node) elif isinstance(value, SigmaTypeModifier): return self.generateMapItemTypedNode(key, value) else: @@ -68,17 +79,21 @@ class STIXBackend(SingleTextQueryBackend): def generateValueNode(self, node): return self.valueExpression % (self.cleanValue(str(node))) - def generateNode(self, node): + def generateNode(self, node, currently_within_NOT_node=False): if type(node) == sigma.parser.condition.ConditionAND: - return self.generateANDNode(node) + if currently_within_NOT_node: + return self.generateORNode(node, currently_within_NOT_node) + return self.generateANDNode(node, currently_within_NOT_node) elif type(node) == sigma.parser.condition.ConditionOR: - return self.generateORNode(node) + if currently_within_NOT_node: + return self.generateANDNode(node, currently_within_NOT_node) + return self.generateORNode(node, currently_within_NOT_node) elif type(node) == sigma.parser.condition.ConditionNOT: - return self.generateNOTNode(node) + return self.generateNOTNode(node, currently_within_NOT_node) elif type(node) == sigma.parser.condition.NodeSubexpression: - return self.generateSubexpressionNode(node) + return self.generateSubexpressionNode(node, currently_within_NOT_node) elif type(node) == tuple: - return self.generateMapItemNode(node) + return self.generateMapItemNode(node, currently_within_NOT_node) else: raise TypeError("Node type %s was not expected in Sigma parse tree" % (str(type(node)))) From 0fac21f4a33d79b9bb882647e4a46354948bd639 Mon Sep 17 00:00:00 2001 From: Simran Soin Date: Thu, 23 Jul 2020 10:13:30 -0400 Subject: [PATCH 05/10] Remove modifications from base file and override in stix.py --- tools/sigma/backends/base.py | 29 ++++++++++----------- tools/sigma/backends/stix.py | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/tools/sigma/backends/base.py b/tools/sigma/backends/base.py index b9671fd22..1840f1519 100644 --- a/tools/sigma/backends/base.py +++ b/tools/sigma/backends/base.py @@ -154,12 +154,10 @@ class BaseBackend: pass return query - def generateNode(self, node, currently_within_NOT_node=False): + def generateNode(self, node): if type(node) == sigma.parser.condition.ConditionAND: return self.applyOverrides(self.generateANDNode(node)) elif type(node) == sigma.parser.condition.ConditionOR: - if currently_within_NOT_node: - return self.applyOverrides(self.generateANDNode(node)) return self.applyOverrides(self.generateORNode(node)) elif type(node) == sigma.parser.condition.ConditionNOT: return self.applyOverrides(self.generateNOTNode(node)) @@ -248,8 +246,8 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): sort_condition_lists = False # Sort condition items for AND and OR conditions - def generateANDNode(self, node, currently_within_NOT_node=False): - generated = [ self.generateNode(val, currently_within_NOT_node) for val in node ] + def generateANDNode(self, node): + generated = [ self.generateNode(val) for val in node ] filtered = [ g for g in generated if g is not None ] if filtered: if self.sort_condition_lists: @@ -258,8 +256,8 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): else: return None - def generateORNode(self, node, currently_within_NOT_node): - generated = [ self.generateNode(val, currently_within_NOT_node) for val in node ] + def generateORNode(self, node): + generated = [ self.generateNode(val) for val in node ] filtered = [ g for g in generated if g is not None ] if filtered: if self.sort_condition_lists: @@ -268,34 +266,33 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): else: return None - def generateNOTNode(self, node, currently_within_NOT_node): - currently_within_NOT_node = True - generated = self.generateNode(node.item, currently_within_NOT_node) + def generateNOTNode(self, node): + generated = self.generateNode(node.item) if generated is not None: return generated else: return None - def generateSubexpressionNode(self, node, currently_within_NOT_node): - generated = self.generateNode(node.items, currently_within_NOT_node) + def generateSubexpressionNode(self, node): + generated = self.generateNode(node.items) if generated: return self.subExpression % generated else: return None - def generateListNode(self, node, currently_within_NOT_node): + def generateListNode(self, node): if not set([type(value) for value in node]).issubset({str, int}): raise TypeError("List values must be strings or numbers") return self.listExpression % (self.listSeparator.join([self.generateNode(value) for value in node])) - def generateMapItemNode(self, node, currently_within_NOT_node): + def generateMapItemNode(self, node): fieldname, value = node transformed_fieldname = self.fieldNameMapping(fieldname, value) if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): return self.mapExpression % (transformed_fieldname, self.generateNode(value)) elif type(value) == list: - return self.generateMapItemListNode(transformed_fieldname, value, currently_within_NOT_node) + return self.generateMapItemListNode(transformed_fieldname, value) elif isinstance(value, SigmaTypeModifier): return self.generateMapItemTypedNode(transformed_fieldname, value) elif value is None: @@ -303,7 +300,7 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): else: raise TypeError("Backend does not support map values of type " + str(type(value))) - def generateMapItemListNode(self, fieldname, value, currently_within_NOT_node): + def generateMapItemListNode(self, fieldname, value): return self.mapListValueExpression % (fieldname, self.generateNode(value)) def generateMapItemTypedNode(self, fieldname, value): diff --git a/tools/sigma/backends/stix.py b/tools/sigma/backends/stix.py index 539da0434..f0d43393a 100644 --- a/tools/sigma/backends/stix.py +++ b/tools/sigma/backends/stix.py @@ -26,6 +26,56 @@ class STIXBackend(SingleTextQueryBackend): def cleanValue(self, value): return value + def generateANDNode(self, node, currently_within_NOT_node=False): + generated = [self.generateNode(val, currently_within_NOT_node) for val in node] + filtered = [g for g in generated if g is not None] + if filtered: + if self.sort_condition_lists: + filtered = sorted(filtered) + return self.andToken.join(filtered) + else: + return None + + def generateORNode(self, node, currently_within_NOT_node): + generated = [self.generateNode(val, currently_within_NOT_node) for val in node] + filtered = [g for g in generated if g is not None] + if filtered: + if self.sort_condition_lists: + filtered = sorted(filtered) + return self.orToken.join(filtered) + else: + return None + + def generateNOTNode(self, node, currently_within_NOT_node): + currently_within_NOT_node = True + generated = self.generateNode(node.item, currently_within_NOT_node) + if generated is not None: + return generated + else: + return None + + def generateSubexpressionNode(self, node, currently_within_NOT_node): + generated = self.generateNode(node.items, currently_within_NOT_node) + if generated: + return self.subExpression % generated + else: + return None + + def generateMapItemNode(self, node, currently_within_NOT_node): + fieldname, value = node + + transformed_fieldname = self.fieldNameMapping(fieldname, value) + if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + return self.mapExpression % (transformed_fieldname, self.generateNode(value)) + elif type(value) == list: + return self.generateMapItemListNode(transformed_fieldname, value, currently_within_NOT_node) + elif isinstance(value, SigmaTypeModifier): + return self.generateMapItemTypedNode(transformed_fieldname, value) + elif value is None: + return self.nullExpression % (transformed_fieldname, ) + else: + raise TypeError("Backend does not support map values of type " + str(type(value))) + def generateMapItemListNode(self, key, value, currently_within_NOT_node): items_list = list() for item in value: From 0e49a6acdf2fc33bdb0c906f6dc81bf52547a9d4 Mon Sep 17 00:00:00 2001 From: Simran Soin Date: Thu, 23 Jul 2020 10:18:16 -0400 Subject: [PATCH 06/10] Default NOT to false for all functions --- tools/sigma/backends/stix.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/sigma/backends/stix.py b/tools/sigma/backends/stix.py index f0d43393a..1c87725a8 100644 --- a/tools/sigma/backends/stix.py +++ b/tools/sigma/backends/stix.py @@ -36,7 +36,7 @@ class STIXBackend(SingleTextQueryBackend): else: return None - def generateORNode(self, node, currently_within_NOT_node): + def generateORNode(self, node, currently_within_NOT_node=False): generated = [self.generateNode(val, currently_within_NOT_node) for val in node] filtered = [g for g in generated if g is not None] if filtered: @@ -46,7 +46,7 @@ class STIXBackend(SingleTextQueryBackend): else: return None - def generateNOTNode(self, node, currently_within_NOT_node): + def generateNOTNode(self, node, currently_within_NOT_node=False): currently_within_NOT_node = True generated = self.generateNode(node.item, currently_within_NOT_node) if generated is not None: @@ -54,14 +54,14 @@ class STIXBackend(SingleTextQueryBackend): else: return None - def generateSubexpressionNode(self, node, currently_within_NOT_node): + def generateSubexpressionNode(self, node, currently_within_NOT_node=False): generated = self.generateNode(node.items, currently_within_NOT_node) if generated: return self.subExpression % generated else: return None - def generateMapItemNode(self, node, currently_within_NOT_node): + def generateMapItemNode(self, node, currently_within_NOT_node=False): fieldname, value = node transformed_fieldname = self.fieldNameMapping(fieldname, value) @@ -76,7 +76,7 @@ class STIXBackend(SingleTextQueryBackend): else: raise TypeError("Backend does not support map values of type " + str(type(value))) - def generateMapItemListNode(self, key, value, currently_within_NOT_node): + def generateMapItemListNode(self, key, value, currently_within_NOT_node=False): items_list = list() for item in value: if type(item) == str and "*" in item: @@ -107,7 +107,7 @@ class STIXBackend(SingleTextQueryBackend): else: raise NotImplementedError("Type modifier '{}' is not supported by backend".format(value.identifier)) - def generateMapItemNode(self, node, currently_within_NOT_node): + def generateMapItemNode(self, node, currently_within_NOT_node=False): key, value = node if ":" not in key: key = "%s:%s" % (self.sigmaSTIXObjectName, str(key).lower()) From ef9af3730a4d3b13f2df50a71fa540cd312300c9 Mon Sep 17 00:00:00 2001 From: Simran Soin Date: Thu, 23 Jul 2020 10:34:29 -0400 Subject: [PATCH 07/10] Remove unnecessary edits from qradar.py --- tools/sigma/backends/qradar.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/sigma/backends/qradar.py b/tools/sigma/backends/qradar.py index 825332215..f29024af1 100644 --- a/tools/sigma/backends/qradar.py +++ b/tools/sigma/backends/qradar.py @@ -58,14 +58,10 @@ class QRadarBackend(SingleTextQueryBackend): """Remove quotes in text""" return value.replace("\'","\\\'") - def generateNode(self, node, currently_within_NOT_node=False): + def generateNode(self, node): if type(node) == sigma.parser.condition.ConditionAND: - if currently_within_NOT_node: - return self.generateORNode(node) return self.generateANDNode(node) elif type(node) == sigma.parser.condition.ConditionOR: - if currently_within_NOT_node: - return self.generateANDNode(node) return self.generateORNode(node) elif type(node) == sigma.parser.condition.ConditionNOT: return self.generateNOTNode(node) From 6c7b4cf4083f01a2d3f5f8d86bc8f5b3b461010d Mon Sep 17 00:00:00 2001 From: Simran Soin Date: Thu, 23 Jul 2020 10:47:22 -0400 Subject: [PATCH 08/10] Revert additional change in base.py --- tools/sigma/backends/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sigma/backends/base.py b/tools/sigma/backends/base.py index 1840f1519..1ef7e175a 100644 --- a/tools/sigma/backends/base.py +++ b/tools/sigma/backends/base.py @@ -269,7 +269,7 @@ class SingleTextQueryBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): def generateNOTNode(self, node): generated = self.generateNode(node.item) if generated is not None: - return generated + return self.notToken + generated else: return None From c329f6412da54316ce4ae667cf58aa3d34805057 Mon Sep 17 00:00:00 2001 From: Simran Soin Date: Thu, 23 Jul 2020 11:47:55 -0400 Subject: [PATCH 09/10] Fix bug with NOT handling --- tools/sigma/backends/stix.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/sigma/backends/stix.py b/tools/sigma/backends/stix.py index 1c87725a8..c48b950e2 100644 --- a/tools/sigma/backends/stix.py +++ b/tools/sigma/backends/stix.py @@ -14,6 +14,7 @@ class STIXBackend(SingleTextQueryBackend): subExpression = "(%s)" valueExpression = "\'%s\'" mapExpression = "%s = %s" + notMapExpression = "%s != %s" mapListsSpecialHandling = True sigmaSTIXObjectName = "x-sigma" @@ -47,7 +48,7 @@ class STIXBackend(SingleTextQueryBackend): return None def generateNOTNode(self, node, currently_within_NOT_node=False): - currently_within_NOT_node = True + currently_within_NOT_node = not(currently_within_NOT_node) generated = self.generateNode(node.item, currently_within_NOT_node) if generated is not None: return generated @@ -66,6 +67,8 @@ class STIXBackend(SingleTextQueryBackend): transformed_fieldname = self.fieldNameMapping(fieldname, value) if self.mapListsSpecialHandling == False and type(value) in (str, int, list) or self.mapListsSpecialHandling == True and type(value) in (str, int): + if currently_within_NOT_node: + return self.notMapExpression % (transformed_fieldname, self.generateNode(value)) return self.mapExpression % (transformed_fieldname, self.generateNode(value)) elif type(value) == list: return self.generateMapItemListNode(transformed_fieldname, value, currently_within_NOT_node) @@ -118,6 +121,8 @@ class STIXBackend(SingleTextQueryBackend): return "%s NOT LIKE %s" % (self.cleanKey(key), self.generateValueNode(value)) return "%s LIKE %s" % (self.cleanKey(key), self.generateValueNode(value)) elif type(value) in (str, int): + if currently_within_NOT_node: + return self.notMapExpression % (self.cleanKey(key), self.generateValueNode(value)) return self.mapExpression % (self.cleanKey(key), self.generateValueNode(value)) elif type(value) == list: return self.generateMapItemListNode(key, value, currently_within_NOT_node) From 9643e01b54ceb230a1b1a3db4b7f3943409843d0 Mon Sep 17 00:00:00 2001 From: bar Date: Sun, 26 Jul 2020 12:16:48 +0300 Subject: [PATCH 10/10] extension should use '..' --- tools/config/stix-windows.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/config/stix-windows.yml b/tools/config/stix-windows.yml index 1083cbcef..6a9de243c 100644 --- a/tools/config/stix-windows.yml +++ b/tools/config/stix-windows.yml @@ -82,7 +82,7 @@ fieldmappings: Image: - process:image_ref.name ImageLoadedTempPath: - - process:extensions.windows-service-ext.service_dll_refs[*].x_temp_path + - process:extensions.'windows-service-ext'.service_dll_refs[*].x_temp_path ImageName: - process:image_ref.name ImagePath: @@ -99,9 +99,9 @@ fieldmappings: IntegrityLevel: - x-windows:integritylevel LoadedImage: - - process:extensions.windows-service-ext.service_dll_refs[*].name + - process:extensions.'windows-service-ext'.service_dll_refs[*].name LoadedImageName: - - process:extensions.windows-service-ext.service_dll_refs[*].name + - process:extensions.'windows-service-ext'.service_dll_refs[*].name LogonType: - x-windows:logontype MD5Hash: @@ -162,9 +162,9 @@ fieldmappings: SHA256Hash: - file:hashes.SHA-256 ServiceFileName: - - process:extensions.windows-service-ext.service_dll_refs[*].name + - process:extensions.'windows-service-ext'.service_dll_refs[*].name ServiceName: - - process:extensions.windows-service-ext.service_name + - process:extensions.'windows-service-ext'.service_name ShareName: - x-windows:sharename SharePath: @@ -231,9 +231,9 @@ fieldmappings: event_data.Image: - process:image_ref.name event_data.ImageLoaded: - - process:extensions.windows-service-ext.service_dll_refs[*].name + - process:extensions.'windows-service-ext'.service_dll_refs[*].name ImageLoaded: - - process:extensions.windows-service-ext.service_dll_refs[*].name + - process:extensions.'windows-service-ext'.service_dll_refs[*].name event_data.ImagePath: - process:image_ref.name event_data.ParentCommandLine: @@ -245,7 +245,7 @@ fieldmappings: event_data.PipeName: - x-windows:pipename event_data.ServiceFileName: - - process:extensions.windows-service-ext.service_dll_refs[*].name + - process:extensions.'windows-service-ext'.service_dll_refs[*].name event_data.ShareName: - x-windows:sharename event_data.Signature: