def _mitre_groups_technique_intersection_function(self, event, *args, **kwargs): """Function: For given Techniques return the Groups that are know to use all of them.""" try: # Get the wf_instance_id of the workflow this Function was called in wf_instance_id = event.message["workflow_instance"][ "workflow_instance_id"] # Get the function parameters: mitre_technique_name = kwargs.get("mitre_technique_name") # text mitre_technique_id = kwargs.get("mitre_technique_id") # text log = logging.getLogger(__name__) log.info("mitre_technique_name: %s", mitre_technique_name) log.info("mitre_technique_id: %s", mitre_technique_id) result_payload = ResultPayload( "fn_mitre_integration", mitre_technique_name=mitre_technique_name, mitre_technique_id=mitre_technique_id) if not mitre_technique_id and not mitre_technique_name: raise ValueError( "At least one of the inputs(mitre_technique_name or mitre_technique_id) " "should be provided.") yield StatusMessage("Getting technique information...") mitre_conn = mitre_attack.MitreAttackConnection() techniques = mitre_attack_utils.get_multiple_techniques( mitre_conn, mitre_technique_ids=mitre_technique_id, mitre_technique_names=mitre_technique_name) intersection_query = ",".join([t.id for t in techniques]) yield StatusMessage("Getting group intersection information...") groups = mitre_attack.MitreAttackGroup.get_by_technique_intersection( mitre_conn, techniques) if len(groups) == 0: yield StatusMessage( "No groups were found using all of the given techniques. Done" ) else: yield StatusMessage("Done. Returning results.") # Storing the techniques specified to query this group for group in groups: group.technique_id = intersection_query groups = [x.dict_form() for x in groups] # prepare the data for viewing results = {"mitre_groups": groups} # Produce a FunctionResult with the results yield FunctionResult(result_payload.done(True, results)) except Exception as e: yield FunctionError(e)
def _mitre_groups_using_technique_function(self, event, *args, **kwargs): """Function: Get a list of groups that are using the given technique(s).""" try: mitre_technique_name = kwargs.get("mitre_technique_name") # text mitre_technique_id = kwargs.get("mitre_technique_id") # text log = logging.getLogger(__name__) log.info("mitre_technique_name: %s", mitre_technique_name) log.info("mitre_technique_id: %s", mitre_technique_id) result_payload = ResultPayload( "fn_mitre_integration", mitre_technique_name=mitre_technique_name, mitre_technique_id=mitre_technique_id) if not mitre_technique_id and not mitre_technique_name: raise ValueError( "At least one of the inputs(mitre_technique_name or mitre_technique_id) " "should be provided.") yield StatusMessage("Getting technique information...") mitre_conn = mitre_attack.MitreAttackConnection( self.opts, self.options) techniques = mitre_attack_utils.get_multiple_techniques( mitre_conn, mitre_technique_ids=mitre_technique_id, mitre_technique_names=mitre_technique_name) yield StatusMessage("Getting group information...") groups = [] for technique in techniques: groups.extend( mitre_attack.MitreAttackGroup.get_by_technique( mitre_conn, technique)) if len(groups) == 0: yield StatusMessage( "No groups were found using any of the given techniques. Done." ) else: yield StatusMessage("Done. Returning results.") groups = [x.dict_form() for x in groups] # prepare the data for viewing results = {"mitre_groups": groups} # Produce a FunctionResult with the results yield FunctionResult(result_payload.done(True, results)) except Exception as e: log.exception(str(e)) yield FunctionError()
def _mitre_technique_information_function(self, event, *args, **kwargs): """Function: Get ATT&CK information about MITRE ATT&CK technique""" try: # Get the function parameters: mitre_technique_name = kwargs.get("mitre_technique_name") # text mitre_technique_id = kwargs.get("mitre_technique_id") # text mitre_technique_mitigation_only = kwargs.get("mitre_technique_mitigation_only") # boolean log = logging.getLogger(__name__) log.info("mitre_technique_name: %s", mitre_technique_name) log.info("mitre_technique_id: %s", mitre_technique_id) log.info("mitre_technique_mitigation_only: %s", mitre_technique_mitigation_only) if not mitre_technique_name and not mitre_technique_id: raise ValueError("Neither name nor id is provided for getting technique information.") result_payload = ResultPayload("fn_mitre_integration", mitre_technique_name=mitre_technique_name, mitre_technique_id=mitre_technique_id, mitre_technique_mitigation_only=mitre_technique_mitigation_only) yield StatusMessage("starting...") yield StatusMessage("querying MITRE STIX TAXII server. It might take several minutes...") mitre_conn = mitre_attack.MitreAttackConnection() techniques = mitre_attack.MitreAttackTechnique.get(mitre_conn, name=mitre_technique_name, id=mitre_technique_id) if not techniques: raise ValueError( "Technique with name/id {}/{} can't be found".format(mitre_technique_name, mitre_technique_id)) techs = [] for technique in techniques: tactics = technique.get_tactic(mitre_conn) tech_dict = technique.dict_form() tech_dict.update( { "tactic": ",".join(x.name for x in tactics) if tactics else None, # there should be 1 tactic per technique "mitre_mitigations": [x.dict_form() for x in technique.get_mitigations(mitre_conn)] } ) techs.append(tech_dict) yield StatusMessage("done...") results = { "mitre_techniques": techs } # Produce a FunctionResult with the results yield FunctionResult(result_payload.done(True, results)) except Exception as e: log.exception(str(e)) yield FunctionError()
def selftest_function(opts): """ Placeholder for selftest function. An example use would be to test package api connectivity. Suggested return values are be unimplemented, success, or failure. """ options = opts.get("fn_mitre_integration", {}) mitre_conn = mitre_attack.MitreAttackConnection() try: mitre_conn.connect_server() except Exception: return {"state": "failure"} if mitre_conn.composite_ds is not None: return {"state": "success"} return {"state": "failure"}
def _mitre_techniques_software_function(self, event, *args, **kwargs): """Function: Gets a list of software used by each of the techniques queried. For each, it will create a row in the corresponding data table for MITRE software.""" try: # Get the function parameters: mitre_technique_name = kwargs.get("mitre_technique_name") # text mitre_technique_id = kwargs.get("mitre_technique_id") # text log = logging.getLogger(__name__) log.info("mitre_technique_name: %s", mitre_technique_name) log.info("mitre_technique_id: %s", mitre_technique_id) result_payload = ResultPayload("fn_mitre_integration", mitre_technique_name=mitre_technique_name, mitre_technique_id=mitre_technique_id) if not mitre_technique_id and not mitre_technique_name: raise ValueError("At least one of the inputs(mitre_technique_name or mitre_technique_id) " "should be provided.") yield StatusMessage("starting...") yield StatusMessage("Getting technique information...") mitre_conn = mitre_attack.MitreAttackConnection(self.opts, self.options) if mitre_technique_id is not None: # Try id first, because it's less ambiguous technique_ids = mitre_technique_id.split(',') techniques = [] for t_id in technique_ids: technique = mitre_attack.MitreAttackTechnique.get_by_id(mitre_conn, t_id) if not technique: raise ValueError("Technique with id {} doesn't exist".format(t_id)) techniques.extend(technique) else: # It's possible for multiple tactics to have the same name # And we want to make sure that all of them are processed in that case technique_names = mitre_technique_name.split(',') techniques = [] for name in technique_names: technique = mitre_attack.MitreAttackTechnique.get_by_name(mitre_conn, name) if not technique: raise ValueError("Techniques with name {} don't exist".format(name)) techniques.extend(technique) yield StatusMessage("Getting software information...") software = [] for technique in techniques: software.extend(mitre_attack.MitreAttackSoftware.get_by_technique(mitre_conn, technique)) if len(software) == 0: yield StatusMessage("No software was found for the given techniques. Done.") else: yield StatusMessage("Done. Returning results.") software = [x.dict_form() for x in software] # prepare the data for viewing results = { "mitre_software": software } # Produce a FunctionResult with the results yield FunctionResult(result_payload.done(True, results)) except Exception as e: log.exception(str(e)) yield FunctionError()