diff --git a/.gitignore b/.gitignore index 320bfc34..190809b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ + *DS_Store *__pycache__/* *.pyc diff --git a/scripts/config.default.yml b/scripts/config.default.yml index de693013..ebf25ca8 100644 --- a/scripts/config.default.yml +++ b/scripts/config.default.yml @@ -29,4 +29,33 @@ attack_json_url: 'https://raw.githubusercontent.com/mitre/cti/master/enterprise- attack_mapping_url: 'scripts/attack_mapping.py' # AMITT amitt_json_url: 'https://raw.githubusercontent.com/cogsec-collaborative/amitt_cti/master/amitt/amitt-attack.json' -amitt_mapping_url: 'scripts/amitt_mapping.py' \ No newline at end of file +amitt_mapping_url: 'scripts/amitt_mapping.py' +# Title formatting rules +titlefmtrules: + capitalizeWords: # will be capitalized: unix -> Unix + - "unix" + - "windows" + - "proxy" + - "firewall" + - "mach-o" + abbreviations: # will be completely converted to uppercase lan -> LAN + - "ip" + - "dns" + - "ms" + - "ngfw" + - "ips" + - "url" + - "pe" + - "pdf" + - "elf" + - "dhcp" + - "vpn" + - "smb" + - "ftp" + - "http" + - "lan" + - "wan" + - "av" + - "fqdn" + - "dfs" + - "soc" \ No newline at end of file diff --git a/scripts/generate_mkdocs_config.py b/scripts/generate_mkdocs_config.py index f4396415..5d79c063 100644 --- a/scripts/generate_mkdocs_config.py +++ b/scripts/generate_mkdocs_config.py @@ -108,7 +108,7 @@ def __init__(self, ra=False, rp=False, rs=False, auto=False, ra_updated_title = ras[i].get('id')\ + ": "\ - + REACTutils.normalize_react_title(ras[i].get('title')) + + REACTutils.normalize_react_title(ras[i].get('title'),REACTConfig.get('titlefmtrules')) if "RA1" in ras[i]['id']: preparation.append((ra_updated_title, ra_filenames[i])) @@ -130,7 +130,7 @@ def __init__(self, ra=False, rp=False, rs=False, auto=False, rp_updated_title = rps[i].get('id')\ + ": "\ - + REACTutils.normalize_react_title(rps[i].get('title')) + + REACTutils.normalize_react_title(rps[i].get('title'),REACTConfig.get('titlefmtrules')) playbooks.append((rp_updated_title, rp_filenames[i])) diff --git a/scripts/react2stix.py b/scripts/react2stix.py index b72ff258..47ce3080 100644 --- a/scripts/react2stix.py +++ b/scripts/react2stix.py @@ -119,7 +119,7 @@ def __init__(self, ra=False, rp=False, auto=False, for i in range(len(ras)): - normalized_title = REACTutils.normalize_react_title(ras[i].get('title')) + normalized_title = REACTutils.normalize_react_title(ras[i].get('title'),REACTConfig.get('titlefmtrules')) ra_updated_title = ras[i].get('id')\ + ":"\ diff --git a/scripts/reactutils.py b/scripts/reactutils.py index 3ed98b6e..933620cc 100755 --- a/scripts/reactutils.py +++ b/scripts/reactutils.py @@ -459,23 +459,21 @@ def push_to_confluence(data, apipath, auth): @staticmethod - def normalize_react_title(title): + def normalize_react_title(title,fmtrules={"abbreviations": ["ip", "dns", "ms", "ngfw", "ips", "url", "pe", "pdf","elf", "dhcp", "vpn", "smb", "ftp", "http"],"capitalizeWords":["unix", "windows", "proxy", "firewall", "mach-o"]}): """Normalize title if it is a RA/RP title in the following format: RP_0003_identification_make_sure_email_is_a_phishing """ - react_id_re = re.compile(r'R[AP]_\d{4}.*$') + react_id_re = re.compile(r'R[AP]_\d{4}_.*$') if react_id_re.match(title): title = title[8:].split('_', 0)[-1].replace('_', ' ').capitalize() new_title = "" for word in title.split(): - if word.lower() in [ - "ip", "dns", "ms", "ngfw", "ips", "url", "pe", "pdf", - "elf", "dhcp", "vpn", "smb", "ftp", "http" ]: + if word.lower() in fmtrules["abbreviations"]: new_title += word.upper() new_title += " " continue - elif word.lower() in [ "unix", "windows", "proxy", "firewall", "mach-o" ]: + elif word.lower() in fmtrules["capitalizeWords"]: new_title += word.capitalize() new_title += " " continue diff --git a/scripts/responseaction.py b/scripts/responseaction.py index 9d5378fb..1f0db93b 100755 --- a/scripts/responseaction.py +++ b/scripts/responseaction.py @@ -74,7 +74,7 @@ def render_template(self, template_type): self.ra_parsed_file.update( {'title': REACTutils.normalize_react_title(self.ra_parsed_file - .get('title'))} + .get('title'),REACTConfig.get('titlefmtrules'))} ) stage_list = [] @@ -95,7 +95,7 @@ def render_template(self, template_type): new_title = self.ra_parsed_file.get('id')\ + ": "\ - + REACTutils.normalize_react_title(self.ra_parsed_file.get('title')) + + REACTutils.normalize_react_title(self.ra_parsed_file.get('title'),REACTConfig.get('titlefmtrules')) self.ra_parsed_file.update( {'title': new_title} diff --git a/scripts/responseplaybook.py b/scripts/responseplaybook.py index e5fbaaa1..e1286d9d 100755 --- a/scripts/responseplaybook.py +++ b/scripts/responseplaybook.py @@ -67,7 +67,7 @@ def render_template(self, template_type): self.rp_parsed_file.update( {'title': REACTutils.normalize_react_title(self.rp_parsed_file - .get('title'))} + .get('title'),REACTConfig.get('titlefmtrules'))} ) # MITRE ATT&CK Tactics and Techniques @@ -141,7 +141,7 @@ def render_template(self, template_type): action_title = action.get('id')\ + ": "\ - + REACTutils.normalize_react_title(action.get('title')) + + REACTutils.normalize_react_title(action.get('title'),REACTConfig.get('titlefmtrules')) stage_list.append( (action_title, task, action.get('description'), action.get('workflow')) @@ -157,7 +157,7 @@ def render_template(self, template_type): new_title = self.rp_parsed_file.get('id')\ + ": "\ - + REACTutils.normalize_react_title(self.rp_parsed_file.get('title')) + + REACTutils.normalize_react_title(self.rp_parsed_file.get('title'),REACTConfig.get('titlefmtrules')) self.rp_parsed_file.update( {'title': new_title } @@ -236,7 +236,7 @@ def render_template(self, template_type): action_title = action.get('id')\ + ": "\ - + REACTutils.normalize_react_title(action.get('title')) + + REACTutils.normalize_react_title(action.get('title'),REACTConfig.get('titlefmtrules')) if self.apipath and self.auth and self.space: stage_list.append( diff --git a/scripts/responsestage.py b/scripts/responsestage.py index 71810403..e00a3184 100755 --- a/scripts/responsestage.py +++ b/scripts/responsestage.py @@ -79,7 +79,7 @@ def render_template(self, template_type): if rs_mapping[rs_id] == REACTutils.normalize_rs_name(ras[i].get('stage')): ra_id = ras[i].get('id') ra_filename = ra_filenames[i] - ra_title = REACTutils.normalize_react_title(ras[i].get('title')) + ra_title = REACTutils.normalize_react_title(ras[i].get('title'),REACTConfig.get('titlefmtrules')) ra_description = ras[i].get('description').strip() stage_list.append( (ra_id, ra_filename, ra_title, ra_description)) @@ -99,7 +99,7 @@ def render_template(self, template_type): if rs_mapping[rs_id] == REACTutils.normalize_rs_name(ras[i].get('stage')): ra_id = ras[i].get('id') ra_filename = ra_filenames[i] - ra_title = REACTutils.normalize_react_title(ras[i].get('title')) + ra_title = REACTutils.normalize_react_title(ras[i].get('title'),REACTConfig.get('titlefmtrules')) ra_description = ras[i].get('description').strip() ra_confluence_page_name = ra_id + ": " + ra_title @@ -115,7 +115,7 @@ def render_template(self, template_type): new_title = self.rs_parsed_file.get('id')\ + ": "\ - + REACTutils.normalize_react_title(self.rs_parsed_file.get('title')) + + REACTutils.normalize_react_title(self.rs_parsed_file.get('title'),REACTConfig.get('titlefmtrules')) self.rs_parsed_file.update( {'title': new_title} diff --git a/scripts/thehive_templates.py b/scripts/thehive_templates.py index 3398956a..cc82bf60 100644 --- a/scripts/thehive_templates.py +++ b/scripts/thehive_templates.py @@ -11,6 +11,7 @@ import argparse import os +REACTConfig = REACTutils.load_config("config.yml") class RPTheHive: @@ -108,7 +109,7 @@ def convertRPToTemplate(self, file_input, output_file): self.case = THC.TheHiveCase() self.case.name = self.rp_rule.get('id')\ + ": "\ - + REACTutils.normalize_react_title(self.rp_rule.get('title')) + + REACTutils.normalize_react_title(self.rp_rule.get('title'),REACTConfig.get('titlefmtrules')) self.case.description = str(self.rp_rule.get('description')) + \ '\n\nWorkflow:\n\n' + str(self.rp_rule.get('workflow')) @@ -157,7 +158,7 @@ def checkRA(self, stage): task.title = str(self.task_prefix) + " | "\ + rtask.get('id')\ + ": "\ - + REACTutils.normalize_react_title(rtask.get('title')) + + REACTutils.normalize_react_title(rtask.get('title'),REACTConfig.get('titlefmtrules')) if rtask.get('stage'): task.group = REACTutils.normalize_rs_name(rtask.get('stage'))