From 3dd942d9ddaf7fa2f745629ae8dc4f575d915373 Mon Sep 17 00:00:00 2001 From: Stephen Lincoln Date: Thu, 26 Sep 2024 13:57:03 -0400 Subject: [PATCH] Implemented base hash value transformation --- sigma/pipelines/sentinelasim/mappings.py | 4 +- sigma/pipelines/sentinelasim/sentinelasim.py | 46 ++++++++++++++----- .../pipelines/sentinelasim/transformations.py | 28 +++++++++++ 3 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 sigma/pipelines/sentinelasim/transformations.py diff --git a/sigma/pipelines/sentinelasim/mappings.py b/sigma/pipelines/sentinelasim/mappings.py index 3603a33..983429a 100644 --- a/sigma/pipelines/sentinelasim/mappings.py +++ b/sigma/pipelines/sentinelasim/mappings.py @@ -35,6 +35,8 @@ "registry_event": next((table for table in table_names if "registry" in table.lower()), "imRegistry"), "registry_set": next((table for table in table_names if "registry" in table.lower()), "imRegistry"), "network_connection": next((table for table in table_names if "network" in table.lower()), "imNetworkSession"), + "proxy": next((table for table in table_names if "web" in table.lower()), "imWebSession"), + "webserver": next((table for table in table_names if "web" in table.lower()), "imWebSession"), } ## Rule Categories -> RuleConditions @@ -169,7 +171,6 @@ class SentinelASIMFieldMappings(FieldMappings): "LogonId": "ActorSessionId", "TargetObject": "TargetFilePath", "Details": "TargetFilePath", - "Hashes": ["TargetFileMD5", "TargetFileSHA1", "TargetFileSHA256", "TargetFileSHA512"], "SubjectUserName": "ActorUsername", "ObjectName": "TargetFilePath", "OldFilePath": "SrcFilePath", @@ -259,7 +260,6 @@ class SentinelASIMFieldMappings(FieldMappings): "ParentProcessGuid": ["ParentProcessGuid", "ActingProcessGuid"], "ParentUser": "ActorUsername", "IntegrityLevel": "TargetProcessIntegrityLevel", - "Hashes": ["TargetProcessMD5", "TargetProcessSHA1", "TargetProcessSHA256", "TargetProcessSHA512"], "ParentProcessName": "ParentProcessName", "CurrentDirectory": "TargetProcessCurrentDirectory", "OriginalFileName": ["TargetProcessFileOriginalName", "TargetProcessFilename"], diff --git a/sigma/pipelines/sentinelasim/sentinelasim.py b/sigma/pipelines/sentinelasim/sentinelasim.py index ad0093f..c34421e 100644 --- a/sigma/pipelines/sentinelasim/sentinelasim.py +++ b/sigma/pipelines/sentinelasim/sentinelasim.py @@ -21,17 +21,20 @@ from ..kusto_common.transformations import ( DynamicFieldMappingTransformation, GenericFieldMappingTransformation, - HashesValuesTransformation, RegistryActionTypeValueTransformation, SetQueryTableStateTransformation, ) from .mappings import ( - CATEGORY_TO_CONDITIONS_MAPPINGS, CATEGORY_TO_TABLE_MAPPINGS, SENTINEL_ASIM_FIELD_MAPPINGS, ) from .schema import SentinelASIMSchema from .tables import SENTINEL_ASIM_TABLES +from .transformations import ( + FileEventHashesValuesTransformation, + ProcessCreateHashesValuesTransformation, + WebSessionHashesValuesTransformation, +) SENTINEL_ASIM_SCHEMA = create_schema(SentinelASIMSchema, SENTINEL_ASIM_TABLES) @@ -92,10 +95,24 @@ transformation=RegistryActionTypeValueTransformation(), field_name_conditions=[IncludeFieldCondition(["EventType"])], ), + # Processing item to transform the Hashes field in the SecurityEvent table to get rid of the hash algorithm prefix in each value + ProcessingItem( + identifier="sentinel_asim_processcreate_hashes_field_values", + transformation=ProcessCreateHashesValuesTransformation(), + field_name_conditions=[IncludeFieldCondition(["Hashes"])], + rule_conditions=[RuleProcessingStateCondition("query_table", "imProcessCreate")], + ), + ProcessingItem( + identifier="sentinel_asim_fileevent_hashes_field_values", + transformation=FileEventHashesValuesTransformation(), + field_name_conditions=[IncludeFieldCondition(["Hashes"])], + rule_conditions=[RuleProcessingStateCondition("query_table", "imFileEvent")], + ), ProcessingItem( - identifier="sentinel_asim_hashes_field_values", - transformation=HashesValuesTransformation(), + identifier="sentinel_asim_webrequest_hashes_field_values", + transformation=WebSessionHashesValuesTransformation(), field_name_conditions=[IncludeFieldCondition(["Hashes"])], + rule_conditions=[RuleProcessingStateCondition("query_table", "imWebSession")], ), # Processing item to essentially ignore initiated field ProcessingItem( @@ -106,15 +123,20 @@ ), ] -## Exceptions/Errors ProcessingItems +# Exceptions/Errors ProcessingItems +# Catch-all for when the query table is not set, meaning the rule could not be mapped to a table or the table name was not set rule_error_proc_items = [ - # Category Not Supported + # Category Not Supported or Query Table Not Set ProcessingItem( - identifier="sentinel_asim_unsupported_rule_category", - rule_condition_linking=any, - transformation=RuleFailureTransformation("Rule category not yet supported by the Sentinel ASIM pipeline."), - rule_condition_negation=True, - rule_conditions=[x for x in CATEGORY_TO_CONDITIONS_MAPPINGS.values()], + identifier="sentinel_asim_unsupported_rule_category_or_missing_query_table", + transformation=RuleFailureTransformation( + "Rule category not yet supported by the Sentinel ASIM pipeline or query_table is not set." + ), + rule_conditions=[ + RuleProcessingItemAppliedCondition("sentinel_asim_set_query_table"), + RuleProcessingStateCondition("query_table", None), + ], + rule_condition_linking=all, ) ] @@ -193,7 +215,7 @@ def sentinel_asim_pipeline( ] return ProcessingPipeline( - name="Generic Log Sources to Windows 365 Defender Transformation", + name="Generic Log Sources to Sentinel ASIM tables and fields", priority=10, items=pipeline_items, allowed_backends=frozenset(["kusto"]), diff --git a/sigma/pipelines/sentinelasim/transformations.py b/sigma/pipelines/sentinelasim/transformations.py new file mode 100644 index 0000000..e8fb726 --- /dev/null +++ b/sigma/pipelines/sentinelasim/transformations.py @@ -0,0 +1,28 @@ +from ..kusto_common.transformations import BaseHashesValuesTransformation + + +class ProcessCreateHashesValuesTransformation(BaseHashesValuesTransformation): + """ + Transforms the Hashes field in imProcessCreate table to get rid of the hash algorithm prefix in each value. + """ + + def __init__(self): + super().__init__(valid_hash_algos=["MD5", "SHA1", "SHA256", "SHA512", "IMPHASH"], field_prefix="TargetProcess") + + +class FileEventHashesValuesTransformation(BaseHashesValuesTransformation): + """ + Transforms the Hashes field in imFileEvent table to get rid of the hash algorithm prefix in each value. + """ + + def __init__(self): + super().__init__(valid_hash_algos=["MD5", "SHA1", "SHA256", "SHA512"], field_prefix="TargetFile") + + +class WebSessionHashesValuesTransformation(BaseHashesValuesTransformation): + """ + Transforms the Hashes field in imWebSession table to get rid of the hash algorithm prefix in each value. + """ + + def __init__(self): + super().__init__(valid_hash_algos=["MD5", "SHA1", "SHA256", "SHA512"], field_prefix="File")