From cbda88fcbb11a3200fff09e3b0698cc25dceeba5 Mon Sep 17 00:00:00 2001 From: Mei Liu Date: Tue, 8 Mar 2022 09:30:27 -0800 Subject: [PATCH] Example: -O: attackMapFile: It's used to set subFunction in XML rule. It's a map of subFunction and tags.attack in YML file. ruleIndex: It's used to set rule id in XML rule. The format of rule id is PH_Rule_{ruleType}_SIGMA_{ruleIndex} ruleType: It's used to set rule id in XML rule. 1. Generate rule for one YML file a. tools/sigmac -t fortisiem -c fortisiem-windows rules/windows/network_connection/win_net_python.yml b. tools/sigmac -t fortisiem -c fortisiem-windows -O attackMapFile=tools/config/fortisiem/MITRE-Attack-matrix.csv -O ruleIndex=0 -O ruleType=Windows rules/windows/network_connection/win_net_python.yml Output: Python Initiated Connection Python Initiated Connection true Adversaries may attempt to get a listing of services running on remote hosts, including those that may be vulnerable to remote software exploitation rules/windows/network_connection/win_net_python.yml compEventType = Filter.eventType,hostName = Filter.hostName,isInitialed = Filter.isInitialed,procName = Filter.procName eventType REGEXP ( "Win-Sysmon-3-Network-Connect.*" ) AND isInitialed="true" AND procName REGEXP ( ".*python.*" ) eventType,hostName,isInitialed,procName COUNT(*) >= 1 phRecvTime,hostName,isInitialed,procName,rawEventMsg 2. Generate rules for YML files under rules/windows a. tools/sigmac -t fortisiem -c fortisiem-windows -r rules/windows -o rule.xml b. tools/sigmac -t fortisiem -c fortisiem-windows -r rules/windows -O attackMapFile=tools/config/fortisiem/MITRE-Attack-matrix.csv -O ruleIndex=0 -O ruleType=Windows -o rule.xml Generate rules for YML files under rules/windows 3. Find files that is modified after some date. a. tools/sigmac --lists-files-after-date 2020/06/04 rules/windows/wmi_event/sysmon_wmi_susp_scripting.yml b. tools/sigmac --lists-files-after-date 2020/06/04 -r rules/windows/ Output: rules/windows/wmi_event/sysmon_wmi_susp_scripting.yml, Updated rules/windows/wmi_event/TestFile.yml, No date --- README.md | 1 + tools/sigma/backends/base.py | 7 +++++++ tools/sigma/backends/fortisiem.py | 10 ++++++++-- tools/sigma/sigmac.py | 4 ++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1215ea0c9..6271514d6 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,7 @@ tools/sigmac -t splunk -c ~/my-splunk-mapping.yml -c tools/config/generic/window * [Devo](https://devo.com) * [LogRhythm](https://logrhythm.com/) * [Datadog Logs](https://docs.datadoghq.com/logs/explorer/search_syntax/) +* [FortiSIEM](https://docs.fortinet.com) Current work-in-progress * [Splunk Data Models](https://docs.splunk.com/Documentation/Splunk/7.1.0/Knowledge/Aboutdatamodels) diff --git a/tools/sigma/backends/base.py b/tools/sigma/backends/base.py index ceb56f8f8..c12face60 100644 --- a/tools/sigma/backends/base.py +++ b/tools/sigma/backends/base.py @@ -228,6 +228,13 @@ class BaseBackend: def generateAfter(self, parsed): return "" + def initialize(self): + """ + Is called before the first file was processed with generate(). The right place if this backend is not intended to + look isolated at each rule, but generates an output which incorporates multiple rules, e.g. dashboards. + """ + pass + def finalize(self): """ Is called after the last file was processed with generate(). The right place if this backend is not intended to diff --git a/tools/sigma/backends/fortisiem.py b/tools/sigma/backends/fortisiem.py index ee4a45f4e..f7b65d798 100644 --- a/tools/sigma/backends/fortisiem.py +++ b/tools/sigma/backends/fortisiem.py @@ -81,6 +81,12 @@ class FortisemBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): self.setRuleType(backend_options) self.loadCSVfiles() self.loadMitreAttackMatrixFile(backend_options); + + def initialize(self): + return "" + + def finalize(self): + return "" # It's used to check whether the format of yml file is right. def ymlValidator(self, node,regdicts={}): @@ -634,9 +640,9 @@ class FortisemBackend(RulenameCommentMixin, BaseBackend, QuoteCharMixin): result = None if technique_str is not None: - result = ("") % (rulename, ruleId, sub_function_str, technique_str) + result = ("") % (rulename, ruleId, sub_function_str, technique_str) else: - result = ("") % (rulename, ruleId, sub_function_str) + result = ("") % (rulename, ruleId, sub_function_str) return result,ruleId,technique_str diff --git a/tools/sigma/sigmac.py b/tools/sigma/sigmac.py index d1f1bc3aa..055cbbd67 100755 --- a/tools/sigma/sigmac.py +++ b/tools/sigma/sigmac.py @@ -303,6 +303,10 @@ def main(): error = 0 output_array = [] + result = backend.initialize() + if result: + print(result, file=out) + for sigmafile in get_inputs(cmdargs.inputs, cmdargs.recurse): logger.debug("* Processing Sigma input %s" % (sigmafile)) success = True