From 8b8100611c94229accc2aad58c80ebb93f5524b2 Mon Sep 17 00:00:00 2001 From: Christophe Vandeplas Date: Wed, 20 Dec 2023 11:29:33 +0100 Subject: [PATCH] new: [code] MISP Galaxy supports most models --- CODE/generate_DISARM_MISP_galaxy.py | 261 ++++++++++++++++++++++++---- CODE/generate_DISARM_pages.py | 3 + 2 files changed, 232 insertions(+), 32 deletions(-) diff --git a/CODE/generate_DISARM_MISP_galaxy.py b/CODE/generate_DISARM_MISP_galaxy.py index 2906e54..a1783f6 100755 --- a/CODE/generate_DISARM_MISP_galaxy.py +++ b/CODE/generate_DISARM_MISP_galaxy.py @@ -12,55 +12,60 @@ import json import uuid import os +DISARM_DESCRIPTION = 'DISARM is a framework designed for describing and understanding disinformation incidents.' +DISARM_CATEGORY = 'disarm' +DISARM_AUTHORS = ['DISARM Project'] +DISARM_SOURCE = 'https://github.com/DISARMFoundation/DISARMframeworks' +CORE_UUID = "9d6bd9d2-2cd3-4900-b61a-06cd64df3996" class DisarmGalaxy: def __init__(self, out_path=os.path.join('..', '..', 'misp-galaxy')): self.disarm = Disarm() self.out_path = out_path - def generate_disarm_galaxy(self): - galaxy = {'name': 'DISARM Techniques', - 'type': 'disarm', - 'description': 'DISARM is a framework designed for describing and understanding disinformation incidents.', - 'uuid': str(uuid.uuid5(uuid.UUID("9319371e-2504-4128-8410-3741cebbcfd3"), 'disarm-galaxy-techniques')), - 'version': 1, - 'icon': 'map', - 'namespace': 'disarm', - 'kill_chain_order': { - 'disarm-tactics': [] - }} - - for k, v in self.disarm.tactics.items(): - galaxy['kill_chain_order']['disarm-tactics'].append(f'{v}') - - self.write_json_file(os.path.join(self.out_path, 'galaxies', 'disarm-techniques.json'), galaxy) - def write_json_file(self, fname, file_data): with open(fname, 'w') as f: json.dump(file_data, f, indent=2, sort_keys=True, ensure_ascii=False) f.write('\n') - def generate_disarm_clusters(self): - cluster = {'authors': ['DISARM Project'], - 'category': 'disarm', - 'description': 'DISARM is a framework designed for describing and understanding disinformation incidents.', - 'name': 'DISARM Techniques', - 'source': 'https://github.com/misinfosecproject/amitt_framework', - 'type': 'disarm', - 'uuid': str(uuid.uuid5(uuid.UUID("9319371e-2504-4128-8410-3741cebbcfd3"), 'disarm-cluster-techniques')), + def generate_disarm_techniques_galaxy(self): + galaxy = {'name': 'Techniques', + 'type': 'disarm-techniques', + 'description': DISARM_DESCRIPTION, + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-galaxy-techniques')), + 'version': 1, + 'icon': 'map', + 'namespace': 'disarm', + 'kill_chain_order': { + 'tactics': [] + }} + + for k, v in self.disarm.tactics.items(): + galaxy['kill_chain_order']['tactics'].append(f'{v}') + + self.write_json_file(os.path.join(self.out_path, 'galaxies', 'disarm-techniques.json'), galaxy) + + def generate_disarm_techniques_clusters(self): + cluster = {'authors': DISARM_AUTHORS, + 'category': DISARM_CATEGORY, + 'description': DISARM_DESCRIPTION, + 'name': 'Techniques', + 'source': DISARM_SOURCE, + 'type': 'disarm-techniques', + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-cluster-techniques')), 'values': [], 'version': 1} values = [] df = self.disarm.df_techniques for i in range(len(df)): t = { - 'uuid': str(uuid.uuid5(uuid.UUID("9319371e-2504-4128-8410-3741cebbcfd3"), df.values[i][0])), - 'value': f"{df.values[i][1]}", + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), df.values[i][0])), + 'value': df.values[i][1], 'description': df.values[i][4], 'meta': { 'external_id': df.values[i][0], 'kill_chain': [ - f'disarm-tactics:{self.disarm.tactics[df.values[i][3]]}' + f'tactics:{self.disarm.tactics[df.values[i][3]]}' ], 'refs': [ f'https://github.com/DISARMFoundation/DISARMframeworks/blob/main/generated_pages/techniques/{df.values[i][0]}.md' @@ -72,14 +77,206 @@ class DisarmGalaxy: cluster['values'] = sorted(values, key=lambda x: x['meta']['external_id']) self.write_json_file(os.path.join(self.out_path, 'clusters', 'disarm-techniques.json'), cluster) - pass + def generate_disarm_countermeasures_galaxy(self): + galaxy = {'name': 'Countermeasures', + 'type': 'disarm-countermeasures', + 'description': DISARM_DESCRIPTION, + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-galaxy-counters')), + 'version': 1, + 'icon': 'shield-alt', + 'namespace': 'disarm', + 'kill_chain_order': { + 'tactics': [], + 'responsetypes': [], + 'metatechniques': [] + }} + + for k, v in self.disarm.tactics.items(): + galaxy['kill_chain_order']['tactics'].append(f'{v}') + for k, v in self.disarm.responsetypes.items(): + galaxy['kill_chain_order']['responsetypes'].append(f'{v}') + for k, v in self.disarm.metatechniques.items(): + galaxy['kill_chain_order']['metatechniques'].append(f'{v}') + + self.write_json_file(os.path.join(self.out_path, 'galaxies', 'disarm-countermeasures.json'), galaxy) + + def generate_disarm_countermeasures_clusters(self): + cluster = {'authors': DISARM_AUTHORS, + 'category': DISARM_CATEGORY, + 'description': DISARM_DESCRIPTION, + 'name': 'Countermeasures', + 'source': DISARM_SOURCE, + 'type': 'disarm-countermeasures', + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-cluster-counters')), + 'values': [], + 'version': 1} + values = [] + df = self.disarm.df_counters + for i in range(len(df)): + kill_chain = [] + if self.disarm.tactics[df.values[i][15]]: + kill_chain.append(f'tactics:{self.disarm.tactics[df.values[i][15]]}') + if self.disarm.responsetypes[df.values[i][10]]: + kill_chain.append(f'responsetypes:{self.disarm.responsetypes[df.values[i][10]]}') + if self.disarm.metatechniques[df.values[i][17]]: + kill_chain.append(f'metatechniques:{self.disarm.metatechniques[df.values[i][17]]}') + + t = { + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), df.values[i][0])), + 'value': df.values[i][1], + 'description': df.values[i][3], + 'meta': { + 'external_id': df.values[i][0], + 'kill_chain': kill_chain, + 'refs': [ + f'https://github.com/DISARMFoundation/DISARMframeworks/blob/main/generated_pages/counters/{df.values[i][0]}.md' + ] + } + } + + values.append(t) + cluster['values'] = sorted(values, key=lambda x: x['meta']['external_id']) + self.write_json_file(os.path.join(self.out_path, 'clusters', 'disarm-countermeasures.json'), cluster) + + def generate_disarm_detections_galaxy(self): + galaxy = {'name': 'Detections', + 'type': 'disarm-detections', + 'description': DISARM_DESCRIPTION, + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-galaxy-detections')), + 'version': 1, + 'icon': 'bell', + 'namespace': 'disarm', + 'kill_chain_order': { + 'tactics': [], + 'responsetypes': [], + # 'metatechniques': [] + }} + + for k, v in self.disarm.tactics.items(): + galaxy['kill_chain_order']['tactics'].append(f'{v}') + for k, v in self.disarm.responsetypes.items(): + galaxy['kill_chain_order']['responsetypes'].append(f'{v}') + # for k, v in self.disarm.metatechniques.items(): + # galaxy['kill_chain_order']['metatechniques'].append(f'{v}') + + self.write_json_file(os.path.join(self.out_path, 'galaxies', 'disarm-detections.json'), galaxy) + + def generate_disarm_detections_clusters(self): + cluster = {'authors': DISARM_AUTHORS, + 'category': DISARM_CATEGORY, + 'description': DISARM_DESCRIPTION, + 'name': 'Detections', + 'source': DISARM_SOURCE, + 'type': 'disarm-detections', + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-cluster-detections')), + 'values': [], + 'version': 1} + values = [] + df = self.disarm.df_detections + for i in range(len(df)): + + kill_chain = [] + try: + if self.disarm.tactics[df.values[i][14]]: + kill_chain.append(f'tactics:{self.disarm.tactics[df.values[i][14]]}') + except KeyError: + pass + try: + if self.disarm.responsetypes[df.values[i][10]]: + kill_chain.append(f'responsetypes:{self.disarm.responsetypes[df.values[i][10]]}') + except KeyError: + pass + # Metatechnique ID is not in the array + # if self.disarm.metatechniques[df.values[i][???]]: + # kill_chain.append(f'metatechniques:{self.disarm.metatechniques[df.values[i][???]]}') + + t = { + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), df.values[i][0])), + 'value': df.values[i][1], + 'description': df.values[i][3], + 'meta': { + 'external_id': df.values[i][0], + 'kill_chain': kill_chain, + 'refs': [ + f'https://github.com/DISARMFoundation/DISARMframeworks/blob/main/generated_pages/detections/{df.values[i][0]}.md' + ] + } + } + + values.append(t) + cluster['values'] = sorted(values, key=lambda x: x['meta']['external_id']) + self.write_json_file(os.path.join(self.out_path, 'clusters', 'disarm-detections.json'), cluster) + + + def generate_disarm_actortypes_galaxy(self): + galaxy = {'name': 'Actor Types', + 'type': 'disarm-actortypes', + 'description': DISARM_DESCRIPTION, + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-galaxy-actortypes')), + 'version': 1, + 'icon': 'user-secret', + 'namespace': 'disarm', + 'kill_chain_order': { + 'sectors': [] + }} + + for k, v in self.disarm.sectors.items(): + galaxy['kill_chain_order']['sectors'].append(f'{v}') + + self.write_json_file(os.path.join(self.out_path, 'galaxies', 'disarm-actortypes.json'), galaxy) + + def generate_disarm_actortypes_clusters(self): + cluster = {'authors': DISARM_AUTHORS, + 'category': DISARM_CATEGORY, + 'description': DISARM_DESCRIPTION, + 'name': 'Actor Types', + 'source': DISARM_SOURCE, + 'type': 'disarm-actortypes', + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), 'disarm-cluster-actortypes')), + 'values': [], + 'version': 1} + values = [] + df = self.disarm.df_actortypes + for i in range(len(df)): + + kill_chain = [] + try: + sectors = df.values[i][3].split(',') + for sector in sectors: + sector = sector.strip() + if self.disarm.sectors[sector]: + kill_chain.append(f'sectors:{self.disarm.sectors[sector]}') + except KeyError: + pass + + t = { + 'uuid': str(uuid.uuid5(uuid.UUID(CORE_UUID), df.values[i][0])), + 'value': df.values[i][1], + 'description': df.values[i][2], + 'meta': { + 'external_id': df.values[i][0], + 'kill_chain': kill_chain, + 'refs': [ + f'https://github.com/DISARMFoundation/DISARMframeworks/blob/main/generated_pages/actortypes/{df.values[i][0]}.md' + ] + } + } + + values.append(t) + cluster['values'] = sorted(values, key=lambda x: x['meta']['external_id']) + self.write_json_file(os.path.join(self.out_path, 'clusters', 'disarm-actortypes.json'), cluster) def main(): disarm_galaxy = DisarmGalaxy() - disarm_galaxy.generate_disarm_galaxy() - disarm_galaxy.generate_disarm_clusters() - + disarm_galaxy.generate_disarm_techniques_galaxy() + disarm_galaxy.generate_disarm_techniques_clusters() + disarm_galaxy.generate_disarm_countermeasures_galaxy() + disarm_galaxy.generate_disarm_countermeasures_clusters() + disarm_galaxy.generate_disarm_detections_galaxy() + disarm_galaxy.generate_disarm_detections_clusters() + disarm_galaxy.generate_disarm_actortypes_galaxy() + disarm_galaxy.generate_disarm_actortypes_clusters() if __name__ == "__main__": main() diff --git a/CODE/generate_DISARM_pages.py b/CODE/generate_DISARM_pages.py index 18f2c41..93df35f 100644 --- a/CODE/generate_DISARM_pages.py +++ b/CODE/generate_DISARM_pages.py @@ -123,6 +123,7 @@ class Disarm: self.it = self.create_incident_technique_crosstable(metadata['incidenttechniques']) self.df_tactics = metadata['tactics'] self.df_playbooks = metadata['playbooks'] + self.df_sectors = metadata['sectors'] # Add columns containing lists of techniques and counters to the tactics dataframe self.df_techniques_per_tactic = self.df_techniques.groupby('tactic_id')['disarm_id'].apply(list).reset_index().rename({'disarm_id':'technique_ids'}, axis=1) @@ -136,8 +137,10 @@ class Disarm: self.techniques = self.make_object_dictionary(self.df_techniques) self.counters = self.make_object_dictionary(self.df_counters) self.metatechniques = self.make_object_dictionary(self.df_metatechniques) + self.responsetypes = self.make_object_dictionary(self.df_responsetypes) self.actortypes = self.make_object_dictionary(self.df_actortypes) self.resources = self.make_object_dictionary(self.df_resources) + self.sectors = self.make_object_dictionary(self.df_sectors) # Create the data table for each framework file self.num_tactics = len(self.df_tactics)