def mitre(): """Urls might change, for proper urls see https://github.com/swimlane/pyattck""" try: from pyattck import Attck except ImportError: print( "Missed dependency: install pyattck library, see requirements for proper version" ) return mitre = Attck( nested_subtechniques=True, save_config=False, use_config=False, config_file_path=os.path.join(CUCKOO_ROOT, "data", "mitre", "config.yml"), data_path=os.path.join(CUCKOO_ROOT, "data", "mitre"), enterprise_attck_json= "https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json", pre_attck_json= "https://raw.githubusercontent.com/mitre/cti/master/pre-attack/pre-attack.json", mobile_attck_json= "https://raw.githubusercontent.com/mitre/cti/master/mobile-attack/mobile-attack.json", nist_controls_json= "https://raw.githubusercontent.com/center-for-threat-informed-defense/attack-control-framework-mappings/master/frameworks/ATT%26CK-v9.0/nist800-53-r4/stix/nist800-53-r4-controls.json", generated_attck_json= "https://swimlane-pyattck.s3.us-west-2.amazonaws.com/generated_attck_data.json", generated_nist_json= "https://swimlane-pyattck.s3.us-west-2.amazonaws.com/attck_to_nist_controls.json", ) print("[+] Updating MITRE datasets") mitre.update()
def test_passed_kwargs(): from pyattck import Attck, Configuration attck = Attck() assert Configuration.requests_kwargs == {} args = { 'verify': False, 'proxies': { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080', } } attck = Attck(**args) assert Configuration.requests_kwargs == args
def test_attck_attribute_is_list(target_attribute): from pyattck import Attck path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures') #, 'generated_attck_data' + '.json') attck = Attck(data_path=path) ics = getattr(attck, 'ics') assert isinstance(getattr(ics, target_attribute), list)
def test_preattck_attck_attribute_is_list(target_attribute): from pyattck import Attck path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', 'generated_attck_data' + '.json') attck = Attck() preattack = getattr(attck, 'preattack') assert isinstance(getattr(preattack, target_attribute), list)
def test_default_config(attck_configuration): from pyattck import Attck, Configuration attck = Attck() for key,val in default_config_data.items(): if hasattr(Configuration, key): setattr(Configuration, key, val) assert attck_configuration.config_data == default_config_data
def test_attck_attribute_is_list(target_attribute): from pyattck import Attck path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', 'generated_attck_data' + '.json') attck = Attck(dataset_json=path) enterprise = getattr(attck, 'enterprise') assert isinstance(getattr(enterprise, target_attribute), list)
def test_nested_subtechniques(): from pyattck import Attck attck = Attck(nested_subtechniques=False) count = 0 for technique in attck.enterprise.techniques: if technique.subtechnique: count += 1 assert count >= 360
def test_config_dataset_json_path_default_value(): from pyattck import Attck Attck() config = None with open(os.path.abspath(os.path.join(expanduser('~'), 'pyattck', 'config' + '.yml'))) as f: config = yaml.load(f, Loader=yaml.FullLoader) assert config['enterprise_attck_dataset'] == os.path.abspath(os.path.join(expanduser('~'), 'pyattck', 'enterprise_attck_dataset' + '.json'))
def test_all_preattck_attck_objects_have_standard_properties( target_attribute, target_properties): from pyattck import Attck path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', 'generated_attck_data' + '.json') attck = Attck() preattack = getattr(attck, 'preattack') for attribute in getattr(preattack, target_attribute): assert getattr(attribute, target_properties)
def test_all_attck_objects_have_standard_properties(target_attribute, target_properties): from pyattck import Attck path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', 'generated_attck_data' + '.json') attck = Attck(dataset_json=path) enterprise = getattr(attck, 'enterprise') for attribute in getattr(enterprise, target_attribute): assert getattr(attribute, target_properties)
def test_all_attck_objects_have_standard_properties_deprecated(target_attribute,target_properties): from pyattck import Attck path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'fixtures', 'generated_attck_data' + '.json') attck = Attck(dataset_json=path) return_list = [] for attribute in getattr(attck,target_attribute): if hasattr(attribute, target_properties): return_list.append(getattr(attribute,target_properties)) if len(return_list) >= 1: assert True
def test_config_enterprise_attck_dataset_json_path_provided_value(tmpdir): from pyattck import Attck config_path = os.path.abspath(os.path.join(expanduser('~'), 'pyattck', 'config' + '.yml')) path = tmpdir.mkdir('pyattck').join('enterprise_attck_dataset.json') Attck(dataset_json=os.path.abspath(str(path))) config = None with open(config_path) as f: config = yaml.load(f, Loader=yaml.FullLoader) assert config['enterprise_attck_dataset'] == os.path.abspath(str(path))
def test_config_attck_json_path_default_value(): from pyattck import Attck Attck() config_path = os.path.abspath( os.path.join(expanduser('~'), 'pyattck', 'config' + '.yml')) config = None with open(config_path) as f: config = yaml.load(f, Loader=yaml.FullLoader) assert os.path.join(config.get('data_path'), config['enterprise'].get('filename')) == os.path.join( config.get('data_path'), 'enterprise_attck' + '.json')
def test_config_attck_json_path_provided_value(tmpdir): from pyattck import Attck config_path = os.path.abspath( os.path.join(expanduser('~'), 'pyattck', 'config' + '.yml')) path = tmpdir.mkdir('pyattck') Attck(data_path=str(path)) config = None with open(config_path) as f: config = yaml.load(f, Loader=yaml.FullLoader) assert os.path.join(config.get('data_path'), config['enterprise'].get('filename')) == os.path.join( config.get('data_path'), 'enterprise_attck' + '.json')
def mitre_techniques() -> Dict[Text, Text]: """ Get list of all MITRE ATT&CK techniques and return map combined with both technique IDs and (lowercased) name as key an name as value """ attack = Attck() techniques = {} for technique in attack.enterprise.techniques: techniques[technique.id] = technique.name techniques[technique.name.lower()] = technique.name return techniques
def main() -> None: """Main function""" # Look for default ini file in "/etc/actworkers.ini" and ~/config/actworkers/actworkers.ini # (or replace .config with $XDG_CONFIG_DIR if set) args = cli.handle_args(parseargs()) actapi = worker.init_act(args) proxies = ({ "http": args.proxy_string, "https": args.proxy_string } if args.proxy_string else None) attack = Attck(proxies=proxies) types = [args.type] if args.type else MITRE_TYPES for mitre_type in types: if mitre_type not in MITRE_TYPES: error("Unknown mitre type: {}. Valid types: {}".format( mitre_type, ",".join(MITRE_TYPES))) sys.exit(2) cache = notify_cache(args.notifycache) model = getattr(attack, mitre_type) techniques_notify = add_techniques(actapi, model, args.output_format) groups_notify = add_groups(actapi, model, args.output_format) software_notify = add_software(actapi, model, args.output_format) # filter revoked objects from those allready notified notify = [ notify for notify in techniques_notify + groups_notify + software_notify if notify.id not in cache ] if notify: notified = send_notification(notify, args.smtphost, args.sender, args.recipient, mitre_type) for object_id in notified: # Add object to cache, so we will not be notified on the same object on the next run add_to_cache(args.notifycache, object_id)
def attck_fixture(): from pyattck import Attck yield Attck( use_config=False, save_config=False, enterprise_attck_json= "https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json", pre_attck_json= "https://raw.githubusercontent.com/mitre/cti/master/pre-attack/pre-attack.json", mobile_attck_json= "https://raw.githubusercontent.com/mitre/cti/master/mobile-attack/mobile-attack.json", nist_controls_json= "https://raw.githubusercontent.com/center-for-threat-informed-defense/attack-control-framework-mappings/main/frameworks/attack_10_1/nist800_53_r4/stix/nist800-53-r4-controls.json", generated_attck_json= "https://github.com/swimlane/pyattck/blob/master/generated_attck_data.json?raw=True", generated_nist_json= "https://github.com/swimlane/pyattck/blob/master/attck_to_nist_controls.json?raw=True" )
def test_setting_json_locations(target_attribute): from pyattck import Attck, Configuration enterprise_temp_value = get_random_file_or_url() pre_attck_temp_value = get_random_file_or_url() mobile_temp_value = get_random_file_or_url() ics_temp_value = get_random_file_or_url() nist_controls_temp_value = get_random_file_or_url() generated_attck_temp_value = get_random_file_or_url() generated_nist_temp_value = get_random_file_or_url() attck = Attck( enterprise_attck_json=enterprise_temp_value ) assert Configuration.enterprise_attck_json == enterprise_temp_value attck = Attck( pre_attck_json=pre_attck_temp_value ) assert Configuration.pre_attck_json == pre_attck_temp_value attck = Attck( mobile_attck_json=mobile_temp_value ) assert Configuration.mobile_attck_json == mobile_temp_value attck = Attck( ics_attck_json=ics_temp_value ) assert Configuration.ics_attck_json == ics_temp_value attck = Attck( nist_controls_json=nist_controls_temp_value ) assert Configuration.nist_controls_json == nist_controls_temp_value attck = Attck( generated_attck_json=generated_attck_temp_value ) assert Configuration.generated_attck_json == generated_attck_temp_value attck = Attck( generated_nist_json=generated_nist_temp_value ) assert Configuration.generated_nist_json == generated_nist_temp_value
from pyattck import Attck attack = Attck() # Examples of MITRE Enterprise ATT&CK using nested subtechniques for actor in attack.enterprise.actors: print(actor.id) print(actor.name) # accessing malware used by an actor or group for malware in actor.malwares: print(malware.id) print(malware.name) # accessing tools used by an actor or group for tool in actor.tools: print(tool.id) print(tool.name) # accessing techniques used by an actor or group for technique in actor.techniques: print(technique.id) print(technique.name) # you can also access generated data sets on aa technique print(technique.command_list) print(technique.commands) print(technique.queries) print(technique.datasets) print(technique.possible_detections) # You can access subtechniques nested under techniques by default
import pandas as pd import matplotlib.pyplot as plt from pyattck import Attck attack = Attck() attack.update(enterprise=True) techniques = [] data_sources = [] for technique in attack.enterprise.techniques: if technique.data_source: for data_source in technique.data_source: techniques.append(technique.name) data_sources.append(data_source) data = { 'technique': techniques, 'data_source': data_sources } t2d = pd.DataFrame(data, columns=['technique', 'data_source']) t2d.head(20) # Look at the frequency of the data sources dataFrequency = t2d['data_source'].value_counts() dataFrequency.head(20) plt.bar(dataFrequency.index, dataFrequency.values) plt.xticks(dataFrequency.index, dataFrequency.index, rotation=90)
def test_config_alternate_location(tmpdir): config_path = str(tmpdir.mkdir('pyattck').join('config.yml')) from pyattck import Attck Attck(config_path=config_path) assert len(tmpdir.listdir()) == 1
def test_config_in_default_location(): from pyattck import Attck Attck() assert os.path.isfile(os.path.join(expanduser('~'), 'pyattck', 'config' + '.yml'))
def test_configuration_save_config(attck_configuration): from pyattck import Attck attck = Attck(save_config=True) assert attck_configuration.save_config == True assert isinstance(attck_configuration.config_data, dict) assert os.path.abspath(os.path.expanduser(os.path.expandvars(attck_configuration.data_path))) == attck_configuration.config_data.get('data_path')
def test_default_configuration_settings_jsons(attck_configuration, target_attribute): from pyattck import Attck, Configuration attck = Attck() assert getattr(Configuration, target_attribute) == default_config_data[target_attribute]
def main(args=None): attck = Attck() fire.Fire(attck)
class AttckDocs(object): _attck = Attck(nested_subtechniques=False)
from pyattck import Attck attack = Attck(nested_subtechniques=False) # Examples of MITRE Enterprise ATT&CK using nested subtechniques for actor in attack.enterprise.actors: print(actor.id) print(actor.name) # accessing malware used by an actor or group for malware in actor.malwares: print(malware.id) print(malware.name) # accessing tools used by an actor or group for tool in actor.tools: print(tool.id) print(tool.name) # accessing techniques used by an actor or group for technique in actor.techniques: print(technique.id) print(technique.name) print(technique.data_sources) # you can also access generated data sets on aa technique print(technique.command_list) print(technique.commands) print(technique.queries) print(technique.datasets)
def attck_fixture_nested_subtechniques_false(): from pyattck import Attck return Attck(nested_subtechniques=False)
class AttckDocs(object): _attck = Attck()
def attck_fixture(): from pyattck import Attck return Attck()