diff --git a/CODE/DISARM-STIX2/main.py b/CODE/DISARM-STIX2/main.py index 5c6f320..a791b96 100644 --- a/CODE/DISARM-STIX2/main.py +++ b/CODE/DISARM-STIX2/main.py @@ -11,7 +11,7 @@ from stix2 import (Bundle, AttackPattern, ThreatActor, IntrusionSet, Relationshi from stix2.properties import (ReferenceProperty, ListProperty, StringProperty, TimestampProperty, BooleanProperty, IntegerProperty) import helpers -from objects import tactic, technique, matrix, bundle +from objects import tactic, technique, matrix, bundle, relationship from helpers import xlsx, file @@ -25,18 +25,19 @@ def generate_disarm_stix(): tactics = tactic.make_disarm_tactics(data) techniques = technique.make_disarm_techniques(data) + subtechniques = technique.make_disarm_subtechniques(data) + subtechnique_relationships = relationship.make_disarm_subtechnique_relationships(techniques, subtechniques) navigator_matrix = matrix.make_disarm_matrix(tactics) stix_objects = [] stix_objects.append(tactics) stix_objects.append(techniques) + stix_objects.append(subtechniques) + stix_objects.append(subtechnique_relationships) stix_objects.append(navigator_matrix) stix_objects = [item for sublist in stix_objects for item in sublist] - # for i in stix_objects: - # print(i) - disarm_bundle = bundle.make_stix_bundle(stix_objects) helpers.file.clean_output_dir() @@ -44,6 +45,5 @@ def generate_disarm_stix(): helpers.file.write_bundle(disarm_bundle, "DISARM") - if __name__ == "__main__": generate_disarm_stix() \ No newline at end of file diff --git a/CODE/DISARM-STIX2/objects/matrix.py b/CODE/DISARM-STIX2/objects/matrix.py index 33d0214..2685ee2 100644 --- a/CODE/DISARM-STIX2/objects/matrix.py +++ b/CODE/DISARM-STIX2/objects/matrix.py @@ -34,11 +34,6 @@ def make_disarm_matrix(tactics): ] name = 'DISARM Framework' - # print(tactics) - # p =[i.id for i in tactics] - # r = properties.ReferenceProperty() - # f = properties.ListProperty(r) - tactic_refs = [i.id for i in tactics] matrix = Matrix( diff --git a/CODE/DISARM-STIX2/objects/relationship.py b/CODE/DISARM-STIX2/objects/relationship.py index 2d6d81a..bba7fbb 100644 --- a/CODE/DISARM-STIX2/objects/relationship.py +++ b/CODE/DISARM-STIX2/objects/relationship.py @@ -19,3 +19,27 @@ def make_disarm_subtechnique_relationship(source, target): ) return relationship + + +def make_disarm_subtechnique_relationships(techniques, subtechniques): + """Creates a map of technique and sub-technique. + + Args: + techniques (list): List of STIX2 technique objects. + subtechniques (list): List of STIX2 subtechnique objects. + + Returns: + A Relationship object. + + """ + technique_ids = {} + for technique in techniques: + technique_ids[technique["external_references"][0]["external_id"]] = technique["id"] + + relationships = [] + for subtechnique in subtechniques: + technique_id = technique_ids[subtechnique["external_references"][0]["external_id"].split(".")[0]] + relationship = make_disarm_subtechnique_relationship(subtechnique["id"], technique_id) + relationships.append(relationship) + + return relationships diff --git a/CODE/DISARM-STIX2/objects/tactic.py b/CODE/DISARM-STIX2/objects/tactic.py index 357a874..46619ff 100644 --- a/CODE/DISARM-STIX2/objects/tactic.py +++ b/CODE/DISARM-STIX2/objects/tactic.py @@ -3,6 +3,11 @@ from stix2 import CustomObject, properties, ExternalReference import objects.marking_definition from objects import identity, marking_definition +valid_tactics = ["plan-strategy", "plan-objectives", "microtarget", "develop-content", + "select-channels-and-affordances", "conduct-pump-priming", "deliver-content", + "drive-offline-activity", "persist-in-the-information-environment", "assess-effectiveness", + "target-audience-analysis", "develop-narratives", "establish-social-assets", "establish-legitimacy", + "maximize-exposure", "drive-online-harms"] @CustomObject('x-mitre-tactic', [ ('name', properties.StringProperty(required=True)), @@ -12,14 +17,8 @@ from objects import identity, marking_definition ]) class Tactic(object): def __init__(self, x_mitre_shortname=None, **kwargs): - if x_mitre_shortname and x_mitre_shortname not in ["strategic-planning", "objective-planning", - "develop-people", "develop-persona", - "develop-networks", "microtargeting", "develop-content", - "channel-selection", "pump-priming", "exposure", - "go-physical", - "persistence", "measure-effectiveness"]: - # raise ValueError("'%s' is not a recognized DISARM Tactic." % x_mitre_shortname) - print("'%s' is not a recognized DISARM Tactic." % x_mitre_shortname) + if x_mitre_shortname and x_mitre_shortname not in valid_tactics: + raise ValueError("'%s' is not a recognized DISARM Tactic." % x_mitre_shortname) def make_disarm_tactics(data): @@ -54,4 +53,3 @@ def make_disarm_tactics(data): tactics.append(tactic) return tactics - diff --git a/CODE/DISARM-STIX2/objects/technique.py b/CODE/DISARM-STIX2/objects/technique.py index b1cc6c2..7dfa2a5 100644 --- a/CODE/DISARM-STIX2/objects/technique.py +++ b/CODE/DISARM-STIX2/objects/technique.py @@ -19,7 +19,7 @@ def make_disarm_techniques(data): for t in data["techniques"].values.tolist(): external_references = [ { - 'external_id': f'{t[0]}', + 'external_id': f'{t[0]}'.strip(), 'source_name': 'DISARM', 'url': f'https://github.com/DISARMFoundation/DISARM_framework/blob/master/techniques/{t[0]}.md' } @@ -50,7 +50,7 @@ def make_disarm_techniques(data): kill_chain_phases=kill_chain_phases, custom_properties={ 'x_mitre_platforms': x_mitre_platforms, - 'x_mitre_version': "1,0", + 'x_mitre_version': "1.0", 'x_mitre_is_subtechnique': x_mitre_is_subtechnique } ) @@ -59,13 +59,57 @@ def make_disarm_techniques(data): return techniques -def make_subtechnique_map(techinques): +def make_disarm_subtechniques(data): """ Args: - techinques: + data: The xlsx subtechnique sheet. Returns: """ - pass \ No newline at end of file + tacdict = pd.Series(data["tactics"].name.values, index=data["tactics"].disarm_id).to_dict() + techdict = pd.Series(data["techniques"].tactic_id.values, index=data["techniques"].disarm_id).to_dict() + + subtechniques = [] + for t in data["subtechniques"].values.tolist(): + external_references = [ + { + 'external_id': f'{t[0]}'.strip(), + 'source_name': 'DISARM', + 'url': f'https://github.com/DISARMFoundation/DISARM_framework/blob/master/techniques/{t[0]}.md' + } + ] + + kill_chain_phases = [ + { + 'phase_name': tacdict[techdict[t[2]]].replace(' ', '-').lower(), + 'kill_chain_name': 'mitre-attack' + } + ] + + subtechnique = t[0].split(".") + x_mitre_is_subtechnique = False + if len(subtechnique) > 1: + x_mitre_is_subtechnique = True + + # MITRE ATT&CK Navigator expect techniques to have at least one of these platforms. + # Without one, the technique will not render in the Navigator. + x_mitre_platforms = 'Windows', 'Linux', 'Mac' + + technique = AttackPattern( + name=f"{t[1]}", + description=f"{t[3]}", + external_references=external_references, + object_marking_refs=objects.marking_definition.make_disarm_marking_definition(), + created_by_ref=objects.identity.make_disarm_identity(), + kill_chain_phases=kill_chain_phases, + custom_properties={ + 'x_mitre_platforms': x_mitre_platforms, + 'x_mitre_version': "1.0", + 'x_mitre_is_subtechnique': x_mitre_is_subtechnique + } + ) + + subtechniques.append(technique) + return subtechniques \ No newline at end of file