Пример #1
0
def create_markdown_dirs():
    config = ATCutils.load_config('scripts/config.yml')
    base_dir = Path(config.get(
        'md_name_of_root_directory',
        '../docs'
    ))

    target_dir_list = ['Response_Actions', 'Response_Playbooks' , 'Response_Stages']

    for item in target_dir_list:
        (base_dir / item).mkdir(parents=True, exist_ok=True)
Пример #2
0
    def save_markdown_file(self,
                           atc_dir=ATCconfig.get('md_name_of_root_directory')):
        """Write content (md template filled with data) to a file"""

        base = os.path.basename(self.yaml_file)
        title = os.path.splitext(base)[0]

        file_path = atc_dir + self.parent_title + "/" + \
            title + ".md"

        return ATCutils.write_file(file_path, self.content)
Пример #3
0
    def render_template(self, template_type):
        """Description
        template_type:
            - "markdown"
        """

        if template_type not in ["markdown"]:
            raise Exception("Bad template_type. Available values:" +
                            " [\"markdown\"]")

        # Point to the templates directory
        env = Environment(loader=FileSystemLoader('scripts/templates'))

        template = env.get_template('markdown_responsestage_template.md.j2')

        self.ra_parsed_file.update(
            {'description': self.ra_parsed_file.get('description').strip()})

        ras, ra_paths = ATCutils.load_yamls_with_paths(
            ATCconfig.get('response_actions_dir'))
        ra_filenames = [
            ra_path.split('/')[-1].replace('.yml', '') for ra_path in ra_paths
        ]

        rs_id = self.ra_parsed_file.get('id')

        stage_list = []

        for i in range(len(ras)):
            if rs_mapping[rs_id] == ATCutils.normalize_rs_name(
                    ras[i].get('stage')):
                ra_id = ras[i].get('id')
                ra_filename = ra_filenames[i]
                ra_title = ATCutils.normalize_react_title(ras[i].get('title'))
                ra_description = ras[i].get('description').strip()
                stage_list.append(
                    (ra_id, ra_filename, ra_title, ra_description))

        self.ra_parsed_file.update({'stage_list': sorted(stage_list)})

        self.content = template.render(self.ra_parsed_file)
Пример #4
0
    def parse_into_fields(self):
        """Description"""

        # self.fields contains parsed fields obtained from yaml file
        self.cu_fields = ATCutils.read_yaml_file(self.yaml_file)
        """Fill the fields with values. Put None if key not found"""
        self.title = self.cu_fields.get('title')
        self.customer_name = self.cu_fields.get('customer_name')
        self.description = self.cu_fields.get('description')
        self.data_needed = self.cu_fields.get('dataneeded')
        self.logging_policies = self.cu_fields.get('loggingpolicy')
        self.detection_rules = self.cu_fields.get('detectionrule')
Пример #5
0
    def hardening_policy(self, hp_path):
        """Populate Hardening Policies"""

        print("[*] Populating Hardening Policies...")
        if hp_path:
            hp_list = glob.glob(hp_path + '*.yml')
        else:
            hp_dir = ATCconfig.get('hardening_policies_directory')
            hp_list = glob.glob(hp_dir + '/*.yml')

        for hp_file in hp_list:
            try:
                hp = HardeningPolicy(hp_file)
                hp.render_template("confluence")
                confluence_data = {
                    "title":
                    hp.hp_parsed_file["title"],
                    "spacekey":
                    self.space,
                    "parentid":
                    str(
                        ATCutils.confluence_get_page_id(
                            self.apipath, self.auth, self.space,
                            "Hardening Policies")),
                    "confluencecontent":
                    hp.content,
                }

                res = ATCutils.push_to_confluence(confluence_data,
                                                  self.apipath, self.auth)
                if res == 'Page updated':
                    print("==> updated page: HP '" +
                          hp.hp_parsed_file['title'] + "'")
            except Exception as err:
                print(hp_file + " failed")
                print("Err message: %s" % err)
                print('-' * 60)
                traceback.print_exc(file=sys.stdout)
                print('-' * 60)
        print("[+] Hardening Policies populated!")
Пример #6
0
    def mitigation_system(self, ms_path):
        """Populate Mitigation Systems"""

        print("[*] Populating Mitigation Systems...")
        if ms_path:
            ms_list = glob.glob(ms_path + '*.yml')
        else:
            ms_dir = ATCconfig.get('mitigation_systems_directory')
            ms_list = glob.glob(ms_dir + '/*.yml')

        for ms_file in ms_list:
            try:
                ms = MitigationSystem(ms_file)
                ms.render_template("confluence")
                confluence_data = {
                    "title":
                    ms.ms_parsed_file["title"],
                    "spacekey":
                    self.space,
                    "parentid":
                    str(
                        ATCutils.confluence_get_page_id(
                            self.apipath, self.auth, self.space,
                            "Mitigation Systems")),
                    "confluencecontent":
                    ms.content,
                }

                res = ATCutils.push_to_confluence(confluence_data,
                                                  self.apipath, self.auth)
                if res == 'Page updated':
                    print("==> updated page: MS '" +
                          ms.ms_parsed_file['title'] + "'")
            except Exception as err:
                print(ms_file + " failed")
                print("Err message: %s" % err)
                print('-' * 60)
                traceback.print_exc(file=sys.stdout)
                print('-' * 60)
        print("[+] Mitigation Systems populated!")
Пример #7
0
    def logging_policy(self, lp_path):
        """Desc"""

        print("[*] Populating Logging Policies...")
        if lp_path:
            lp_list = glob.glob(lp_path + '*.yml')
        else:
            lp_dir = ATCconfig.get('logging_policies_dir')
            lp_list = glob.glob(lp_dir + '/*.yml')

        for lp_file in lp_list:
            try:
                lp = LoggingPolicy(lp_file)
                lp.render_template("confluence")
                confluence_data = {
                    "title":
                    lp.fields["title"],
                    "spacekey":
                    self.space,
                    "parentid":
                    str(
                        ATCutils.confluence_get_page_id(
                            self.apipath, self.auth, self.space,
                            "Logging Policies")),
                    "confluencecontent":
                    lp.content,
                }

                res = ATCutils.push_to_confluence(confluence_data,
                                                  self.apipath, self.auth)
                if res == 'Page updated':
                    print("==> updated page: LP '" + lp.fields['title'] + "'")
                # print("Done: ", lp.fields['title'])
            except Exception as err:
                print(lp_file + " failed")
                print("Err message: %s" % err)
                print('-' * 60)
                traceback.print_exc(file=sys.stdout)
                print('-' * 60)
        print("[+] Logging Policies populated!")
def create_markdown_dirs():
    config = ATCutils.load_config('config.yml')
    base_dir = Path(
        config.get('md_name_of_root_directory', '../Atomic_Threat_Coverage'))

    target_dir_list = [
        'Detection_Rules', 'Logging_Policies', 'Data_Needed', 'Triggers',
        'Enrichments', 'Customers', 'Mitigation_Systems',
        'Mitigation_Policies', 'Hardening_Policies'
    ]

    for item in target_dir_list:
        (base_dir / item).mkdir(parents=True, exist_ok=True)
Пример #9
0
    def render_template(self, template_type):
        """Description
        template_type:
            - "markdown"
        """

        if template_type not in ["markdown"]:
            raise Exception("Bad template_type. Available values:" +
                            " [\"markdown\"]")

        # Point to the templates directory
        env = Environment(loader=FileSystemLoader('scripts/templates'))

        template = env.get_template('markdown_responseaction_template.md.j2')

        self.ra_parsed_file.update(
            {'description': self.ra_parsed_file.get('description').strip()})

        self.ra_parsed_file.update({
            'title':
            ATCutils.normalize_react_title(self.ra_parsed_file.get('title'))
        })

        stage_list = []
        stage = self.ra_parsed_file.get('stage')

        for rs_id, rs_name in rs_mapping.items():
            if ATCutils.normalize_rs_name(stage) == rs_name:
                stage_list.append((rs_id, rs_name))

        self.ra_parsed_file.update({'stage': stage_list})

        self.ra_parsed_file.update({
            'category':
            ATCutils.get_ra_category(self.ra_parsed_file.get('id'))
        })

        self.content = template.render(self.ra_parsed_file)
Пример #10
0
 def checkRA(self, stage):
     if self.rp_rule.get(stage):
         for rule in self.rp_rule.get(stage):
             try:
                 rtask = ATCutils.read_yaml_file(self.inputRA + rule +
                                                 ".yml")
             except OSError:
                 print("Response Action %s not existing\n" % rule)
                 continue
             self.task_prefix = int(self.task_prefix)
             self.task_prefix += 1
             task = THC.TheHiveTask(order=self.task_order)
             self.task_order += 1
             task.title = str(self.task_prefix) + " | " + \
                 str(rtask.get('title'))
             task.group = rtask.get('stage', 'Unknown stage')
             task.description = str(rtask.get('workflow'))
             self.case.tasks.append(task.return_dictionary())
             if rtask.get('linked_ra'):
                 self.task_prefix = float(self.task_prefix)
                 for linked_ra in rtask.get('linked_ra'):
                     try:
                         rtask = ATCutils.read_yaml_file(self.inputRA +
                                                         linked_ra + ".yml")
                     except OSError:
                         print("Response Action %s not existing\n" % rule)
                         continue
                     task = THC.TheHiveTask(order=self.task_order)
                     self.task_order += 1
                     self.task_prefix += 0.1
                     task.title = str(round(self.task_prefix, 1)) + \
                         " | " + str(rtask.get('title'))
                     task.title = str(round(self.task_prefix, 1)) + " | "\
                         + str(rtask.get("title"))
                     task.group = rtask.get('stage', 'Unknown stage')
                     task.description = str(rtask.get('workflow'))
                     self.case.tasks.append(task.return_dictionary())
Пример #11
0
    def triggers(self, tg_path):
        """Populate Triggers"""

        print("[*] Populating Triggers...")
        if tg_path:
            tg_list = glob.glob(tg_path + '*.yml')
        else:
            tg_list = glob.glob(ATCconfig.get("triggers_directory") +
                                '/T*/*.yaml')

        for tg_file in tg_list:
            try:
                tg = Triggers(tg_file)
                tg.render_template("confluence")
                title = tg.fields["attack_technique"] + ": " + \
                    te_mapping.get(tg.fields["attack_technique"])
                confluence_data = {
                    "title": title,
                    "spacekey": self.space,
                    "parentid": str(ATCutils.confluence_get_page_id(
                        self.apipath, self.auth, self.space, "Triggers")),
                    "confluencecontent": tg.content,
                }

                res = ATCutils.push_to_confluence(confluence_data, self.apipath,
                                            self.auth)
                if res == 'Page updated':
            	    print("==> updated page: TR '" + title + "'")
                # print("Done: ", tg.fields["attack_technique"])
            except Exception as err:
                print(tg_file + " failed")
                print("Err message: %s" % err)
                print('-' * 60)
                traceback.print_exc(file=sys.stdout)
                print('-' * 60)

        print("[+] Triggers populated!")
Пример #12
0
    def parse_into_fields(self, yaml_file):
        """Description"""

        # self.dn_fields contains parsed fields obtained from yaml file
        self.dn_fields = ATCutils.read_yaml_file(yaml_file)
        """Fill the fields with values. Put None if key not found"""
        self.title = self.dn_fields.get("title")
        self.description = self.dn_fields.get("description")
        self.loggingpolicy = self.dn_fields.get("loggingpolicy")
        self.mitigation_policy = self.dn_fields.get("mitigation_policy")
        self.platform = self.dn_fields.get("platform")
        self.type = self.dn_fields.get("type")
        self.channel = self.dn_fields.get("channel")
        self.provider = self.dn_fields.get("provider")
        self.fields = self.dn_fields.get("fields")
        self.sample = self.dn_fields.get("sample")
    def __init__(self):

        def get_techniques(threats):
            techniques = []
            for threat in threats:
                if not isinstance(threat.get('tags'), list):
                    continue
                tags = threat['tags']
        
                # iterate over all tags finding the one which starts from attack and has all digits after attack.t
                technique_ids = [f'T{tag[8:]}' for tag in tags if tag.startswith('attack') and tag[8:].isdigit()]
        
                # iterate again finding all techniques and removing attack. part from them
                tactics = [tag.replace('attack.', '').replace('_', '-')
                           for tag in tags if tag.startswith('attack') and not tag[8:].isdigit()]
                for technique_id in technique_ids:
                    for tactic in tactics:
                        techniques.append({
                            "techniqueID": technique_id,
                            "tactic": tactic,
                            "color": "#fcf26b",
                            "comment": "",
                            "enabled": True
        
                        })
            return techniques


        dr_dirs = ATCconfig.get('detection_rules_directories')
        dr_list = []
        for path in dr_dirs:
            dr_list.append(ATCutils.load_yamls(path))
        # flat dr_list
        dr_list = [dr for drs_from_path in dr_list for dr in drs_from_path]
        techniques = get_techniques(dr_list)
        NAVIGATOR_TEMPLATE['techniques'] = techniques
    
        filename = 'atc_attack_navigator_profile.json'
        exported_analytics_directory = \
            ATCconfig.get('exported_analytics_directory') + "/attack_navigator_profiles"
    
        with open(exported_analytics_directory + '/' + filename, 'w') as fp:
            json.dump(NAVIGATOR_TEMPLATE, fp)
        print(f'[+] Created {filename}')
        
Пример #14
0
    def convertRPToTemplate(self, file_input, output_file):

        self.rp_rule = ATCutils.read_yaml_file(file_input)

        self.case = THC.TheHiveCase()
        self.case.name = self.rp_rule.get('title')
        self.case.description = "Description:\n" + \
            str(self.rp_rule.get('description')) + \
            '\n\nWorkflow:\n' + str(self.rp_rule.get('workflow'))
        try:
            self.case.tags += self.rp_rule.get('tags')
        except TypeError:
            pass

        self.case.tlp = self.checkTLP(self.rp_rule.get('tlp'))
        self.case.pap = self.checkPAP(self.rp_rule.get('pap'))

        if self.args.prefix:
            self.case.prefix = self.args.prefix

        self.task_prefix = 0.0
        self.task_order = 0

        stages = [
            'preparation', 'identification', 'containment', 'eradication',
            'recovery', 'lessons_learned'
        ]

        for stage in stages:
            if stage in self.rp_rule.keys():
                self.checkRA(stage)
        try:
            with open(output_file, 'w') as f:
                f.write(self.case.json())
        except OSError:
            print("ERROR: No such directory %s" %
                  os.path.dirname(os.path.abspath(output_file)))
Пример #15
0
from scripts.atcutils import ATCutils
from scripts.attack_mapping import te_mapping, ta_mapping
from scripts.amitt_mapping import amitt_tactic_mapping, amitt_technique_mapping

from jinja2 import Environment, FileSystemLoader
import os
import subprocess
import re


# ########################################################################### #
# ########################### Detection Rule ################################ #
# ########################################################################### #

ATCconfig = ATCutils.load_config('config.yml')

env = Environment(loader=FileSystemLoader('scripts/templates'))

class DetectionRule:
    """Class for the Detection Rule entity"""

    def __init__(self, yaml_file, apipath=None, auth=None, space=None):
        """Init method"""

        # Init vars
        self.yaml_file = yaml_file

        # The name of the directory containing future markdown DetectionRules
        self.parent_title = "Detection_Rules"
Пример #16
0
    def __init__(self):

        dn_path = ATCconfig.get('data_needed_dir')
        lp_path = ATCconfig.get('logging_policies_dir')
        en_path = ATCconfig.get('enrichments_directory')
        rp_path = ATCconfig.get('response_playbooks_dir')
        ra_path = ATCconfig.get('response_actions_dir')
        cu_path = ATCconfig.get('customers_directory')

        cu_list = ATCutils.load_yamls(cu_path)
        dn_list = ATCutils.load_yamls(dn_path)
        lp_list = ATCutils.load_yamls(lp_path)
        ra_list = ATCutils.load_yamls(ra_path)
        rp_list = ATCutils.load_yamls(rp_path)
        enrichments_list = ATCutils.load_yamls(en_path)

        pivoting = []
        analytics = []
        result = []

        dr_dirs = ATCconfig.get('detection_rules_directories')

        print("[*] Iterating through Detection Rules")
        # Iterate through alerts and pathes to them

        for dr_path in dr_dirs:
            alerts, path_to_alerts = ATCutils.load_yamls_with_paths(dr_path)

            for alert, path in zip(alerts, path_to_alerts):
                if not isinstance(alert.get('tags'), list):
                    continue

                list_of_customers = []
                for specific_customer in cu_list:
                    if alert['title'] in specific_customer[
                            'detectionrule'] and specific_customer[
                                'customer_name'] not in list_of_customers:
                        list_of_customers.append(
                            specific_customer['customer_name'])

                if not isinstance(list_of_customers,
                                  list) or len(list_of_customers) == 0:
                    list_of_customers = ["None"]

                customer = ';'.join(list_of_customers)

                threats = [
                    tag for tag in alert['tags'] if tag.startswith('attack')
                ]
                tactics = [
                    f'{ta_mapping[threat][1]}: {ta_mapping[threat][0]}'
                    for threat in threats if threat in ta_mapping.keys()
                ]
                techniques = [
                    threat for threat in threats
                    if threat.startswith('attack.t')
                ]

                enrichments = [
                    er for er in enrichments_list
                    if er['title'] in alert.get('enrichment', [])
                ]
                dn_titles = ATCutils.main_dn_calculatoin_func(path)

                alert_dns = [
                    data for data in dn_list if data['title'] in dn_titles
                ]

                logging_policies = []

                for dn in alert_dns:

                    if 'loggingpolicy' in dn:
                        # If there are logging policies in DN that we havent added yet - add them
                        logging_policies.extend([
                            l for l in lp_list
                            if l['title'] in dn['loggingpolicy']
                            and l not in logging_policies
                        ])
                    # If there are no logging policices at all - make an empty one just to make one row in csv
                    if not isinstance(logging_policies,
                                      list) or len(logging_policies) == 0:
                        logging_policies = [{
                            'title': "-",
                            'eventID': [
                                -1,
                            ]
                        }]

                for dn in alert_dns:
                    pivot = [
                        dn['category'], dn['platform'], dn['type'],
                        dn['channel'], dn['provider'], dn['title'], '', ''
                    ]

                    for tactic in tactics:
                        for technique in techniques:
                            technique_name = technique.replace('attack.t', 'T') + ': ' +\
                                ATCutils.get_attack_technique_name_by_id(
                                    technique.replace('attack.', ''))
                            for lp in logging_policies:
                                rps = [
                                    rp for rp in rp_list
                                    if technique in rp['tags']
                                    or tactic in rp['tags']
                                ]
                                if len(rps) < 1:
                                    rps = [{'title': '-'}]
                                for rp in rps:
                                    ras_buf = []
                                    [
                                        ras_buf.extend(l) for l in rp.values()
                                        if isinstance(l, list)
                                    ]
                                    ras = [
                                        ra for ra in ras_buf
                                        if ra.startswith('RA')
                                    ]
                                    if len(ras) < 1:
                                        ras = ['title']
                                    #if len(rp) > 1:
                                    #todo
                                    for ra in ras:
                                        lp['title'] = lp['title'].replace(
                                            '\n', '')
                                        result.append([
                                            customer, tactic, technique_name,
                                            alert['title'], dn['category'],
                                            dn['platform'], dn['type'],
                                            dn['channel'], dn['provider'],
                                            dn['title'], lp['title'], '', '',
                                            rp['title'], ra
                                        ])

                    # pivoting.append(pivot)
                    for field in dn['fields']:
                        analytics.append([field] + pivot)

                for er in enrichments:
                    for dn in [
                            dnn for dnn in dn_list
                            if dnn['title'] in er.get('data_to_enrich', [])
                    ]:
                        pivot = [
                            dn['category'], dn['platform'], dn['type'],
                            dn['channel'], dn['provider'], dn['title'],
                            er['title'], ';'.join(er.get('requirements', []))
                        ]
                        for tactic in tactics:
                            for technique in techniques:
                                technique_name = technique.replace('attack.t', 'T') + ': ' + \
                                    ATCutils.get_attack_technique_name_by_id(
                                        technique.replace('attack.', ''))
                                for lp in logging_policies:
                                    lp['title'] = lp['title'].replace('\n', '')
                                    result.append([
                                        customer, tactic, technique_name,
                                        alert['title'], dn['category'],
                                        dn['platform'], dn['type'],
                                        dn['channel'], dn['provider'],
                                        dn['title'], lp['title'], er['title'],
                                        ';'.join(er.get('requirements',
                                                        [])), '-', '-'
                                    ])

                        # pivoting.append(pivot)
                        for field in er['new_fields']:
                            analytics.append([field] + pivot)

        analytics = []

        for dn in dn_list:

            if 'category' in dn:
                dn_category = dn['category']
            else:
                dn_category = "-"
            if 'platform' in dn:
                dn_platform = dn['platform']
            else:
                dn_platform = "-"
            if 'type' in dn:
                dn_type = dn['type']
            else:
                dn_type = "-"
            if 'channel' in dn:
                dn_channel = dn['channel']
            else:
                dn_channel = "-"
            if 'provider' in dn:
                dn_provider = dn['provider']
            else:
                dn_provider = "-"
            if 'title' in dn:
                dn_title = dn['title']
            else:
                dn_title = "-"

            pivot = [
                dn_category, dn_platform, dn_type, dn_channel, dn_provider,
                dn_title, '', ''
            ]
            for field in dn['fields']:
                analytics.append([field] + pivot)

        for er in enrichments_list:
            for dn in [
                    dnn for dnn in dn_list
                    if dnn['title'] in er.get('data_to_enrich', [])
            ]:
                pivot = [
                    dn['category'], dn['platform'], dn['type'], dn['channel'],
                    dn['provider'], dn['title'], er['title'],
                    ';'.join(er.get('requirements', []))
                ]
                for field in er['new_fields']:
                    analytics.append([field] + pivot)

        filename = 'analytics.csv'
        exported_analytics_directory = ATCconfig.get(
            'exported_analytics_directory')

        with open(exported_analytics_directory + '/' + filename,
                  'w',
                  newline='') as csvfile:
            # maybe need some quoting
            alertswriter = csv.writer(csvfile, delimiter=',')
            alertswriter.writerow([
                'customer', 'tactic', 'technique', 'detection_rule',
                'category', 'platform', 'type', 'channel', 'provider',
                'data_needed', 'logging policy', 'enrichment',
                'enrichment requirements', 'response playbook',
                'response action'
            ])
            for row in result:
                alertswriter.writerow(row)
        print(f'[+] Created {filename}')

        filename = 'pivoting.csv'
        exported_analytics_directory = ATCconfig.get(
            'exported_analytics_directory')

        with open(exported_analytics_directory + '/' + filename,
                  'w',
                  newline='') as csvfile:
            # maybe need some quoting
            alertswriter = csv.writer(csvfile, delimiter=',')
            alertswriter.writerow([
                'field', 'category', 'platform', 'type', 'channel', 'provider',
                'data_needed', 'enrichment', 'enrichment requirements'
            ])
            for row in analytics:
                alertswriter.writerow(row)

        print(f'[+] Created {filename}')
Пример #17
0
#!/usr/bin/env python3

from scripts.atcutils import ATCutils
from scripts.attack_mapping import te_mapping, ta_mapping

import csv
import sys
import getopt
from os import listdir
from os.path import isfile, join
from yaml.scanner import ScannerError

ATCconfig = ATCutils.read_yaml_file("config.yml")

HELP_MESSAGE = """Usage: python3 yamls2csv.py [OPTIONS]\n\n\n
        Possible options are --detectionrules_path, --dataneeded_path --loggingpolicies path
        Defaults are 
        dataneeded_path = ../data_needed/;
        loggingpolicies_path=../logging_policies/"""


class GenerateCSV:
    def __init__(self):

        dn_path = ATCconfig.get('data_needed_dir')
        lp_path = ATCconfig.get('logging_policies_dir')
        en_path = ATCconfig.get('enrichments_directory')
        rp_path = ATCconfig.get('response_playbooks_dir')
        ra_path = ATCconfig.get('response_actions_dir')
        cu_path = ATCconfig.get('customers_directory')
Пример #18
0
    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\"]")

        # Get proper template
        if template_type == "markdown":
            template = env.get_template('markdown_enrichments_template.md.j2')

            self.en_parsed_file.update({
                'description':
                self.en_parsed_file.get('description').strip()
            })
        elif template_type == "confluence":
            template = env.get_template(
                'confluence_enrichments_template.html.j2')

            self.en_parsed_file.update({
                'confluence_viewpage_url':
                ATCconfig.get('confluence_viewpage_url')
            })

            data_needed = self.en_parsed_file.get('data_needed')
            if data_needed:
                data_needed_with_id = []
                for dn in data_needed:
                    data_needed_id = str(
                        ATCutils.confluence_get_page_id(
                            self.apipath, self.auth, self.space, dn))
                    dn = (dn, data_needed_id)
                    data_needed_with_id.append(dn)

                self.en_parsed_file.update(
                    {'data_needed': data_needed_with_id})

            data_to_enrich = self.en_parsed_file.get('data_to_enrich')
            if data_to_enrich:
                data_to_enrich_with_id = []
                for de in data_to_enrich:
                    data_to_enrich_id = str(
                        ATCutils.confluence_get_page_id(
                            self.apipath, self.auth, self.space, de))
                    de = (de, data_to_enrich_id)
                    data_to_enrich_with_id.append(de)

                self.en_parsed_file.update(
                    {'data_to_enrich': data_to_enrich_with_id})

            requirements = self.en_parsed_file.get('requirements')
            if requirements:
                requirements_with_id = []
                for req in requirements:
                    requirements_id = str(
                        ATCutils.confluence_get_page_id(
                            self.apipath, self.auth, self.space, req))
                    req = (req, requirements_id)
                    requirements_with_id.append(req)

                self.en_parsed_file.update(
                    {'requirements': requirements_with_id})

            self.en_parsed_file.update({
                'description':
                self.en_parsed_file.get('description').strip()
            })
        # Render
        self.content = template.render(self.en_parsed_file)
Пример #19
0
    def parse_into_fields(self, yaml_file):
        """Description"""

        self.en_parsed_file = ATCutils.read_yaml_file(yaml_file)
Пример #20
0
        def get_customers():
            """ This fuction should be moved to ATCUtils or other class"""
            customers = ATCutils.load_yamls(
                ATCconfig.get('customers_directory'))

            return customers
Пример #21
0
#!/usr/bin/env python3

from scripts.atcutils import ATCutils
from scripts.attack_mapping import te_mapping, ta_mapping
from scripts.amitt_mapping import amitt_tactic_mapping, amitt_technique_mapping, amitt_mitigation_mapping

from jinja2 import Environment, FileSystemLoader
import os
import re

# ########################################################################### #
# ########################### Response Playboo ############################## #
# ########################################################################### #

ATCconfig = ATCutils.load_config("scripts/config.yml")


class ResponsePlaybook:
    """Class for the Playbook Actions entity"""
    def __init__(self, yaml_file):
        """Init method"""

        # Init vars
        self.yaml_file = yaml_file
        # The name of the directory containing future markdown Response_Playbooks
        self.parent_title = "Response_Playbooks"

        # Init methods
        self.parse_into_fields(self.yaml_file)

    def parse_into_fields(self, yaml_file):
    def __init__(self,
                 ra=False,
                 rp=False,
                 rs=False,
                 auto=False,
                 ra_path=False,
                 rp_path=False,
                 rs_path=False,
                 atc_dir=False,
                 init=False):
        """Init"""

        # Check if atc_dir provided
        if atc_dir:
            self.atc_dir = atc_dir
        else:
            self.atc_dir = ATCconfig.get('md_name_of_root_directory') + '/'

        # Main logic
        if auto:
            self.response_action(ra_path)
            self.response_playbook(rp_path)
            self.response_stage(rs_path)

        if ra:
            self.response_action(ra_path)

        if rp:
            self.response_playbook(rp_path)

        if rs:
            self.response_stage(rs_path)

        if ra_path:
            ras, ra_paths = ATCutils.load_yamls_with_paths(ra_path)
        else:
            ras, ra_paths = ATCutils.load_yamls_with_paths(
                ATCconfig.get('response_actions_dir'))

        if rp_path:
            rps, rp_paths = ATCutils.load_yamls_with_paths(rp_path)
        else:
            rps, rp_paths = ATCutils.load_yamls_with_paths(
                ATCconfig.get('response_playbooks_dir'))

        if rs_path:
            rss, rs_paths = ATCutils.load_yamls_with_paths(rs_path)
        else:
            rss, rs_paths = ATCutils.load_yamls_with_paths(
                ATCconfig.get('response_stages_dir'))

        ra_filenames = [
            ra_path.split('/')[-1].replace('.yml', '') for ra_path in ra_paths
        ]
        rp_filenames = [
            rp_path.split('/')[-1].replace('.yml', '') for rp_path in rp_paths
        ]
        rs_filenames = [
            rs_path.split('/')[-1].replace('.yml', '') for rs_path in rs_paths
        ]

        # Point to the templates directory
        env = Environment(loader=FileSystemLoader('scripts/templates'))

        # Get proper template
        template = env.get_template('mkdocs_config_template.md.j2')

        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)]

        playbooks = []

        data_to_render = {}

        for i in range(len(ras)):

            ra_updated_title = ras[i].get('id')\
                + ": "\
                + ATCutils.normalize_react_title(ras[i].get('title'))

            if "RA1" in ras[i]['id']:
                preparation.append((ra_updated_title, ra_filenames[i]))
            elif "RA2" in ras[i]['id']:
                identification.append((ra_updated_title, ra_filenames[i]))
            elif "RA3" in ras[i]['id']:
                containment.append((ra_updated_title, ra_filenames[i]))
            elif "RA4" in ras[i]['id']:
                eradication.append((ra_updated_title, ra_filenames[i]))
            elif "RA5" in ras[i]['id']:
                recovery.append((ra_updated_title, ra_filenames[i]))
            elif "RA6" in ras[i]['id']:
                lessons_learned.append((ra_updated_title, ra_filenames[i]))

        stages = [(stage_name.replace('_',
                                      ' ').capitalize(), sorted(stage_list))
                  for stage_name, stage_list in stages]

        for i in range(len(rps)):

            rp_updated_title = rps[i].get('id')\
                + ": "\
                + ATCutils.normalize_react_title(rps[i].get('title'))

            playbooks.append((rp_updated_title, rp_filenames[i]))

        rs_list = []

        for i in range(len(rss)):

            rs_title = rss[i].get('title')
            rs_id = rss[i].get('id')

            rs_list.append((rs_title, rs_id))

        data_to_render.update({'stages': stages})
        data_to_render.update({'playbooks': sorted(playbooks)})
        data_to_render.update({'rs_list': rs_list})

        content = template.render(data_to_render)
        try:
            ATCutils.write_file('mkdocs.yml', content)
            print("[+] Created mkdocs.yml")
        except:
            print("[-] Failed to create mkdocs.yml")
Пример #23
0
    def __init__(self):
        def get_customers():
            """ This fuction should be moved to ATCUtils or other class"""
            customers = ATCutils.load_yamls(
                ATCconfig.get('customers_directory'))

            return customers

        def find_rules_per_customer(customer, dr_list):
            dr_list_per_customer = [
                dr for dr_title in customer.get('detectionrule')
                for dr in dr_list if dr.get('title') == dr_title
            ]
            return dr_list_per_customer

        def get_techniques(threats):
            techniques = []
            for threat in threats:
                if not isinstance(threat.get('tags'), list):
                    continue
                tags = threat['tags']

                # iterate over all tags finding the one which starts from attack and has all digits after attack.t
                technique_ids = [
                    f'T{tag[8:]}' for tag in tags
                    if tag.startswith('attack') and tag[8:].isdigit()
                ]

                # iterate again finding all techniques and removing attack. part from them
                tactics = [
                    tag.replace('attack.', '').replace('_', '-')
                    for tag in tags
                    if tag.startswith('attack') and not tag[8:].isdigit()
                ]
                for technique_id in technique_ids:
                    for tactic in tactics:
                        techniques.append({
                            "techniqueID": technique_id,
                            "tactic": tactic,
                            "color": "#fcf26b",
                            "comment": "",
                            "enabled": True
                        })
            return techniques

        dr_dirs = ATCconfig.get('detection_rules_directories')
        dr_list = []
        for path in dr_dirs:
            dr_list.append(ATCutils.load_yamls(path))
        # flat dr_list
        dr_list = [dr for drs_from_path in dr_list for dr in drs_from_path]

        list_of_customers = get_customers()
        for customer in list_of_customers:
            rules = find_rules_per_customer(customer, dr_list)
            techniques = get_techniques(rules)

            tab_name = {"name": customer.get('customer_name')}
            NAVIGATOR_TEMPLATE.update(tab_name)
            NAVIGATOR_TEMPLATE['techniques'] = techniques

            filename = 'atc_attack_navigator_profile_' + \
                customer.get('title') + '.json'
            exported_analytics_directory = \
                ATCconfig.get('exported_analytics_directory') + \
                "/attack_navigator_profiles"

            with open(exported_analytics_directory + '/' + filename,
                      'w') as fp:
                json.dump(NAVIGATOR_TEMPLATE, fp)
            print(f'[+] Created {filename}')
Пример #24
0
    def parse_into_fields(self):
        """Description"""

        self.mp_parsed_file = ATCutils.read_yaml_file(self.yaml_file)
Пример #25
0
                                rs=args.responsestage,
                                init=args.init)
    elif args.react_stix:
        GenerateSTIX()
    elif args.react_navigator:
        GenerateNavigator()
    elif args.csv:
        GenerateCSV()
    elif args.td_navigator:
        GenerateDetectionNavigator()
    elif args.td_navigator_customers:
        GenerateDetectionNavigatorCustomers()
    elif args.es:
        GenerateESIndex()
    elif args.visualisations:
        ATCconfig = ATCutils.load_config("config.yml")
        ATCconfig_default = ATCutils.load_config("scripts/config.default.yml")
        if not args.vis_output_dir:
            analytics_generated = ATCconfig.get(
                "exported_analytics_directory",
                ATCconfig_default.get("exported_analytics_directory"))
            analytics_generated = analytics_generated if \
                analytics_generated[-1] == "/" else analytics_generated + "/"
            output_path = analytics_generated + "visualizations/"

            if not args.vis_output_file_name:
                output_name = ''.join(
                    random.choices(string.ascii_uppercase +
                                   string.ascii_lowercase + string.digits,
                                   k=20))
                # output_name += ".json"
Пример #26
0
    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\"]")

        # 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)
Пример #27
0
    def parse_into_fields(self):
        """Description"""

        # self.fields contains parsed fields obtained from yaml file
        self.fields = ATCutils.read_yaml_file(self.yaml_file)
Пример #28
0
#!/usr/bin/env python3

from scripts.atcutils import ATCutils

from jinja2 import Environment, FileSystemLoader
import os

# ########################################################################### #
# ########################### Enrichments ################################### #
# ########################################################################### #

ATCconfig = ATCutils.load_config("config.yml")

try:
    env = Environment(
        loader=FileSystemLoader('data/atc_data/scripts/templates'))
except:
    env = Environment(loader=FileSystemLoader('scripts/templates'))


class Enrichment:
    """Class for the Enrichments entity"""
    def __init__(self, yaml_file, apipath=None, auth=None, space=None):
        """Init method"""

        # Init vars
        self.yaml_file = yaml_file
        # The name of the directory containing future markdown LogginPolicy
        self.parent_title = "Enrichments"

        self.apipath = apipath
Пример #29
0
    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\"]")

        # 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)
                if query == "powershell":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + query + \
                        " --config  " + ATCconfig.get('powershell_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif query == "es-qs":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + query + \
                        " --config  " + ATCconfig.get('es-qs_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif query == "xpack-watcher":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + query + \
                        " --config  " + ATCconfig.get('xpack-watcher_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif query == "splunk":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + query + \
                        " --config  " + ATCconfig.get('splunk_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif query == "logpoint":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + query + \
                        " --config  " + ATCconfig.get('logpoint_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                else:
                    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 = subprocess.getoutput(cmd)

                # 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': sorted(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{4}$|attack\.t\d{4}\.\d{3}$)')
            # 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
                trigger_name, trigger_id = trigger
                # Check if a directory for a technique exists in atomic red team repo
                if os.path.isdir(ATCconfig.get('triggers_directory') + '/' + trigger_id):
                    triggers.append(trigger)

                else:
                    print(trigger_id + ": 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:
                if output == "powershell":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + output + \
                        " --config  " + ATCconfig.get('powershell_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif output == "es-qs":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + output + \
                        " --config  " + ATCconfig.get('es-qs_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif output == "xpack-watcher":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + output + \
                        " --config  " + ATCconfig.get('xpack-watcher_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif output == "splunk":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + output + \
                        " --config  " + ATCconfig.get('splunk_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                elif output == "logpoint":
                    cmd = ATCconfig.get('sigmac_path') + " -t " + output + \
                        " --config  " + ATCconfig.get('logpoint_sigma_config') + \
                        " --ignore-backend-errors " + self.yaml_file
                else:
                    cmd = ATCconfig.get('sigmac_path') + ' --shoot-yourself-in-the-foot -t "' + \
                        output + '" --ignore-backend-errors "' + self.yaml_file + '"'

                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]})
                det_queries[output] = str(query)[2:-3].replace("\\n", "\n")
                
            # 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)

            data_needed_with_id = []

            for data in sorted(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}(\.\d{3})?$')
            # 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("&", "&amp;")
        # Done in the template itself

        return True
Пример #30
0
    def render_template(self, template_type):
        """Description
        template_type:
            - "markdown"
        """

        if template_type not in ["markdown"]:
            raise Exception("Bad template_type. Available values:" +
                            " [\"markdown\"]")

        # Point to the templates directory
        env = Environment(loader=FileSystemLoader('scripts/templates'))

        # Get proper template
        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')

                    action_title = action.get('id')\
                        + ": "\
                        + ATCutils.normalize_react_title(action.get('title'))

                    stage_list.append(
                        (action_title, task, 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()})

        # Render
        self.content = template.render(self.rp_parsed_file)