Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump PySigma and update Microsoft XDR and Microsoft Sentinel #20

Merged
merged 7 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PyYAML==6.0.1
pySigma==0.11.10
pySigma==0.11.17
ruamel.yaml==0.18.1
azure-common==1.1.28
azure-core==1.30.1
Expand Down
26 changes: 26 additions & 0 deletions src/droid/platforms/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Module holding common functions for the platforms
"""

def get_pipeline_group_match(rule_content: dict, fields: dict):
"""Retrieve the config group name based on a dict

Return: a str with the pipeline config group
"""

sigma_logsource_fields = ['category', 'product', 'service']
rule_logsource = {}

for key, value in rule_content['logsource'].items():
if key in sigma_logsource_fields:
rule_logsource[key] = value

for key, value in fields.items():
value = {k: v for k, v in value.items() if k in sigma_logsource_fields}
if value == rule_logsource:
group_match = key
break
else:
group_match = None

return group_match
42 changes: 29 additions & 13 deletions src/droid/platforms/ms_xdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pprint import pprint
from droid.abstracts import AbstractPlatform
from droid.color import ColorLogger
from droid.platforms.common import get_pipeline_group_match
from msal import ConfidentialClientApplication
from azure.identity import DefaultAzureCredential

Expand All @@ -24,6 +25,9 @@ def __init__(self, parameters: dict, logger_param: dict, export_mssp: bool=False
self._parameters = parameters
self._export_mssp = export_mssp

if 'query_period_groups' in self._parameters['rule_parameters']:
self._query_period_groups = self._parameters['rule_parameters']['query_period_groups']

if "query_period" not in self._parameters:
raise Exception(
'MicrosoftXDRPlatform: "query_period" parameter is required.'
Expand Down Expand Up @@ -205,6 +209,24 @@ def acquire_token(self, tenant_id=None):
)
exit()

def process_query_period(self, query_period: str, rule_file: str):
"""Process the query period time
:return: a query period time
"""
if query_period.upper() in [
"0",
"1H",
"3H",
"12H",
"24H",
]:
return query_period.upper()
else:
self.logger.error(
f"Sigma Query Period must be one of '0', '1H', '3H', '12H' or '24H', used value provided in the config {self._query_period} - {rule_file}"
)
raise

def create_rule(self, rule_content, rule_converted, rule_file):
"""
Create an Custom Detection Rule in Microsoft XDR
Expand Down Expand Up @@ -291,21 +313,15 @@ def create_rule(self, rule_content, rule_converted, rule_file):
except Exception as e:
self.logger.error(e)

if 'query_period_groups' in self._parameters['rule_parameters']:
query_period_group = get_pipeline_group_match(rule_content, self._query_period_groups)
if query_period_group:
self.logger.debug(f"Applying the query_period value from group {query_period_group}")
alert_rule["schedule"]["period"] = self.process_query_period(self._query_period_groups[query_period_group]['query_period'], rule_file)

if "custom" in rule_content:
if "query_period" in rule_content["custom"]:
query_period = rule_content["custom"]["query_period"].upper()
if query_period in [
"0",
"1H",
"3H",
"12H",
"24H",
]:
alert_rule["schedule"]["period"] = query_period
else:
self.logger.error(
f"Sigma Query Period must be one of '0', '1H', '3H', '12H' or '24H', used value provided in the config {self._query_period} - {rule_file}"
)
alert_rule["schedule"]["period"] = self.process_query_period(rule_content["custom"]["query_period"], rule_file)
if "actions" in rule_content["custom"]:
responseActions = self.parse_actions(
rule_content["custom"]["actions"], rule_file=rule_file
Expand Down
13 changes: 13 additions & 0 deletions src/droid/platforms/sentinel.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,19 @@ def create_rule(self, rule_content, rule_converted, rule_file):
techniques=self.mitre_techniques(rule_content)
)

if rule_content.get('custom', {}).get('disabled') is True:
alert_rule.enabled = False
self.logger.info(f"Successfully disabled the rule {rule_file}", extra={
"rule_file": rule_file, "rule_converted": rule_converted,
"rule_content": rule_content}
)

if rule_content.get("custom", {}).get("query_frequency"):
alert_rule.query_frequency = timedelta(hours=rule_content["custom"]["query_frequency"])

if rule_content.get("custom", {}).get("query_period"):
alert_rule.query_period = timedelta(hours=rule_content["custom"]["query_period"])

if self._export_mssp:
if self._export_list_mssp:
self.logger.info("Exporting to designated customers")
Expand Down
30 changes: 3 additions & 27 deletions src/droid/platforms/splunk.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from time import sleep
from droid.color import ColorLogger
from droid.abstracts import AbstractPlatform
from droid.platforms.common import get_pipeline_group_match
from splunklib.binding import AuthenticationError

class SplunkPlatform(AbstractPlatform):
Expand Down Expand Up @@ -150,32 +151,6 @@ def remove_rule(self, rule_content: dict, rule_converted: str, rule_file: str):
else:
self.logger.info(f"Saved search for rule {rule_file} already deleted", extra={"rule_file": rule_file, "rule_converted": rule_converted, "rule_content": rule_content})


def get_suppress_config_group(self, rule_content: dict):
"""Retrieve the suppress config group name

Return: a str with the pipeline config group
"""

sigma_logsource_fields = ['category', 'product', 'service']
rule_logsource = {}

for key, value in rule_content['logsource'].items():
if key in sigma_logsource_fields:
rule_logsource[key] = value

for key, value in self._suppress_fields_groups.items():
value = {k: v for k, v in value.items() if k in sigma_logsource_fields}
if value == rule_logsource:
self.logger.info(f"Suppress config found: {key}")
group_match = key
break
else:
group_match = None

return group_match


def get_rule(self, rule_content: dict, rule_converted: str, rule_file: str):

alert_name = rule_content["title"]
Expand Down Expand Up @@ -248,8 +223,9 @@ def create_rule(self, rule_content: dict, rule_converted: str, rule_file: str):
alert_config['cron_schedule'] = custom_config["cron_schedule"]

if 'suppress_fields_groups' in self._parameters['savedsearch_parameters']:
suppress_config_group = self.get_suppress_config_group(rule_content)
suppress_config_group = get_pipeline_group_match(rule_content, self._suppress_fields_groups)
if suppress_config_group:
self.logger.debug(f"Applying the suppress fields from group {suppress_config_group}")
alert_config['alert.suppress.fields'] = self._suppress_fields_groups[suppress_config_group]['alert.suppress.fields']
alert_config.pop('suppress_fields_groups')

Expand Down
4 changes: 2 additions & 2 deletions tests/files/raw-rules/convert_valid_splunk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ status: experimental
description: Rule to fetch the alerts from Azure (Defender for Cloud)
references:
author: pizza53
date: 2022/05/05
modified: 2022/05/05
date: 2022-05-05
modified: 2022-05-05
tags:
- attack.privilege_escalation
- attack.t1053.002
Expand Down
4 changes: 2 additions & 2 deletions tests/files/sigma-rules/invalid/convert_invalid_rule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ description: Detects the use of process_lezgo2.pl
references:
- https://ref.pizza-planet.local/ref2
author: pizza53
date: 2022/01/24
modified: 2023/02/14
date: 2022-01-24
modified: 2023-02-14
tags:
- attack.execution
- attack.t1569
Expand Down
4 changes: 2 additions & 2 deletions tests/files/sigma-rules/invalid/invalid_rule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ references:
- https://www.snip2code.com/Snippet/4397378/UAC-bypass-using-EditionUpgradeManager-C/
- https://gist.github.com/hfiref0x/de9c83966623236f5ebf8d9ae2407611
author: pizza53
date: 2023/11/06
modified: 2023/11/06
date: 2023-11-06
modified: 2023-11-06
tags:
- attack.defense_evasion
- attack.privilege_escalation
Expand Down
4 changes: 2 additions & 2 deletions tests/files/sigma-rules/valid/convert_valid_rule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ references:
- https://www.d7xtech.com/free-software/runx/
- https://www.winhelponline.com/blog/run-program-as-system-localsystem-account-windows/
author: pizza53
date: 2022/01/24
modified: 2023/02/14
date: 2022-01-24
modified: 2023-02-14
tags:
- attack.execution
- attack.t1569.002
Expand Down