def load_datasource(base=CTI_BASE): print("Loading CTI datasources map...") enterprise_attack_fs = FileSystemSource( os.path.join(base, "enterprise-attack")) mobile_attack_fs = FileSystemSource(os.path.join(base, "mobile-attack")) composite_ds = CompositeDataSource() composite_ds.add_data_sources([enterprise_attack_fs, mobile_attack_fs]) return composite_ds
def get_map(base=CTI_BASE): from stix2 import FileSystemSource, CompositeDataSource, Filter print("Loading CTI attack-pattern map...") enterprise_attack_fs = FileSystemSource( os.path.join(base, "enterprise-attack")) mobile_attack_fs = FileSystemSource(os.path.join(base, "mobile-attack")) composite_ds = CompositeDataSource() composite_ds.add_data_sources([enterprise_attack_fs, mobile_attack_fs]) filt = Filter('type', '=', 'attack-pattern') attack_map = {} for item in composite_ds.query(filt): name = item['name'] if item['revoked']: print( f"[WARN] Ignored {name.upper()}: This attack-pattern has been revoked." ) continue categories = [x['phase_name'] for x in item['kill_chain_phases']] desc = item['description'] platforms = item['x_mitre_platforms'] attack_id = None for er in item['external_references']: if er['source_name'] in [ "mitre-attack", "mobile-mitre-attack", "mitre-mobile-attack" ]: attack_id = er['external_id'] if attack_id: attack_map[attack_id] = { "name": name, "categories": categories, "description": desc, "platforms": platforms, "attack_id": attack_id } print(f"\tAdding {name.upper()} as ID: {attack_id}") else: print(f"[ERR] Ignored {name.upper()}: No attack ID found.") return attack_map
class attack_client(object): TC_ENTERPRISE_SOURCE = None TC_PRE_SOURCE = None TC_MOBILE_SOURCE = None COMPOSITE_DS = None def __init__(self, local_path=None): if local_path is not None and os.path.isdir(os.path.join(local_path, ENTERPRISE_ATTCK_LOCAL_DIR)) \ and os.path.isdir(os.path.join(local_path, PRE_ATTCK_LOCAL_DIR)) \ and os.path.isdir(os.path.join(local_path, MOBILE_ATTCK_LOCAL_DIR)): self.TC_ENTERPRISE_SOURCE = FileSystemSource( os.path.join(local_path, ENTERPRISE_ATTCK_LOCAL_DIR)) self.TC_PRE_SOURCE = FileSystemSource( os.path.join(local_path, PRE_ATTCK_LOCAL_DIR)) self.TC_MOBILE_SOURCE = FileSystemSource( os.path.join(local_path, MOBILE_ATTCK_LOCAL_DIR)) else: ENTERPRISE_COLLECTION = Collection(ATTCK_STIX_COLLECTIONS + ENTERPRISE_ATTCK + "/") PRE_COLLECTION = Collection(ATTCK_STIX_COLLECTIONS + PRE_ATTCK + "/") MOBILE_COLLECTION = Collection(ATTCK_STIX_COLLECTIONS + MOBILE_ATTCK + "/") self.TC_ENTERPRISE_SOURCE = TAXIICollectionSource( ENTERPRISE_COLLECTION) self.TC_PRE_SOURCE = TAXIICollectionSource(PRE_COLLECTION) self.TC_MOBILE_SOURCE = TAXIICollectionSource(MOBILE_COLLECTION) self.COMPOSITE_DS = CompositeDataSource() self.COMPOSITE_DS.add_data_sources([ self.TC_ENTERPRISE_SOURCE, self.TC_PRE_SOURCE, self.TC_MOBILE_SOURCE ]) def translate_stix_objects(self, stix_objects): technique_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "object_marking_refs": "object_marking_refs", "name": "technique", "description": "technique_description", "kill_chain_phases": "tactic", "x_mitre_detection": "technique_detection", "x_mitre_platforms": "platform", "x_mitre_data_sources": "data_sources", "x_mitre_defense_bypassed": "defense_bypassed", "x_mitre_permissions_required": "permissions_required", "x_mitre_effective_permissions": "effective_permissions", "x_mitre_system_requirements": "system_requirements", "x_mitre_network_requirements": "network_requirements", "x_mitre_remote_support": "remote_support", "x_mitre_contributors": "contributors", "x_mitre_detectable_by_common_defenses": "detectable_by_common_defenses", "x_mitre_detectable_by_common_defenses_explanation": "detectable_explanation", "x_mitre_difficulty_for_adversary": "difficulty_for_adversary", "x_mitre_difficulty_for_adversary_explanation": "difficulty_explanation", "x_mitre_tactic_type": "tactic_type", "x_mitre_impact_type": "impact_type", "external_references": "external_references" } mitigation_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "name": "mitigation", "description": "mitigation_description", "external_references": "external_references", "x_mitre_old_attack_id": "old_mitigation_id" } group_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "name": "group", "description": "group_description", "aliases": "group_aliases", "external_references": "external_references", "x_mitre_contributors": "contributors" } software_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "name": "software", "description": "software_description", "labels": "software_labels", "x_mitre_aliases": "software_aliases", "x_mitre_platforms": "software_platform", "external_references": "external_references", "x_mitre_contributors": "contributors", "x_mitre_old_attack_id": "old_software_id" } relationship_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "relationship_type": "relationship", "description": "relationship_description", "source_ref": "source_object", "target_ref": "target_object" } tactic_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "object_marking_refs": "object_marking_refs", "name": "tactic", "description": "tactic_description", "x_mitre_shortname": "tactic_shortname", "external_references": "external_references" } matrix_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "modified": "modified", "object_marking_refs": "object_marking_refs", "name": "matrix", "description": "matrix_description", "tactic_refs": "tactic_references", "external_references": "external_references" } identity_stix_mapping = { "type": "type", "id": "id", "created_by_ref": "created_by_ref", "created": "created", "definition_type": "marking_definition_type", "definition": "marking_definition" } marking_stix_mapping = { "type": "type", "id": "id", "created": "created", "modified": "modified", "object_marking_refs": "object_marking_refs", "name": "identity", "identity_class": "identity_class" } # ******** Helper Functions ******** def handle_list(list_object, object_type): if object_type == "external_references": obj_dict['url'] = list_object[0]['url'] obj_dict['matrix'] = list_object[0]['source_name'] if obj_dict['type'] == 'attack-pattern': for ref in list_object: if ref['source_name'] == 'capec': obj_dict['capec_id'] = ref['external_id'] obj_dict['capec_url'] = ref['url'] obj_dict['technique_id'] = list_object[0]['external_id'] elif obj_dict['type'] == 'course-of-action': obj_dict['mitigation_id'] = list_object[0]['external_id'] elif obj_dict['type'] == 'group': obj_dict['group_id'] = list_object[0]['external_id'] elif obj_dict['type'] == 'software': obj_dict['software_id'] = list_object[0]['external_id'] elif obj_dict['type'] == 'tactic': obj_dict['tactic_id'] = list_object[0]['external_id'] elif obj_dict['type'] == 'matrix': obj_dict['matrix_id'] = list_object[0]['external_id'] elif object_type == "kill_chain_phases": tactic_list = list() for phase in list_object: tactic_list.append(phase['phase_name']) obj_dict['tactic'] = tactic_list stix_objects_list = list() for obj in stix_objects: if isinstance(obj, dict): obj_dict = obj else: obj_dict = json.loads( obj.serialize()) # From STIX to Python Dict dict_keys = list(obj_dict.keys()) for key in dict_keys: if obj['type'] == "attack-pattern": stix_mapping = technique_stix_mapping elif obj['type'] == "course-of-action": stix_mapping = mitigation_stix_mapping elif obj['type'] == "intrusion-set": stix_mapping = group_stix_mapping elif obj['type'] == "malware" or obj['type'] == "tool": stix_mapping = software_stix_mapping elif obj['type'] == "relationship": stix_mapping = relationship_stix_mapping elif obj['type'] == "x-mitre-tactic": stix_mapping = tactic_stix_mapping elif obj['type'] == "x-mitre-matrix": stix_mapping = matrix_stix_mapping elif obj['type'] == "identity": stix_mapping = identity_stix_mapping elif obj['type'] == "marking-definition": stix_mapping = marking_stix_mapping else: exit if key in stix_mapping.keys(): if key == "external_references" or key == "kill_chain_phases": handle_list(obj_dict[key], key) else: new_key = stix_mapping[key] obj_dict[new_key] = obj_dict.pop(key) stix_objects_list.append(obj_dict) return stix_objects_list def remove_revoked(self, stix_objects, extract=False): handle_revoked = list() for obj in stix_objects: if 'revoked' in obj.keys() and obj['revoked'] == True: if extract: handle_revoked.append(obj) else: continue handle_revoked.append(obj) return handle_revoked # ******** Enterprise ATT&CK Technology Domain ******* def get_enterprise(self, stix_format=True): enterprise_filter_objects = { "techniques": Filter("type", "=", "attack-pattern"), "mitigations": Filter("type", "=", "course-of-action"), "groups": Filter("type", "=", "intrusion-set"), "malware": Filter("type", "=", "malware"), "tools": Filter("type", "=", "tool"), "relationships": Filter("type", "=", "relationship"), "tactics": Filter("type", "=", "x-mitre-tactic"), "matrix": Filter("type", "=", "x-mitre-matrix"), "identity": Filter("type", "=", "identity"), "marking-definition": Filter("type", "=", "marking-definition") } enterprise_stix_objects = {} for key in enterprise_filter_objects: enterprise_stix_objects[key] = (self.TC_ENTERPRISE_SOURCE.query( enterprise_filter_objects[key])) if not stix_format: enterprise_stix_objects[key] = self.translate_stix_objects( enterprise_stix_objects[key]) return enterprise_stix_objects def get_enterprise_techniques(self, stix_format=True): enterprise_techniques = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "attack-pattern")) if not stix_format: enterprise_techniques = self.translate_stix_objects( enterprise_techniques) return enterprise_techniques def get_enterprise_mitigations(self, stix_format=True): enterprise_mitigations = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "course-of-action")) if not stix_format: enterprise_mitigations = self.translate_stix_objects( enterprise_mitigations) return enterprise_mitigations def get_enterprise_groups(self, stix_format=True): enterprise_groups = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "intrusion-set")) if not stix_format: enterprise_groups = self.translate_stix_objects(enterprise_groups) return enterprise_groups def get_enterprise_malware(self, stix_format=True): enterprise_malware = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "malware")) if not stix_format: enterprise_malware = self.translate_stix_objects( enterprise_malware) return enterprise_malware def get_enterprise_tools(self, stix_format=True): enterprise_tools = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "tool")) if not stix_format: enterprise_tools = self.translate_stix_objects(enterprise_tools) return enterprise_tools def get_enterprise_relationships(self, stix_format=True): enterprise_relationships = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "relationship")) if not stix_format: enterprise_relationships = self.translate_stix_objects( enterprise_relationships) return enterprise_relationships def get_enterprise_tactics(self, stix_format=True): enterprise_tactics = self.TC_ENTERPRISE_SOURCE.query( Filter("type", "=", "x-mitre-tactic")) if not stix_format: enterprise_tactics = self.translate_stix_objects( enterprise_tactics) return enterprise_tactics # ******** Pre ATT&CK Domain ******* def get_pre(self, stix_format=True): pre_filter_objects = { "techniques": Filter("type", "=", "attack-pattern"), "groups": Filter("type", "=", "intrusion-set"), "relationships": Filter("type", "=", "relationship"), "tactics": Filter("type", "=", "x-mitre-tactic"), "matrix": Filter("type", "=", "x-mitre-matrix"), "identity": Filter("type", "=", "identity"), "marking-definition": Filter("type", "=", "marking-definition") } pre_stix_objects = {} for key in pre_filter_objects: pre_stix_objects[key] = self.TC_PRE_SOURCE.query( pre_filter_objects[key]) if not stix_format: pre_stix_objects[key] = self.translate_stix_objects( pre_stix_objects[key]) return pre_stix_objects def get_pre_techniques(self, stix_format=True): pre_techniques = self.TC_PRE_SOURCE.query( Filter("type", "=", "attack-pattern")) if not stix_format: pre_techniques = self.translate_stix_objects(pre_techniques) return pre_techniques def get_pre_groups(self, stix_format=True): pre_groups = self.TC_PRE_SOURCE.query( Filter("type", "=", "intrusion-set")) if not stix_format: pre_groups = self.translate_stix_objects(pre_groups) return pre_groups def get_pre_relationships(self, stix_format=True): pre_relationships = self.TC_PRE_SOURCE.query( Filter("type", "=", "relationship")) if not stix_format: pre_relationships = self.translate_stix_objects(pre_relationships) return pre_relationships def get_pre_tactics(self, stix_format=True): pre_tactics = self.TC_PRE_SOURCE.query( Filter("type", "=", "x-mitre-tactic")) if not stix_format: pre_tactics = self.translate_stix_objects(pre_tactics) return pre_tactics # ******** Mobile ATT&CK Technology Domain ******* def get_mobile(self, stix_format=True): mobile_filter_objects = { "techniques": Filter("type", "=", "attack-pattern"), "mitigations": Filter("type", "=", "course-of-action"), "groups": Filter("type", "=", "intrusion-set"), "malware": Filter("type", "=", "malware"), "tools": Filter("type", "=", "tool"), "relationships": Filter("type", "=", "relationship"), "tactics": Filter("type", "=", "x-mitre-tactic"), "matrix": Filter("type", "=", "x-mitre-matrix"), "identity": Filter("type", "=", "identity"), "marking-definition": Filter("type", "=", "marking-definition") } mobile_stix_objects = {} for key in mobile_filter_objects: mobile_stix_objects[key] = self.TC_MOBILE_SOURCE.query( mobile_filter_objects[key]) if not stix_format: mobile_stix_objects[key] = self.translate_stix_objects( mobile_stix_objects[key]) return mobile_stix_objects def get_mobile_techniques(self, stix_format=True): mobile_techniques = self.TC_MOBILE_SOURCE.query( Filter("type", "=", "attack-pattern")) if not stix_format: mobile_techniques = self.translate_stix_objects(mobile_techniques) return mobile_techniques def get_mobile_mitigations(self, stix_format=True): mobile_mitigations = self.TC_MOBILE_SOURCE.query( Filter("type", "=", "course-of-action")) if not stix_format: mobile_mitigations = self.translate_stix_objects( mobile_mitigations) return mobile_mitigations def get_mobile_groups(self, stix_format=True): mobile_groups = self.TC_MOBILE_SOURCE.query( Filter("type", "=", "intrusion-set")) if not stix_format: mobile_groups = self.translate_stix_objects(mobile_groups) return mobile_groups def get_mobile_malware(self, stix_format=True): mobile_malware = self.TC_MOBILE_SOURCE.query( Filter("type", "=", "malware")) if not stix_format: mobile_malware = self.translate_stix_objects(mobile_malware) return mobile_malware def get_mobile_tools(self, stix_format=True): mobile_tools = self.TC_MOBILE_SOURCE.query(Filter("type", "=", "tool")) if not stix_format: mobile_tools = self.translate_stix_objects(mobile_tools) return mobile_tools def get_mobile_relationships(self, stix_format=True): mobile_relationships = self.TC_MOBILE_SOURCE.query( Filter("type", "=", "relationship")) if not stix_format: mobile_relationships = self.translate_stix_objects( mobile_relationships) return mobile_relationships def get_mobile_tactics(self, stix_format=True): mobile_tactics = self.TC_MOBILE_SOURCE.query( Filter("type", "=", "x-mitre-tactic")) if not stix_format: mobile_tactics = self.translate_stix_objects(mobile_tactics) return mobile_tactics # ******** Get All Functions ******** def get_stix_objects(self, stix_format=True): enterprise_objects = self.get_enterprise() pre_objects = self.get_pre() mobile_objects = self.get_mobile() for keypre in pre_objects.keys(): for preobj in pre_objects[keypre]: if keypre in enterprise_objects.keys(): if preobj not in enterprise_objects[keypre]: enterprise_objects[keypre].append(preobj) for keymob in mobile_objects.keys(): for mobobj in mobile_objects[keymob]: if keymob in enterprise_objects.keys(): if mobobj not in enterprise_objects[keymob]: enterprise_objects[keymob].append(mobobj) if not stix_format: for enterkey in enterprise_objects.keys(): enterprise_objects[enterkey] = self.translate_stix_objects( enterprise_objects[enterkey]) return enterprise_objects def get_techniques(self, stix_format=True): all_techniques = self.COMPOSITE_DS.query( Filter("type", "=", "attack-pattern")) if not stix_format: all_techniques = self.translate_stix_objects(all_techniques) return all_techniques def get_groups(self, stix_format=True): all_groups = self.COMPOSITE_DS.query( Filter("type", "=", "intrusion-set")) if not stix_format: all_groups = self.translate_stix_objects(all_groups) return all_groups def get_mitigations(self, stix_format=True): enterprise_mitigations = self.get_enterprise_mitigations() mobile_mitigations = self.get_mobile_mitigations() for mm in mobile_mitigations: if mm not in enterprise_mitigations: enterprise_mitigations.append(mm) if not stix_format: enterprise_mitigations = self.translate_stix_objects( enterprise_mitigations) return enterprise_mitigations def get_software(self, stix_format=True): enterprise_malware = self.get_enterprise_malware() enterprise_tools = self.get_enterprise_tools() mobile_malware = self.get_mobile_malware() mobile_tools = self.get_mobile_tools() for mt in mobile_tools: if mt not in enterprise_tools: enterprise_tools.append(mt) for mmal in mobile_malware: if mmal not in enterprise_malware: enterprise_malware.append(mmal) all_software = enterprise_tools + enterprise_malware if not stix_format: all_software = self.translate_stix_objects(all_software) return all_software def get_relationships(self, stix_format=True): all_relationships = self.COMPOSITE_DS.query( Filter("type", "=", "relationship")) if not stix_format: all_relationships = self.translate_stix_objects(all_relationships) return all_relationships def get_tactics(self, stix_format=True): all_tactics = self.COMPOSITE_DS.query( Filter("type", "=", "x-mitre-tactic")) if not stix_format: all_tactics = self.translate_stix_objects(all_tactics) return all_tactics # ******** Custom Functions ******** def get_technique_by_name(self, name, case=True, stix_format=True):
class MitreAttack: """ Simple class that controls access to Mitre Att&ck datasets. """ DEFAULT_SERVER = "https://cti-taxii.mitre.org/taxii/" def __init__(self): self._api_root = None self._server = None self._source = None self._frames = {} def _get_frame_from_collection(self, collection): """ Returns a DataFrame with information from a Mitre Att&ck collection. """ data = collection.get_objects() lines = [] for item in data.get('objects', []): line = item external = item.get('external_references', []) for source in external: if not source.get("url", "").startswith("https://attack.mitre.org"): continue line["mitre_source"] = source.get("source_name") line["mitre_id"] = source.get("external_id") url = source.get("url") url_items = url.split("/") line["mitre_collection"] = url_items[-2] lines.append(line) return pd.DataFrame(lines) @property def server(self): """ Returns a copy of the Mitre server object. """ if self._server: return self._server self._server = Server(self.DEFAULT_SERVER) self._api_root = self._server.api_roots[0] return self._server @property def collection_titles(self): """ Returns a list of collection titles and ID that are available. """ _ = self.server return [(c.title, c.id) for c in self._api_root.collections] @property def source(self): """ Returns the data source object for Att&ck data. """ if self._source: return self._source self._source = CompositeDataSource() self._source.add_data_sources(self._api_root.collections) return self._source def get_collection(self, collection_title): """ Returns a DataFrame with the content of a particular collection. :param str collection_title: The tile or a substring of a collection entry in Mitre Att&ck framework. The first match of available collections will be used. :return: A pandas DataFrame with the content or an empty frame if the collection was not found. """ _ = self.server for collection in self._api_root.collections: if collection_title.lower() not in collection.title.lower(): continue title = collection.title if title not in self._frames: self._frames[title] = self._get_frame_from_collection( collection) return self._frames[title] return pd.DataFrame() def get_technique(self, mitre_id, collection_title='Enterprise ATT&CK'): """ Returns a pandas Series with the content of a single technique. :param str mitre_id: This is the corresponding Mitre Att&ck ID for the technique to look up. :param str collection_title: The title of the collection this particular technique exists in. By default uses the Enterprise collection. :return: A pandas Series with the information, or an empty series if not found. """ titles = [x[0] for x in self.collection_titles] use_title = "" for title in titles: if collection_title.lower() in title.lower(): use_title = title break if not use_title: raise ValueError("Collection Title %s not found", collection_title) if use_title not in self._frames: _ = self.get_collection(use_title) frame = self._frames.get(use_title) frame_slice = frame[frame.mitre_id == mitre_id.upper()] if not frame_slice.empty: return frame_slice.iloc[0].dropna() return pd.Series()
class MitreAttackConnection(object): """ Collection of methods for extracting data from MitreServer. Includes the logic of using multiple data sources. """ def __init__(self, opts=None, function_opts=None): self.attack_server = None self.composite_ds = None self.proxies = RequestsCommon(opts, function_opts).get_proxies() def connect_server(self, url=None): """ Allow user to specify what url to use :param url: :return: """ server_url = MITRE_TAXII_URL if url is None else url self.attack_server = Server(server_url, proxies=self.proxies) api_root = self.attack_server.api_roots[0] # CompositeSource to query all the collections at once c_sources = [ TAXIICollectionSource(collection) for collection in api_root.collections ] self.composite_ds = CompositeDataSource() self.composite_ds.add_data_sources(c_sources) def get_items(self, filters): """ Get items using filters, convert them to dictionaries. Reference: https://github.com/mitre/cti/blob/master/USAGE.md :param filters: list of filter :return: list of dictionaries representing stix objects :rtype: list(dict) """ if self.attack_server is None: self.connect_server() items = [] for data_source in self.composite_ds.get_all_data_sources(): try: ds_items = data_source.query(filters) updated_items = [ MitreAttackBase.object_to_dict(x) for x in ds_items ] for item in updated_items: item["collection"] = data_source.collection.title items.extend(updated_items) except DataSourceError as e: # happens if data_source finds no elements with given filter pass return items def get_related_to(self, *args, **kwargs): """ Facade for `related_to` of composite data source. Needed to abstract out DataSource from classes using AttackMitre. :return: objects with the provided relationships """ if self.attack_server is None: self.connect_server() return self.composite_ds.related_to(*args, **kwargs) def lookup_item(self, item_name, type_name="attack-pattern"): """ Look up items using item name :param item_name: :param collection_title: :param type_name: :return: """ query_filter = Filter("type", "=", type_name) name_filter = Filter("name", "=", item_name) items = self.get_items([query_filter, name_filter]) if not len(items): return None return items
class MitreParser: """This class wraps all the function for interacting with the MitreAtt&ck Repository""" def __init__(self, cti_folder): self.cti_folder = cti_folder repo = Repo(cti_folder) origin = repo.remotes.origin try: origin.pull() except Exception as e: pass enterprise_attack_fs = FileSystemSource(cti_folder + "enterprise-attack") pre_attack_fs = FileSystemSource(cti_folder + "pre-attack") mobile_attack_fs = FileSystemSource(cti_folder + "mobile-attack") self.src = CompositeDataSource() self.src.add_data_sources( [enterprise_attack_fs, pre_attack_fs, mobile_attack_fs]) # self.columns_list = {"techniques":['mitre_id', 'name', 'description', 'permissions_required', 'platforms', 'adversary-opsec', 'build-capabilities', 'collection', 'command-and-control', 'compromise', 'credential-access', 'defense-evasion', 'discovery', 'effects', 'establish-&-maintain-infrastructure', 'execution', 'exfiltration', 'impact', 'initial-access', 'lateral-movement', 'launch', 'network-effects', 'organizational-information-gathering', 'organizational-weakness-identification', 'people-information-gathering', 'people-weakness-identification', 'persistence', 'persona-development', 'priority-definition-direction', 'priority-definition-planning', 'privilege-escalation', 'remote-service-effects', 'stage-capabilities', 'target-selection', 'technical-information-gathering', 'technical-weakness-identification', 'test-capabilities','kill_chain_phases']} self.columns_list = { "techniques": [ 'mitre_id', 'tactics', 'name', 'permissions_required', 'platforms' ] } def get_technique_by_group(self, stix_id): relations = self.src.relationships(stix_id, 'uses', source_only=True) return self.src.query([ Filter('type', '=', 'attack-pattern'), Filter('id', 'in', [r.target_ref for r in relations]) ]) def get_malware_by_group(self, stix_id): relations = self.src.relationships(stix_id, 'uses', source_only=True) query_malware = self.src.query([ Filter('type', '=', 'malware'), Filter('id', 'in', [r.target_ref for r in relations]) ]) dict_malware = [] for group in query_malware: string_report = group.serialize() dict_report = json.loads(string_report) dict_malware.append(dict_report) df_malware = pd.DataFrame(dict_malware) return df_malware def get_tool_by_group(self, stix_id): relations = self.src.relationships(stix_id, 'uses', source_only=True) query_tool = self.src.query([ Filter('type', '=', 'tool'), Filter('id', 'in', [r.target_ref for r in relations]) ]) dict_tool = [] for group in query_tool: string_report = group.serialize() dict_report = json.loads(string_report) dict_tool.append(dict_report) df_tool = pd.DataFrame(dict_tool) return df_tool def get_techniques_by_group(self, stix_id): group_uses = [ r for r in self.src.relationships(stix_id, 'uses', source_only=True) if get_type_from_id(r.target_ref) in ['malware', 'tool'] ] software_uses = self.src.query([ Filter('type', '=', 'relationship'), Filter('relationship_type', '=', 'uses'), Filter('source_ref', 'in', [r.source_ref for r in group_uses]) ]) techniques_query = self.src.query([ Filter('type', '=', 'attack-pattern'), Filter('id', 'in', [r.target_ref for r in software_uses]) ]) dict_techniques = [] for current_technique in techniques_query: string_report = current_technique.serialize() dict_report = json.loads(string_report) dict_techniques.append(dict_report) techniques_df = pd.DataFrame(dict_techniques) if techniques_df.empty: return techniques_df techniques_df = techniques_df.fillna("") techniques_df["kill_chain_phases"] = techniques_df[ "kill_chain_phases"].apply(lambda x: [ y["phase_name"] for y in x if 'mitre' in y['kill_chain_name'] ]) techniques_df = techniques_df.rename( index=str, columns={ "x_mitre_permissions_required": "permissions_required", "x_mitre_platforms": "platforms", "id": "mitre_id", "kill_chain_phases": "tactics" }) column_set = set(techniques_df.columns.values) for i in self.columns_list["techniques"]: column_set.add(i) techniques_df = techniques_df.reindex(columns=list(column_set), fill_value="") return techniques_df[self.columns_list["techniques"]] def get_group_by_alias(self, alias): return self.src.query([ Filter('type', '=', 'intrusion-set'), Filter('aliases', '=', alias) ]) def get_all_groups(self): filt = Filter('type', '=', 'intrusion-set') groups = self.src.query([filt]) dict_groups = [] for group in groups: string_report = group.serialize() dict_report = json.loads(string_report) hash_report = hashlib.sha1( string_report.encode('utf-8')).hexdigest() dict_report["hash"] = hash_report dict_groups.append(dict_report) group_df = pd.DataFrame(dict_groups) group_df = group_df.fillna("") return group_df def get_all_techniques(self): technique_query = self.src.query(Filter('type', '=', 'attack-pattern')) dict_techniques = [] for current_technique in technique_query: string_report = current_technique.serialize() dict_report = json.loads(string_report) dict_techniques.append(dict_report) techniques_df = pd.DataFrame(dict_techniques) techniques_df = techniques_df.fillna("") techniques_df["kill_chain_phases"] = techniques_df[ "kill_chain_phases"].apply(lambda x: [ y["phase_name"] for y in x if 'mitre' in y['kill_chain_name'] ]) techniques_df = techniques_df.rename( index=str, columns={ "x_mitre_permissions_required": "permissions_required", "x_mitre_platforms": "platforms", "id": "mitre_id" }) return techniques_df[self.columns_list["techniques"]] def get_all_tactics(self): tactic_query = self.src.query(Filter('type', '=', 'x-mitre-tactic')) tactics_df = pd.DataFrame(tactic_query) return tactics_df