def render_template(self, template_type): """Description template_type: - "markdown" - "confluence" """ if template_type not in ["markdown", "confluence"]: raise Exception("Bad template_type. Available values:" + " [\"markdown\", \"confluence\"]") # Point to the templates directory env = Environment(loader=FileSystemLoader('templates')) # Get proper template if template_type == "markdown": template = env.get_template( 'markdown_mitigationpolicies_template.md.j2') platform = self.mp_parsed_file.get("platform") if isinstance(platform, str): platform = [platform] self.mp_parsed_file.update({'platform': platform}) minimum_version = self.mp_parsed_file.get("minimum_version") if isinstance(minimum_version, str): minimum_version = [minimum_version] self.mp_parsed_file.update({'minimum_version': minimum_version}) mitigation_systems = self.mp_parsed_file.get("mitigation_system") if isinstance(mitigation_systems, str): mitigation_systems = [mitigation_systems] self.mp_parsed_file.update( {'mitigation_system': mitigation_systems}) self.mp_parsed_file.update({ 'configuration': self.mp_parsed_file.get('configuration').strip() }) self.mp_parsed_file.update({ 'description': self.mp_parsed_file.get('description').strip() }) # MITRE ATT&CK Tactics and Techniques tactic = [] tactic_re = re.compile(r'attack\.\w\D+$') technique = [] technique_re = re.compile(r'attack\.t\d{1,5}$') # AM!TT Tactics and Techniques amitt_tactic = [] amitt_tactic_re = re.compile(r'amitt\.\w\D+$') amitt_technique = [] amitt_technique_re = re.compile(r'amitt\.t\d{1,5}$') # MITRE ATT&CK Mitigation mitigation = [] mitigation_re = re.compile(r'attack\.m\d{1,5}$') # AM!TT Mitigation amitt_mitigation = [] amitt_mitigation_re = re.compile(r'amitt\.m\d{1,5}$') other_tags = [] if self.mp_parsed_file.get('tags'): for tag in self.mp_parsed_file.get('tags'): if tactic_re.match(tag): if ta_mapping.get(tag): tactic.append(ta_mapping.get(tag)) else: other_tags.append(tag) elif amitt_tactic_re.match(tag): if amitt_tactic_mapping.get(tag): amitt_tactic.append(amitt_tactic_mapping.get(tag)) else: other_tags.append(tag) elif technique_re.match(tag): te = tag.upper()[7:] technique.append((te_mapping.get(te), te)) elif amitt_technique_re.match(tag): te = tag.upper()[6:] technique.append((amitt_technique_mapping.get(te), te)) elif mitigation_re.match(tag): mi = tag.upper()[7:] mitigation.append((mi_mapping.get(mi), mi)) elif amitt_mitigation_re.match(tag): te = tag.upper()[6:] mitigation.append( (amitt_mitigation_mapping.get(te), te)) else: other_tags.append(tag) if not tactic_re.match(tag) and not \ technique_re.match(tag) and not \ mitigation_re.match(tag): other_tags.append(tag) if len(tactic): self.mp_parsed_file.update({'tactics': tactic}) if len(technique): self.mp_parsed_file.update({'techniques': technique}) if len(amitt_tactic): self.mp_parsed_file.update({'amitt_tactics': amitt_tactic}) if len(amitt_technique): self.mp_parsed_file.update( {'amitt_techniques': amitt_technique}) if len(mitigation): self.mp_parsed_file.update({'mitigations': mitigation}) if len(amitt_mitigation): self.mp_parsed_file.update( {'amitt_mitigations': amitt_mitigation}) if len(other_tags): self.mp_parsed_file.update({'other_tags': other_tags}) elif template_type == "confluence": template = env.get_template( 'confluence_mitigationpolicies_template.html.j2') self.mp_parsed_file.update({ 'confluence_viewpage_url': ATCconfig.get('confluence_viewpage_url') }) self.mp_parsed_file.update({ 'description': self.mp_parsed_file.get('description').strip() }) platform = self.mp_parsed_file.get("platform") if isinstance(platform, str): platform = [platform] self.mp_parsed_file.update({'platform': platform}) minimum_version = self.mp_parsed_file.get("minimum_version") if isinstance(minimum_version, str): minimum_version = [minimum_version] self.mp_parsed_file.update({'minimum_version': minimum_version}) mitigation_systems = self.mp_parsed_file.get("mitigation_system") if isinstance(mitigation_systems, str): mitigation_systems = [mitigation_systems] if not mitigation_systems: mitigation_systems = [ "None", ] mitigation_systems_with_id = [] if mitigation_systems: for ms in mitigation_systems: mitigation_systems_id = str( ATCutils.confluence_get_page_id( self.apipath, self.auth, self.space, ms)) ms = (ms, mitigation_systems_id) mitigation_systems_with_id.append(ms) self.mp_parsed_file.update( {'mitigation_system': mitigation_systems_with_id}) # MITRE ATT&CK Tactics and Techniques tactic = [] tactic_re = re.compile(r'attack\.\w\D+$') technique = [] technique_re = re.compile(r'attack\.t\d{1,5}$') # AM!TT Tactics and Techniques amitt_tactic = [] amitt_tactic_re = re.compile(r'amitt\.\w\D+$') amitt_technique = [] amitt_technique_re = re.compile(r'amitt\.t\d{1,5}$') # MITRE ATT&CK Mitigation mitigation = [] mitigation_re = re.compile(r'attack\.m\d{1,5}$') # AM!TT Mitigation amitt_mitigation = [] amitt_mitigation_re = re.compile(r'amitt\.m\d{1,5}$') other_tags = [] if self.mp_parsed_file.get('tags'): for tag in self.mp_parsed_file.get('tags'): if tactic_re.match(tag): if ta_mapping.get(tag): tactic.append(ta_mapping.get(tag)) else: other_tags.append(tag) elif amitt_tactic_re.match(tag): if amitt_tactic_mapping.get(tag): amitt_tactic.append(amitt_tactic_mapping.get(tag)) else: other_tags.append(tag) elif technique_re.match(tag): te = tag.upper()[7:] technique.append((te_mapping.get(te), te)) elif amitt_technique_re.match(tag): te = tag.upper()[6:] technique.append((amitt_technique_mapping.get(te), te)) elif mitigation_re.match(tag): mi = tag.upper()[7:] mitigation.append((mi_mapping.get(mi), mi)) elif amitt_mitigation_re.match(tag): te = tag.upper()[6:] mitigation.append( (amitt_mitigation_mapping.get(te), te)) else: other_tags.append(tag) if not tactic_re.match(tag) and not \ technique_re.match(tag) and not \ mitigation_re.match(tag): other_tags.append(tag) if len(tactic): self.mp_parsed_file.update({'tactics': tactic}) if len(technique): self.mp_parsed_file.update({'techniques': technique}) if len(amitt_tactic): self.mp_parsed_file.update({'amitt_tactics': amitt_tactic}) if len(amitt_technique): self.mp_parsed_file.update( {'amitt_techniques': amitt_technique}) if len(mitigation): self.mp_parsed_file.update({'mitigations': mitigation}) if len(amitt_mitigation): self.mp_parsed_file.update( {'amitt_mitigations': amitt_mitigation}) if len(other_tags): self.mp_parsed_file.update({'other_tags': other_tags}) # Render self.content = template.render(self.mp_parsed_file)
def render_template(self, template_type): """Description template_type: - "markdown" - "confluence" """ if template_type not in ["markdown", "confluence"]: raise Exception("Bad template_type. Available values:" + " [\"markdown\", \"confluence\"]") # Point to the templates directory env = Environment(loader=FileSystemLoader('templates')) # Get proper template if template_type == "markdown": template = env.get_template( 'markdown_responseplaybook_template.md.j2') self.rp_parsed_file.update({ 'title': ATCutils.normalize_react_title( self.rp_parsed_file.get('title')) }) # MITRE ATT&CK Tactics and Techniques tactic = [] tactic_re = re.compile(r'attack\.\w\D+$') technique = [] technique_re = re.compile(r'attack\.t\d{1,5}$') # AM!TT Tactics and Techniques amitt_tactic = [] amitt_tactic_re = re.compile(r'amitt\.\w\D+$') amitt_technique = [] amitt_technique_re = re.compile(r'amitt\.t\d{1,5}$') other_tags = [] for tag in self.rp_parsed_file.get('tags'): if tactic_re.match(tag): tactic.append(ta_mapping.get(tag)) elif technique_re.match(tag): te = tag.upper()[7:] technique.append((te_mapping.get(te), te)) elif amitt_tactic_re.match(tag): amitt_tactic.append(amitt_tactic_mapping.get(tag)) elif amitt_technique_re.match(tag): te = tag.upper()[6:] amitt_technique.append( (amitt_technique_mapping.get(te), te)) else: other_tags.append(tag) # Add MITRE ATT&CK Tactics and Techniques to J2 self.rp_parsed_file.update({'tactics': tactic}) self.rp_parsed_file.update({'techniques': technique}) # Add AM!TT Tactics and Techniques to J2 self.rp_parsed_file.update({'amitt_tactics': amitt_tactic}) self.rp_parsed_file.update({'amitt_techniques': amitt_technique}) self.rp_parsed_file.update({'other_tags': other_tags}) preparation = [] identification = [] containment = [] eradication = [] recovery = [] lessons_learned = [] detect = [] deny = [] disrupt = [] degrade = [] deceive = [] destroy = [] deter = [] stages = [('preparation', preparation), ('identification', identification), ('containment', containment), ('eradication', eradication), ('recovery', recovery), ('lessons_learned', lessons_learned), ('detect', detect), ('deny', deny), ('disrupt', disrupt), ('degrade', degrade), ('deceive', deceive), ('destroy', destroy), ('deter', deter)] # grab workflow per action in each IR stages # error handling for playbooks with empty stages for stage_name, stage_list in stages: try: for task in self.rp_parsed_file.get(stage_name): action = ATCutils.read_yaml_file( ATCconfig.get('response_actions_dir') + '/' + task + '.yml') stage_list.append((action.get('description'), action.get('workflow'))) except TypeError: pass # change stages name to more pretty format stages = [(stage_name.replace('_', ' ').capitalize(), stage_list) for stage_name, stage_list in stages] self.rp_parsed_file.update({'stages': stages}) self.rp_parsed_file.update({ 'description': self.rp_parsed_file.get('description').strip() }) elif template_type == "confluence": template = env.get_template( 'confluence_responseplaybook_template.html.j2') new_title = self.rp_parsed_file.get('id')\ + ": "\ + ATCutils.normalize_react_title(self.rp_parsed_file.get('title')) self.rp_parsed_file.update({'title': new_title}) self.rp_parsed_file.update({ 'confluence_viewpage_url': ATCconfig.get('confluence_viewpage_url') }) # MITRE ATT&CK Tactics and Techniques tactic = [] tactic_re = re.compile(r'attack\.\w\D+$') technique = [] technique_re = re.compile(r'attack\.t\d{1,5}$') # AM!TT Tactics and Techniques amitt_tactic = [] amitt_tactic_re = re.compile(r'amitt\.\w\D+$') amitt_technique = [] amitt_technique_re = re.compile(r'amitt\.t\d{1,5}$') other_tags = [] for tag in self.rp_parsed_file.get('tags'): if tactic_re.match(tag): tactic.append(ta_mapping.get(tag)) elif technique_re.match(tag): te = tag.upper()[7:] technique.append((te_mapping.get(te), te)) elif amitt_tactic_re.match(tag): amitt_tactic.append(amitt_tactic_mapping.get(tag)) elif amitt_technique_re.match(tag): te = tag.upper()[6:] amitt_technique.append( (amitt_technique_mapping.get(te), te)) else: other_tags.append(tag) # Add MITRE ATT&CK Tactics and Techniques to J2 self.rp_parsed_file.update({'tactics': tactic}) self.rp_parsed_file.update({'techniques': technique}) # Add AM!TT Tactics and Techniques to J2 self.rp_parsed_file.update({'amitt_tactics': amitt_tactic}) self.rp_parsed_file.update({'amitt_techniques': amitt_technique}) self.rp_parsed_file.update({'other_tags': other_tags}) # get links to response action preparation = [] identification = [] containment = [] eradication = [] recovery = [] lessons_learned = [] detect = [] deny = [] disrupt = [] degrade = [] deceive = [] destroy = [] deter = [] stages = [('preparation', preparation), ('identification', identification), ('containment', containment), ('eradication', eradication), ('recovery', recovery), ('lessons_learned', lessons_learned), ('detect', detect), ('deny', deny), ('disrupt', disrupt), ('degrade', degrade), ('deceive', deceive), ('destroy', destroy), ('deter', deter)] for stage_name, stage_list in stages: try: for task in self.rp_parsed_file.get(stage_name): action = ATCutils.read_yaml_file( ATCconfig.get('response_actions_dir') + '/' + task + '.yml') action_title = action.get('id')\ + ": "\ + ATCutils.normalize_react_title(action.get('title')) if self.apipath and self.auth and self.space: stage_list.append( (action_title, str( ATCutils.confluence_get_page_id( self.apipath, self.auth, self.space, action_title)))) else: stage_list.append((action_title, "")) except TypeError: pass # change stages name to more pretty format stages = [(stage_name.replace('_', ' ').capitalize(), stage_list) for stage_name, stage_list in stages] self.rp_parsed_file.update({'stages_with_id': stages}) # get descriptions for response actions preparation = [] identification = [] containment = [] eradication = [] recovery = [] lessons_learned = [] detect = [] deny = [] disrupt = [] degrade = [] deceive = [] destroy = [] deter = [] stages = [('preparation', preparation), ('identification', identification), ('containment', containment), ('eradication', eradication), ('recovery', recovery), ('lessons_learned', lessons_learned), ('detect', detect), ('deny', deny), ('disrupt', disrupt), ('degrade', degrade), ('deceive', deceive), ('destroy', destroy), ('deter', deter)] # grab workflow per action in each IR stages # error handling for playbooks with empty stages for stage_name, stage_list in stages: try: for task in self.rp_parsed_file.get(stage_name): action = ATCutils.read_yaml_file( ATCconfig.get('response_actions_dir') + '/' + task + '.yml') stage_list.append((action.get('description'), action.get('workflow'))) except TypeError: pass # change stages name to more pretty format stages = [(stage_name.replace('_', ' ').capitalize(), stage_list) for stage_name, stage_list in stages] self.rp_parsed_file.update({'stages': stages}) self.rp_parsed_file.update( {'workflow': self.rp_parsed_file.get('workflow')}) self.rp_parsed_file.update({ 'description': self.rp_parsed_file.get('description').strip() }) # Render self.content = template.render(self.rp_parsed_file)
def render_template(self, template_type): """Render template with data in it template_type: - "markdown" - "confluence" """ if template_type not in ["markdown", "confluence"]: raise Exception( "Bad template_type. Available values: " + "[\"markdown\", \"confluence\"]") # Point to the templates directory env = Environment(loader=FileSystemLoader('templates')) # Get proper template if template_type == "markdown": template = env.get_template( 'markdown_alert_template.md.j2') # Read raw sigma rule sigma_rule = ATCutils.read_rule_file(self.yaml_file) # Put raw sigma rule into fields var self.fields.update({'sigma_rule': sigma_rule}) # Define which queries we want from Sigma #queries = ["es-qs", "xpack-watcher", "graylog", "splunk", "logpoint", "grep", "fieldlist"] queries = ATCconfig.get('detection_queries').split(",") # dict to store query key + query values det_queries = {} # Convert sigma rule into queries (for instance, graylog query) for query in queries: # prepare command to execute from shell # (yes, we know) cmd = ATCconfig.get('sigmac_path') + " --shoot-yourself-in-the-foot -t " + \ query + " --ignore-backend-errors " + self.yaml_file #query + " --ignore-backend-errors " + self.yaml_file + \ #" 2> /dev/null" p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) (query2, err) = p.communicate() # Wait for date to terminate. Get return returncode # p_status = p.wait() p.wait() """ Had to remove '-' due to problems with Jinja2 variable naming, e.g es-qs throws error 'no es variable' """ det_queries[query] = str(query2)[2:-3] # Update detection rules self.fields.update({"det_queries": det_queries}) self.fields.update({"queries": queries}) # Data Needed data_needed = ATCutils.main_dn_calculatoin_func(self.yaml_file) # if there is only 1 element in the list, print it as a string, # without quotes # if isistance(data_needed, list) and len(data_needed) == 1: # [data_needed] = data_needed # print("%s || Dataneeded: \n%s\n" % # (self.fields.get("title"), data_needed)) self.fields.update({'data_needed': data_needed}) # Enrichments enrichments = self.fields.get("enrichment") if isinstance(enrichments, str): enrichments = [enrichments] self.fields.update({'enrichment': enrichments}) # MITRE ATT&CK Tactics and Techniques tactic = [] tactic_re = re.compile(r'attack\.\w\D+$') technique = [] technique_re = re.compile(r'attack\.t\d{1,5}$') # AM!TT Tactics and Techniques amitt_tactic = [] amitt_tactic_re = re.compile(r'amitt\.\w\D+$') amitt_technique = [] amitt_technique_re = re.compile(r'amitt\.t\d{1,5}$') other_tags = [] if self.fields.get('tags'): for tag in self.fields.get('tags'): if tactic_re.match(tag): if ta_mapping.get(tag): tactic.append(ta_mapping.get(tag)) else: other_tags.append(tag) elif amitt_tactic_re.match(tag): if amitt_tactic_mapping.get(tag): amitt_tactic.append(amitt_tactic_mapping.get(tag)) else: other_tags.append(tag) elif technique_re.match(tag): te = tag.upper()[7:] technique.append((te_mapping.get(te), te)) elif amitt_technique_re.match(tag): te = tag.upper()[6:] amitt_technique.append((amitt_technique_mapping.get(te), te)) else: other_tags.append(tag) if len(tactic): self.fields.update({'tactics': tactic}) if len(technique): self.fields.update({'techniques': technique}) if len(amitt_tactic): self.fields.update({'amitt_tactics': amitt_tactic}) if len(amitt_technique): self.fields.update({'amitt_techniques': amitt_technique}) if len(other_tags): self.fields.update({'other_tags': other_tags}) triggers = [] for trigger in technique: if trigger is "None": continue try: triggers.append(trigger) except FileNotFoundError: print(trigger + ": No atomics trigger for this technique") """ triggers.append( trigger + ": No atomics trigger for this technique" ) """ self.fields.update( {'description': self.fields.get('description').strip()}) self.fields.update({'triggers': triggers}) elif template_type == "confluence": template = env.get_template( 'confluence_alert_template.html.j2') self.fields.update( {'confluence_viewpage_url': ATCconfig.get('confluence_viewpage_url')}) sigma_rule = ATCutils.read_rule_file(self.yaml_file) self.fields.update({'sigma_rule': sigma_rule}) #outputs = ["es-qs", "xpack-watcher", "graylog"] queries = ATCconfig.get('detection_queries').split(",") # dict to store query key + query values det_queries = {} for output in queries: cmd = ATCconfig.get('sigmac_path') + \ " --shoot-yourself-in-the-foot -t " + \ output + " --ignore-backend-errors " + self.yaml_file + \ " 2> /dev/null" p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) (query, err) = p.communicate() # Wait for date to terminate. Get return returncode ## # p_status = p.wait() p.wait() # have to remove '-' due to problems with # Jinja2 variable naming,e.g es-qs throws error # 'no es variable' self.fields.update({output.replace("-", ""): str(query)[2:-3]}) # Data Needed data_needed = ATCutils.main_dn_calculatoin_func(self.yaml_file) data_needed_with_id = [] for data in data_needed: data_needed_id = str(ATCutils.confluence_get_page_id( self.apipath, self.auth, self.space, data)) data = (data, data_needed_id) data_needed_with_id.append(data) self.fields.update({'data_needed': data_needed_with_id}) # Enrichments enrichments = self.fields.get("enrichment") enrichments_with_page_id = [] if isinstance(enrichments, str): enrichments = [enrichments] if enrichments: for enrichment_name in enrichments: enrichment_page_id = str(ATCutils.confluence_get_page_id( self.apipath, self.auth, self.space, enrichment_name)) enrichment_data = (enrichment_name, enrichment_page_id) enrichments_with_page_id.append(enrichment_data) self.fields.update({'enrichment': enrichments_with_page_id}) # MITRE ATT&CK Tactics and Techniques tactic = [] tactic_re = re.compile(r'attack\.\w\D+$') technique = [] technique_re = re.compile(r'attack\.t\d{1,5}$') # AM!TT Tactics and Techniques amitt_tactic = [] amitt_tactic_re = re.compile(r'amitt\.\w\D+$') amitt_technique = [] amitt_technique_re = re.compile(r'amitt\.t\d{1,5}$') other_tags = [] if self.fields.get('tags'): for tag in self.fields.get('tags'): if tactic_re.match(tag): if ta_mapping.get(tag): tactic.append(ta_mapping.get(tag)) else: other_tags.append(tag) elif amitt_tactic_re.match(tag): if amitt_tactic_mapping.get(tag): amitt_tactic.append(amitt_tactic_mapping.get(tag)) else: other_tags.append(tag) elif technique_re.match(tag): te = tag.upper()[7:] technique.append((te_mapping.get(te), te)) elif amitt_technique_re.match(tag): te = tag.upper()[6:] amitt_technique.append((amitt_technique_mapping.get(te), te)) else: other_tags.append(tag) if len(tactic): self.fields.update({'tactics': tactic}) if len(technique): self.fields.update({'techniques': technique}) if len(amitt_tactic): self.fields.update({'amitt_tactics': amitt_tactic}) if len(technique): self.fields.update({'amitt_techniques': amitt_technique}) if len(other_tags): self.fields.update({'other_tags': other_tags}) triggers = [] for trigger_name, trigger_id in technique: if trigger_id is "None": continue try: page_name = trigger_id + ": " + trigger_name trigger_page_id = str(ATCutils.confluence_get_page_id( self.apipath, self.auth, self.space, page_name)) trigger = (trigger_name, trigger_id, trigger_page_id) triggers.append(trigger) except FileNotFoundError: print(trigger + ": No atomics trigger for this technique") self.fields.update({'triggers': triggers}) self.content = template.render(self.fields) # Need to convert ampersand into HTML "save" format # Otherwise confluence throws an error # self.content = self.content.replace("&", "&") # Done in the template itself return True