mirror of
https://github.com/valitydev/SigmaHQ.git
synced 2024-11-06 17:35:19 +00:00
Parsing of detections
Transformation of detections into internal data structures. Parsing must be changed later to on-demand parsing because condition can change default behavior of lists.
This commit is contained in:
parent
3821e59db1
commit
ce43dce7ef
@ -3,7 +3,80 @@
|
||||
import yaml
|
||||
import re
|
||||
|
||||
COND_NONE = 0
|
||||
COND_AND = 1
|
||||
COND_OR = 2
|
||||
COND_NOT = 3
|
||||
|
||||
class SigmaParser:
|
||||
def __init__(self, sigma):
|
||||
self.definitions = dict()
|
||||
self.parsedyaml = yaml.safe_load(sigma)
|
||||
try:
|
||||
for definitionName in self.parsedyaml["detection"]:
|
||||
if definitionName in ("condition", "timeframe"): # skip non-identifiers here
|
||||
continue
|
||||
if definitionName in self.definitions:
|
||||
raise SigmaParseError("Definition '%s' was already defined" % (definitionName))
|
||||
self.definitions[definitionName] = self.parse_definition(self.parsedyaml["detection"][definitionName])
|
||||
except KeyError:
|
||||
raise SigmaParseError("No detection definitions found")
|
||||
|
||||
def parse_definition(self, definition, condOverride=None):
|
||||
if type(definition) not in (dict, list):
|
||||
raise SigmaParseError("Expected map or list, got type %s: '%s'" % (type(definition), str(definition)))
|
||||
|
||||
if type(definition) == list: # list of values or maps
|
||||
if condOverride: # condition given through rule detection condition, e.g. 1 of x
|
||||
cond = condOverride
|
||||
else: # no condition given, use default from spec
|
||||
cond = ConditionOR()
|
||||
|
||||
for value in definition:
|
||||
if type(value) in (str, int, dict):
|
||||
cond.add(value)
|
||||
else:
|
||||
raise SigmaParseError("Definition list may only contain plain values or maps")
|
||||
elif type(definition) == dict: # map
|
||||
cond = definition
|
||||
|
||||
return cond
|
||||
|
||||
class SigmaParseError(Exception):
|
||||
pass
|
||||
|
||||
### Parse Tree Node Classes ###
|
||||
class ConditionBase:
|
||||
"""Base class for conditional operations"""
|
||||
op = COND_NONE
|
||||
items = None
|
||||
|
||||
def __init__(self):
|
||||
raise NotImplementedError("ConditionBase is no usable class")
|
||||
|
||||
def add(self, item):
|
||||
self.items.append(item)
|
||||
|
||||
class ConditionAND(ConditionBase):
|
||||
"""AND Condition"""
|
||||
op = COND_AND
|
||||
|
||||
def __init__(self):
|
||||
self.items = list()
|
||||
|
||||
class ConditionOR(ConditionAND):
|
||||
"""OR Condition"""
|
||||
op = COND_OR
|
||||
|
||||
class ConditionNOT(ConditionBase):
|
||||
"""NOT Condition"""
|
||||
op = COND_NOT
|
||||
|
||||
def __init__(self):
|
||||
self.items = None
|
||||
|
||||
def add(self, item):
|
||||
if self.items == None:
|
||||
super.add(item)
|
||||
else:
|
||||
raise ValueError("Only one element allowed in NOT condition")
|
||||
|
@ -20,7 +20,7 @@ argparser = argparse.ArgumentParser(description="Convert Sigma rules into SIEM s
|
||||
argparser.add_argument("--recurse", "-r", help="Recurse into subdirectories")
|
||||
argparser.add_argument("--target", "-t", default="null", choices=backends.getBackendDict().keys(), help="Output target format")
|
||||
argparser.add_argument("--target-list", "-l", action="store_true", help="List available output target formats")
|
||||
argparser.add_argument("--fieldmapping", "-f", help="File with mappings between generic Sigma field names and configured field names (format: sigma_field: field1, field2, ...)")
|
||||
argparser.add_argument("--config", "-c", help="Configuration mit field name and index mapping for target environment")
|
||||
argparser.add_argument("--output", "-o", help="Output file or filename prefix if multiple files are generated")
|
||||
argparser.add_argument("--verbose", "-v", action="store_true", help="Be verbose")
|
||||
argparser.add_argument("--debug", "-d", action="store_true", help="Debugging output")
|
||||
@ -38,6 +38,7 @@ for sigmafile in cmdargs.inputs:
|
||||
f = open(sigmafile)
|
||||
parser = SigmaParser(f)
|
||||
print_debug(json.dumps(parser.parsedyaml, indent=2))
|
||||
#print_debug(json.dumps(parser.definitions, indent=2))
|
||||
except OSError as e:
|
||||
print("Failed to open Sigma file %s: %s" % (sigmafile, str(e)))
|
||||
except yaml.parser.ParserError as e:
|
||||
|
Loading…
Reference in New Issue
Block a user