예제 #1
0
def on_finish(container, summary):
    phantom.debug('on_finish() called')
    # This function is called after all actions are completed.
    # summary of all the action and/or all detals of actions
    # can be collected here.

    # summary_json = phantom.get_summary()
    # if 'result' in summary_json:
    # for action_result in summary_json['result']:
    # if 'action_run_id' in action_result:
    # action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
    # phantom.debug(action_results)

    qa_overall_result = phantom.get_data(key=keyfile, clear_data=False)
    qa_overall_result['message'] = qa_overall_result['message'] + '\n\n' + summary
    #

    #
    if qa_overall_result['qa_fail_count'] == 0:
        if expected_pass_count == qa_overall_result['qa_pass_count']:
            qa_overall_result['overall_result'] = 'Pass'  # set final pass/fail result in on_finish
    phantom.debug(
        'Overall Qa result: {} - Pass: {} - Fail: {} \nMessage: {}'.format(qa_overall_result['overall_result'],
                                                                           qa_overall_result['qa_pass_count'],
                                                                           qa_overall_result['qa_fail_count'],
                                                                           qa_overall_result['message'], ))
    phantom.save_data(qa_overall_result, key=keyfile)

    return
예제 #2
0
def Post_Start_Event_to_Splunk(action=None,
                               success=None,
                               container=None,
                               results=None,
                               handle=None,
                               filtered_artifacts=None,
                               filtered_results=None):
    phantom.debug('post_data_1() called')
    import platform
    import uuid

    # collect data for 'post_data_1' call
    formatted_data_1 = phantom.get_format_data(name='format_3')

    parameters = []

    splunk_status_index_list = phantom.collect(
        container, "artifact:*.cef.splunk_status_index")
    if len(splunk_status_index_list) > 0:
        splunk_status_index = str(splunk_status_index_list[0])
    else:
        splunk_status_index = "default"

    splunk_status_source_type_list = phantom.collect(
        container, "artifact:*.cef.splunk_status_source_type")
    if len(splunk_status_source_type_list) > 0:
        splunk_status_source_type = str(splunk_status_source_type_list[0])
    else:
        splunk_status_source_type = "advsim:atr"

    try:
        guid = phantom.collect(container, "artifact:*.cef.request")[0]
    except:
        guid = uuid.uuid4().hex
    playbook_info = phantom.get_playbook_info()
    phantom.save_data(guid, playbook_info[0]['id'])
    source = playbook_info[0]['name']
    data = {}
    data['msg'] = formatted_data_1
    data['guid'] = guid
    data['playbook_info'] = playbook_info[0]
    data_json = json.dumps(data)

    # build parameters list for 'post_data_1' call
    parameters.append({
        'index': splunk_status_index,
        'host': platform.node(),
        'source_type': splunk_status_source_type,
        'data': data_json,
        'source': source,
    })

    phantom.act("post data",
                parameters=parameters,
                app={"name": 'Splunk'},
                callback=decision_2,
                name="Post_Start_Event_to_Splunk")

    return
def pin_1(action=None,
          success=None,
          container=None,
          results=None,
          handle=None,
          filtered_artifacts=None,
          filtered_results=None):
    import random
    phantom.debug('pin_1() called')

    # collect data for 'pin_to_hud_6' call
    dest_ip_artifacts = filter(
        lambda x: x[0],
        phantom.collect2(container=container,
                         datapath=['artifact:*.cef.destinationAddress']))
    sorc_ip_artifacts = filter(
        lambda x: x[0],
        phantom.collect2(container=container,
                         datapath=['artifact:*.cef.sourceAddress']))

    styles = set(["white", "red", "purple"])

    pin_name = pin_name_mangle("pin_1", container)
    pin_id = phantom.get_data(pin_name)

    if not pin_id:
        ret_val, message, pin_id = phantom.pin(
            container=container,
            message="Affected IPs",
            data=str(len(dest_ip_artifacts) + len(sorc_ip_artifacts)),
            pin_type="card_medium",
            pin_style="white")
        phantom.debug("new pin_1")
    else:
        style = random.sample(styles, 1)[0]
        phantom.debug(style)
        ret_val, message = phantom.update_pin(
            pin_id,
            message="Affected IPs",
            data=str(len(dest_ip_artifacts) + len(sorc_ip_artifacts)),
            pin_style=style)

    if ret_val:
        phantom.save_data(pin_id, pin_name)

    # set container properties for:
    update_data = {}

    phantom.update(container, update_data)

    return
def pin_2(action=None,
          success=None,
          container=None,
          results=None,
          handle=None,
          filtered_artifacts=None,
          filtered_results=None):
    import random
    phantom.debug('pin_2() called')

    # collect data for 'pin_to_hud_6' call
    dest_username = filter(
        lambda x: x[0],
        phantom.collect2(container=container,
                         datapath=['artifact:*.cef.destinationUserName']))
    sorc_username = filter(
        lambda x: x[0],
        phantom.collect2(container=container,
                         datapath=['artifact:*.cef.sourceUserName']))

    styles = set(["white", "red", "purple"])
    pin_name = pin_name_mangle("pin_2", container)
    pin_id = phantom.get_data(pin_name)

    if not pin_id:
        ret_val, message, pin_id = phantom.pin(
            container=container,
            message="Affected Users",
            data=str(len(dest_username) + len(sorc_username)),
            pin_type="card_medium",
            pin_style="purple")
        phantom.debug("new pin_2")
    else:
        # Delete and remake this one, for the sake of demonstration
        ret_val, message = phantom.delete_pin(pin_id)
        ret_val, message, pin_id = phantom.pin(
            container=container,
            message="Affected Users",
            data=str(len(dest_username) + len(sorc_username)),
            pin_type="card_medium",
            pin_style=random.sample(styles, 1)[0])

    if ret_val:
        phantom.save_data(pin_id, pin_name)
    # set container properties for:
    update_data = {}

    phantom.update(container, update_data)

    return
예제 #5
0
def on_start(incident):
    # lets do VT lookup of file hashes in the artifacts of an incident
    params = []
    hashes = list(
        set(phantom.collect(incident, 'artifact:*.cef.fileHash', scope='all')))
    if len(hashes) > 0:
        for filehash in hashes:
            params.append({'hash': filehash})
        phantom.act("file reputation", parameters=params, callback=generic_cb)

    # lets do geo lookup of attacker IPs
    params = []
    attacker_ips = phantom.attacker_ips(incident, scope='all')
    if len(attacker_ips) > 0:
        for ip in attacker_ips:
            params.append({'ip': ip})

        key = phantom.save_data(str(params))

        phantom.act("geolocate ip",
                    parameters=params,
                    callback=generic_cb,
                    handle=key)

    return
예제 #6
0
def _save_data(qa_pass_count=0, qa_fail_count=0, qa_overall_result="Fail", message="", init=False, offset=0):
    if init:
        if message == "":
            message = 'At on_start'
        qa_overall_result = {'qa_pass_count': 0, 'qa_fail_count': 0, 'overall_result': 'Fail', 'message': message}
        phantom.save_data(qa_overall_result, key=keyfile)

    else:
        with padlock:
            qa_overall_result = phantom.get_data(key=keyfile, clear_data=False)
            if len(message) > 0:
                message = "{}():{}> {}".format(inspect.stack()[1 + offset][3], inspect.stack()[1 + offset][2], message)
                phantom.debug(message)
                qa_overall_result['message'] += "\n" + message
            qa_overall_result['qa_pass_count'] += qa_pass_count
            qa_overall_result['qa_fail_count'] += qa_fail_count
            phantom.save_data(qa_overall_result, key=keyfile)
def pin_3(action=None,
          success=None,
          container=None,
          results=None,
          handle=None,
          filtered_artifacts=None,
          filtered_results=None):
    import random
    phantom.debug('pin_3() called')

    # collect data for 'pin_to_hud_6' call
    dest_domain = filter(
        lambda x: x[0],
        phantom.collect2(container=container,
                         datapath=['artifact:*.cef.destinationDnsDomain']))

    pin_name = pin_name_mangle("pin_3", container)

    try:
        most_rcnt_domain = dest_domain[0][0]
    except:
        pass
    else:
        pin_id = phantom.get_data(pin_name)
        if not pin_id:
            ret_val, message, pin_id = phantom.pin(
                container=container,
                message="Most Recent Domain",
                data=most_rcnt_domain,
                pin_type="card_medium",
                pin_style="red")
            phantom.debug("new pin_3")
        else:
            ret_val, message = phantom.update_pin(pin_id,
                                                  message="Most Recent Domain",
                                                  data=most_rcnt_domain,
                                                  pin_type="card_medium",
                                                  pin_style="red")
        if ret_val:
            phantom.save_data(pin_id, pin_name)

    # set container properties for:
    update_data = {}

    phantom.update(container, update_data)
    return
예제 #8
0
def on_start(email):
    #
    #phantom.debug('Email container data:\n {}\n\n'.format(email))
    email_to = "email_to@my_enterprise.com"
    email_from = "*****@*****.**"
    smtp_asset = "smtp"
    # these keys are used to save persistent data across the playbook,
    # they must be unique by rule run ID, otherwise its possible the data 
    # could be clobbered in another playbook running at the same time
    setupkey = 'setup_data' + str(email['current_rule_run_id'])
    collectkey = 'collect_data' + str(email['current_rule_run_id'])
    phantom.save_data([email_to, email_from, smtp_asset], key=setupkey)
    #
    collected_results = dict()
    collected_vault_items = dict()
    container_owner = "None"
    container_url = phantom.get_base_url() + 'container/' + str(email['id'])
    ##
    # we needed to get the vault_id for the email attachment to be detonated and pass that to the detonate action
    # so we use phantom.collect to grab the cef field (cs6) where we place the vault_id on the artifact
    vaultid = phantom.collect(email, 'artifact:*.cef.cs6', scope='new')
    #
    if len(vaultid) > 0:  # we have at least one item to process
        # lets grab the owner of the container and make it something useful if blank
        if email['owner'] == '':
            container_owner = 'None'
        else:
            container_owner = email['owner']
        phantom.debug('url: {}'.format(phantom.get_base_url()))
        email_body = "\nStarted file detonations on container_id: {} - Owner: {}\nURL: {}\nvault_item_info:\n".format(email['id'], container_owner, container_url)
        for vault_item in vaultid:
            vaultinfo = phantom.get_vault_item_info(vault_item)
            for vault_item_info in vaultinfo:
                collected_vault_items[vault_item] = vault_item_info
                email_body = email_body + pprint.pformat(vault_item_info, indent=4) + '\n'
            phantom.act('detonate file', parameters=[{'vault_id':vault_item}], assets=["threatgrid"], callback=detonate_file_cb)
        email_subject = "Running: Detonating files from ingest"
        # save modified data
        phantom.save_data([collected_results, collected_vault_items, container_owner], key=collectkey)
        # send email
        phantom.act('send email', parameters=[{ "from" : email_from,  "to" : email_to,  "subject" : email_subject,  "body" : email_body }], assets=[smtp_asset], callback=send_email_cb)
    else: # no artifacts run on
        phantom.debug('No artifacts to process, ending on_start without running any actions. \n{}'.format(email))

    return
예제 #9
0
def detonate_file_cb(action, success, email, results, handle):
    collectkey = 'collect_data' + str(email['current_rule_run_id'])
    if not success:
        phantom.debug("Error running detonate action.\n{}".format(json.dumps(results)))
        return

    # grab just the results url from the threatgrid return data, perhaps send the entire results dict
    # later as an email attachment?
    #result_url = results[0]['action_results'][0]['summary']['results_url']
    # get the app run ID, and use it as a key to the dictionary we build with results
    app_run_id = results[0]['app_run_id']
    collected_results, collected_vault_items, container_owner = phantom.get_data(collectkey, clear_data=False)
    collected_results[app_run_id] = dict()
    collected_results[app_run_id]['asset'] = results[0]['asset']
    collected_results[app_run_id]['message'] = results[0]['message']
    collected_results[app_run_id]['summary'] = results[0]['summary']
    collected_results[app_run_id]['detonate_summary'] =  results[0]['action_results'][0]['summary']
    phantom.save_data([collected_results, collected_vault_items, container_owner], key=collectkey)

    return
예제 #10
0
def get_system_info_1(action=None,
                      success=None,
                      container=None,
                      results=None,
                      handle=None,
                      filtered_artifacts=None,
                      filtered_results=None):

    #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))

    # collect data for 'get_system_info_1' call
    filtered_container_data = phantom.collect2(
        container=container,
        datapath=[
            'filtered-artifact:*.cef.sourceAddress', 'filtered-artifact:*.id'
        ],
        filter_artifacts=filtered_artifacts)
    phantom.save_data(filtered_container_data, key="rkitdata")
    parameters = []

    # build parameters list for 'get_system_info_1' call
    for filtered_container_item in filtered_container_data:
        if filtered_container_item[0]:
            parameters.append({
                'ip_hostname': filtered_container_item[0],
            })

    if parameters:
        phantom.act("get system info",
                    parameters=parameters,
                    assets=['carbonblack'],
                    callback=Send_Email_malicious,
                    name="get_system_info_1")
    else:
        phantom.error(
            "'get_system_info_1' will not be executed due to lack of parameters"
        )

    return
예제 #11
0
def on_start(incident):
    # lets do VT lookup of file hashes in the artifacts of an incident
    params = []
    hashes = list(set(phantom.collect(incident, 'artifact:*.cef.fileHash', scope='all')))
    if len(hashes) > 0:
        for filehash in hashes:
            params.append({'hash':filehash})
        phantom.act("file reputation", parameters=params, callback=generic_cb)

    # lets do geo lookup of attacker IPs
    params = []
    attacker_ips = phantom.attacker_ips(incident, scope='all')
    if len(attacker_ips) > 0:
        for ip in attacker_ips:
            params.append({'ip':ip})

        key = phantom.save_data(str(params))

        phantom.act("geolocate ip", parameters=params, callback=generic_cb, handle=key)

    return
def pin_4(action=None,
          success=None,
          container=None,
          results=None,
          handle=None,
          filtered_artifacts=None,
          filtered_results=None):
    phantom.debug('pin_4() called')
    artifacts = phantom.collect(container=container,
                                datapath='artifacts:*',
                                scope='all')
    artifacts = sorted(artifacts, key=lambda x: x['update_time'], reverse=True)

    ioc_count = 0
    most_recent_ioc = None
    ioc_types = set()

    for artifact in artifacts:
        for key, value in artifact['cef'].iteritems():
            value = str(value)
            ret, ioc_type = is_ioc(value)
            if ret:
                if most_recent_ioc is None:
                    most_recent_ioc = value
                ioc_count += 1
                ioc_types.add(ioc_type)

    pin4_name = pin_name_mangle("pin_4", container)
    pin5_name = pin_name_mangle("pin_5", container)
    pin6_name = pin_name_mangle("pin_6", container)

    pin_id_ioc_cnt = phantom.get_data(pin4_name)
    pin_id_ioc_rct = phantom.get_data(pin5_name)
    pin_id_ioc_type = phantom.get_data(pin6_name)

    if not pin_id_ioc_cnt:
        ret_val, message, pin_id_ioc_cnt = phantom.pin(container=container,
                                                       message="IOC Count",
                                                       data=str(ioc_count),
                                                       pin_type="card_medium",
                                                       pin_style="white")
    else:
        ret_val, message = phantom.update_pin(pin_id_ioc_cnt,
                                              message="IOC Count",
                                              data=str(ioc_count),
                                              pin_type="card_medium",
                                              pin_style="red")
    if ret_val:
        phantom.save_data(pin_id_ioc_cnt, pin4_name)

    if ioc_count:
        if not pin_id_ioc_rct:
            ret_val, message, pin_id_ioc_rct = phantom.pin(
                container=container,
                message="Most Recent IOC",
                data=most_recent_ioc,
                pin_type="card_medium",
                pin_style="purple")
        else:
            ret_val, message = phantom.update_pin(pin_id_ioc_rct,
                                                  message="Most Recent IOC",
                                                  data=most_recent_ioc,
                                                  pin_type="card_medium",
                                                  pin_style="purple")
        if ret_val:
            phantom.save_data(pin_id_ioc_rct, pin5_name)

        if not pin_id_ioc_type:
            ret_val, message, pin_id_ioc_type = phantom.pin(
                container=container,
                message="IOC Types",
                data=", ".join(ioc_types))
        else:
            ret_val, message = phantom.update_pin(pin_id_ioc_type,
                                                  message="IOC Types",
                                                  data=", ".join(ioc_types))
        if ret_val:
            phantom.save_data(pin_id_ioc_type, pin6_name)
    return