Files
blue-team-tools/tools/config/mitre/update_mitre.py
T

127 lines
5.5 KiB
Python

# Updates the Mitre Tactics & Techniques from Mitre CTI Pre, Enterprise & Mobile Attack
# Copyright 2020 Scott Dermott
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import json
import urllib.request
mitre_update_urls = [
'https://raw.githubusercontent.com/mitre/cti/master/pre-attack/pre-attack.json',
'https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json',
'https://raw.githubusercontent.com/mitre/cti/master/mobile-attack/mobile-attack.json'
]
mitre_source_types = list([
'mitre-pre-attack',
'mitre-attack',
'mitre-mobile-attack'
])
tactics_list = []
techniques_list = []
def get_external_id(obj):
return obj.get('external_id')
def get_technique_id(obj):
return obj.get('technique_id')
def revoked_or_deprecated(entry):
if "revoked" in entry.keys() and entry['revoked'] or "x_mitre_deprecated" in entry.keys() and entry['x_mitre_deprecated']:
return True
return False
for url in mitre_update_urls:
with urllib.request.urlopen(url) as cti_json:
mitre_json = json.loads(cti_json.read().decode())
url_type = url.rsplit('/',1)[1].split('.')[0].title()
techniques = []
tactics = []
tactic_map = {}
technique_map = {}
# Map the tatics
for entry in mitre_json['objects']:
if not entry['type'] == "x-mitre-tactic" or revoked_or_deprecated(entry):
continue
for ref in entry['external_references']:
if ref['source_name'] in mitre_source_types:
tactic_map[entry['x_mitre_shortname']] = entry['name']
tactics.append({
"external_id": ref['external_id'],
"url": ref['url'],
"tactic": entry['name']
})
break
# Map the techniques
for entry in mitre_json['objects']:
if not entry['type'] == "attack-pattern" or revoked_or_deprecated(entry):
continue
if "x_mitre_is_subtechnique" in entry.keys() and entry['x_mitre_is_subtechnique']:
continue
for ref in entry['external_references']:
if ref['source_name'] in mitre_source_types:
technique_map[ref['external_id']] = entry['name']
sub_tactics = []
# Get Mitre Tactics (Kill-Chains)
for tactic in entry['kill_chain_phases']:
if tactic['kill_chain_name'] in mitre_source_types:
# Map the short phase_name to tactic name
sub_tactics.append(tactic_map[tactic['phase_name']])
techniques.append({
"technique_id": ref['external_id'],
"technique": entry['name'],
"url": ref['url'],
"tactic" : sub_tactics
})
break
## Map the sub-techniques
for entry in mitre_json['objects']:
if not entry['type'] == "attack-pattern" or revoked_or_deprecated(entry):
continue
if "x_mitre_is_subtechnique" in entry.keys() and entry['x_mitre_is_subtechnique']:
for ref in entry['external_references']:
if ref['source_name'] in mitre_source_types:
sub_technique_id = ref['external_id']
sub_technique_name = entry['name']
parent_technique_name = technique_map[sub_technique_id.split('.')[0]]
sub_technique_name = '{} : {}'.format(parent_technique_name, sub_technique_name)
techniques.append({
"technique_id": ref['external_id'],
"technique": sub_technique_name,
"url": ref['url'],
})
break
print("Updating from : {}".format(url))
print("{} Mitre Bundle ID : {} ".format(url_type, mitre_json['id']))
print("{} Tactics : {} ".format(url_type, len(tactic_map)))
print("{} Techniques : {} ".format(url_type, len(technique_map)))
print("{} Sub-Techniques : {} ".format(url_type, len(techniques) - len(technique_map)))
print("-------------------------------------------------")
tactics_list.extend(tactics)
techniques_list.extend(techniques)
print("Total Mitre Tactics : {} ".format(len(tactics_list)))
print("Total Mitre Techniques : {} ".format(len(techniques_list)))
## Create the output files
with open('tactics.json', 'w') as json_file:
tactics_list.sort(key=get_external_id)
json.dump(tactics_list, json_file, sort_keys=False, indent=2)
with open('techniques.json', 'w') as json_file:
techniques_list.sort(key=get_technique_id)
json.dump(techniques_list, json_file, sort_keys=False, indent=2)