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 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 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 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_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
def __init__( self, base_cti_path: Path = Path(__file__).parents[1] / "cti", log_path: Path = Path("~/riskmap.log").expanduser(), ) -> None: self.base_cti_path = base_cti_path self.log_path = log_path # Configure sources self.src = CompositeDataSource() self.src.add_data_source( FileSystemSource(base_cti_path / "enterprise-attack")) self.src.add_data_source( FileSystemSource(base_cti_path / "mobile-attack")) self.src.add_data_source(FileSystemSource(base_cti_path / "ics-attack")) self.src.add_data_source(FileSystemSource(base_cti_path / "capec")) logger.remove() logger.add(sink=self.log_path, format="{message}")
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' ] }
class attack_client(object): ENTERPRISE_COLLECTION = Collection(ATTCK_STIX_COLLECTIONS + ENTERPRISE_ATTCK + "/") PRE_COLLECTION = Collection(ATTCK_STIX_COLLECTIONS + PRE_ATTCK + "/") MOBILE_COLLECTION = Collection(ATTCK_STIX_COLLECTIONS + MOBILE_ATTCK + "/") TC_ENTERPRISE_SOURCE = TAXIICollectionSource(ENTERPRISE_COLLECTION) TC_PRE_SOURCE = TAXIICollectionSource(PRE_COLLECTION) TC_MOBILE_SOURCE = TAXIICollectionSource(MOBILE_COLLECTION) COMPOSITE_DS = CompositeDataSource() COMPOSITE_DS.add_data_sources( [TC_ENTERPRISE_SOURCE, TC_PRE_SOURCE, 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):
import re import requests from bs4 import BeautifulSoup from stix2 import TAXIICollectionSource from stix2 import Filter from stix2 import CompositeDataSource from taxii2client.v20 import Server # globals TAXII_SERVER = "https://cti-taxii.mitre.org/taxii/" SUCCESS = (200, ) DATA_SOURCE = None EXCLUDE_COLLECTIONS = ['PRE-ATT&CK'] CS = CompositeDataSource() def execute(method, url, payload=None, user=None, password=None): """ Execute rest api :param method: http method :param url: rest endpoint :param payload: body of request :param user: username for auth :param password: password for auth :return: """ headers = {'Content-Type': "text/html; charset=utf-8"} response = requests.request(method=method, url=url, auth=None,