def detonate_file_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('detonate_file_1() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) extract_attachment_info__attachment_file_name = json.loads( phantom.get_run_data( key='extract_attachment_info:attachment_file_name')) extract_attachment_info__vault_id = json.loads( phantom.get_run_data(key='extract_attachment_info:vault_id')) # collect data for 'detonate_file_1' call parameters = [] # build parameters list for 'detonate_file_1' call parameters.append({ 'file_name': extract_attachment_info__attachment_file_name, 'vault_id': extract_attachment_info__vault_id, }) phantom.act("detonate file", parameters=parameters, assets=['cuckoo'], callback=detonate_file_1_callback, name="detonate_file_1") return
def update_case(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('update_case() called') get_pins_body = phantom.collect2(container=container, datapath=['get_pins:action_result.data.*.response_body'], action_results=results) # get the necessary run_data fuzzy_matched_access_points = json.loads(phantom.get_run_data(key='fuzzy_matched_access_points')) live_case_id = int(phantom.get_run_data(key='live_case_id')) # delete all the existing pins to prevent duplicates for pin in get_pins_body[0][0]['data']: phantom.delete_pin(int(pin['id'])) # add a pin for each ap that fuzzy-matched the greylist for ap in fuzzy_matched_access_points: if ap['is_escalated']: phantom.pin(container=live_case_id, message=ap['signal_strength'], data=ap['mac_address'], pin_type="card_medium", pin_style="red") phantom.add_artifact( container=live_case_id, raw_data={}, cef_data=ap, label='wireless', name='suspicious access point detection', severity='high', identifier=None, artifact_type='network') decision_1(container=container) return
def cf_rba_master_dynamic_prompt_pairing_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug('cf_rba_master_dynamic_prompt_pairing_1() called') legacy_custom_function_result_0 = [ [ json.loads(phantom.get_run_data(key="get_run_data:responses")), json.loads(phantom.get_run_data(key="get_run_data:output")), ], ] parameters = [] for item0 in legacy_custom_function_result_0: parameters.append({ 'response': item0[0], 'input_json': item0[1], }) ################################################################################ ## Custom Code Start ################################################################################ parameters = [] responses = legacy_custom_function_result_0[0][1][0] input_json = json.loads(legacy_custom_function_result_0[0][0]) incrementer = 0 for item in input_json: parameters.append({ 'input_json': item, 'response': responses[incrementer] }) incrementer += 1 #### ################################################################################ ## Custom Code End ################################################################################ # call custom function "rba-master/dynamic_prompt_pairing", returns the custom_function_run_id phantom.custom_function( custom_function='rba-master/dynamic_prompt_pairing', parameters=parameters, name='cf_rba_master_dynamic_prompt_pairing_1', callback=cf_rba_master_dynamic_prompt_pairing_1_callback) return
def delete_files(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("delete_files() called") # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) ################################################################################ # Iterate through host and deletion command. Contains custom code. ################################################################################ generate_deletion_commands__deletion_command = json.loads( phantom.get_run_data( key="generate_deletion_commands:deletion_command")) generate_deletion_commands__host = json.loads( phantom.get_run_data(key="generate_deletion_commands:host")) parameters = [] if generate_deletion_commands__host is not None: parameters.append({ "command": generate_deletion_commands__deletion_command, "ip_hostname": generate_deletion_commands__host, }) ################################################################################ ## Custom Code Start ################################################################################ parameters = [] for del_cmd, host in zip(generate_deletion_commands__deletion_command, generate_deletion_commands__host): parameters.append({ "command": del_cmd, "ip_hostname": host, }) ################################################################################ ## Custom Code End ################################################################################ phantom.act("execute program", parameters=parameters, name="delete_files", assets=["ssh"], callback=join_dedup_hostnames) return
def on_finish(container, summary): phantom.debug("on_finish() called") # Added custom code to overcome bug with on_finish trying to call outputs that may not exist process_notes__note_title = phantom.get_run_data( key="process_notes:note_title") process_notes__note_content = phantom.get_run_data( key="process_notes:note_content") if process_notes__note_title: process_notes__note_title = json.loads(process_notes__note_title) if process_notes__note_content: process_notes__note_content = json.loads(process_notes__note_content) output = { "note_title": process_notes__note_title, "note_content": process_notes__note_content, } ################################################################################ ## Custom Code Start ################################################################################ # Error handling in case of playbook not being able to find investigative playbooks list_investigate_playbooks_data = phantom.collect2( container=container, datapath=[ "list_investigate_playbooks:custom_function_result.data.*.full_name" ]) list_investigate_playbooks_data___full_name = [ item[0] for item in list_investigate_playbooks_data if item[0] ] if not list_investigate_playbooks_data___full_name: raise RuntimeError("Unable to find investigate type playbooks.") # This function is called after all actions are completed. # summary of all the action and/or all details 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) ################################################################################ ## Custom Code End ################################################################################ phantom.save_playbook_output_data(output=output) return
def get_entity_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug('get_entity_3() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) DedupeListEntries__new_list = json.loads( phantom.get_run_data(key='DedupeListEntries:new_list')) # collect data for 'get_entity_3' call parameters = [] # build parameters list for 'get_entity_3' call for entity_title in DedupeListEntries__new_list: parameters.append({ 'entity_title': entity_title, }) phantom.act(action="get entity", parameters=parameters, assets=['splunk itsi'], name="get_entity_3") return
def send_email_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('send_email_1() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) custom_function_2__container_email = json.loads(phantom.get_run_data(key='custom_function_2:container_email')) # collect data for 'send_email_1' call formatted_data_1 = phantom.get_format_data(name='format_1') parameters = [] # build parameters list for 'send_email_1' call parameters.append({ 'body': formatted_data_1, 'from': "*****@*****.**", 'attachments': "", 'to': custom_function_2__container_email, 'cc': "", 'bcc': "", 'headers': "", 'subject': "New Case Created", }) phantom.act("send email", parameters=parameters, assets=['smtp'], name="send_email_1", parent_action=action) return
def url_reputation_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('url_reputation_1() called') Parsed_Proofpoint_URL__url_parsed = json.loads( phantom.get_run_data(key='Parsed_Proofpoint_URL:url_parsed')) # collect data for 'url_reputation_1' call parameters = [] # build parameters list for 'url_reputation_1' call parameters.append({ 'url': Parsed_Proofpoint_URL__url_parsed, }) phantom.act("url reputation", parameters=parameters, assets=['phishtank'], callback=filter_2, name="url_reputation_1") return
def I_want_the_data(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('I_want_the_data() called') get_object_data__value = json.loads( phantom.get_run_data(key='get_object_data:value')) ################################################################################ ## Custom Code Start ################################################################################ # Write your custom code here... phantom.debug("========================================") phantom.debug("I got this: %s" % get_object_data__value) phantom.debug("========================================") ################################################################################ ## Custom Code End ################################################################################ return
def send_failed_playbook_email(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('send_failed_playbook_email() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) playbook_email_body__body_format = json.loads(phantom.get_run_data(key='playbook_email_body:body_format')) # collect data for 'send_failed_playbook_email' call formatted_data_1 = phantom.get_format_data(name='subject_body') parameters = [] # build parameters list for 'send_failed_playbook_email' call parameters.append({ 'body': playbook_email_body__body_format, 'from': "*****@*****.**", 'attachments': "", 'to': "*****@*****.**", 'cc': "", 'bcc': "", 'headers': "", 'subject': formatted_data_1, }) phantom.act("send email", parameters=parameters, assets=['smtp'], name="send_failed_playbook_email") return
def domain_intelligence_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('domain_intelligence_1() called') deduplicate_inputs__domain = json.loads( phantom.get_run_data(key='deduplicate_inputs:domain')) # collect data for 'domain_intelligence_1' call parameters = [] # build parameters list for 'domain_intelligence_1' call parameters.append({ 'domain': deduplicate_inputs__domain, }) phantom.act("domain intelligence", parameters=parameters, assets=['recorded_future'], callback=join_format_prompt_question, name="domain_intelligence_1") return
def summary_note(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("summary_note() called") ################################################################################ # Leave a summary note ################################################################################ format_custom_note__output = json.loads( phantom.get_run_data(key="format_custom_note:output")) ################################################################################ ## Custom Code Start ################################################################################ ################################################################################ ## Custom Code End ################################################################################ phantom.add_note(container=container, content=format_custom_note__output, note_format="markdown", note_type="general", title="SSH Log4j Response") return
def merge_selected(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("merge_selected() called") id_value = container.get("id", None) process_responses__container_list = json.loads(phantom.get_run_data(key="process_responses:container_list")) parameters = [] parameters.append({ "workbook": None, "container_list": process_responses__container_list, "close_containers": True, "target_container": id_value, }) ################################################################################ ## Custom Code Start ################################################################################ # Write your custom code here... ################################################################################ ## Custom Code End ################################################################################ phantom.custom_function(custom_function="community/container_merge", parameters=parameters, name="merge_selected", callback=merge_selected_callback) return
def on_finish(container, summary): phantom.debug("on_finish() called") format_note__note_content = json.loads(phantom.get_run_data(key="format_note:note_content")) output = { "note_title": "TruSTAR Indicator Enrichment", "note_content": format_note__note_content, } ################################################################################ ## Custom Code Start ################################################################################ # This function is called after all actions are completed. # summary of all the action and/or all details 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) ################################################################################ ## Custom Code End ################################################################################ phantom.save_playbook_output_data(output=output) return
def playbook_wait(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("playbook_wait() called") ################################################################################ # Custom code block operating as a join function for dynamic playbook calls. ################################################################################ decide_and_launch_playbooks__names = json.loads( phantom.get_run_data(key="decide_and_launch_playbooks:names")) ################################################################################ ## Custom Code Start ################################################################################ if phantom.completed(playbook_names=decide_and_launch_playbooks__names): process_notes(container=container) # return early to avoid moving to next block return ################################################################################ ## Custom Code End ################################################################################ process_notes(container=container) return
def block_ip_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('block_ip_1() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) deduplicate_inputs__ip = json.loads( phantom.get_run_data(key='deduplicate_inputs:ip')) # collect data for 'block_ip_1' call parameters = [] # build parameters list for 'block_ip_1' call parameters.append({ 'ip': deduplicate_inputs__ip, }) phantom.act("block ip", parameters=parameters, assets=['cisco_firepower'], name="block_ip_1") return
def block_domain_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('block_domain_1() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) deduplicate_inputs__domain = json.loads( phantom.get_run_data(key='deduplicate_inputs:domain')) # collect data for 'block_domain_1' call parameters = [] # build parameters list for 'block_domain_1' call parameters.append({ 'disable_safeguards': False, 'domain': deduplicate_inputs__domain, }) phantom.act("block domain", parameters=parameters, assets=['opendns_umbrella'], name="block_domain_1") return
def select_response_plan(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("select_response_plan() called") # set user and message variables for phantom.prompt call user = json.loads(phantom.get_run_data(key='get_effective_user:username')) message = """Splunk SOAR has loaded all available response plans\n - Only Playbooks with tags "response_option" are shown.""" # Playbooks list playbook_list = phantom.collect2(container=container, datapath=["list_response_playbooks:custom_function_result.data.*.full_name"], action_results=results) playbook_list = [item[0] for item in playbook_list] playbook_list.append("Do Nothing") #responses: response_types = [ { "prompt": "Response Plan", "options": { "type": "list", "choices": playbook_list }, } ] phantom.prompt2(container=container, user=user, message=message, respond_in_mins=30, name="select_response_plan", response_types=response_types, callback=user_response_decision) return
def query_connections(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug('query_connections() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) multi_connection_query_construct__query = json.loads( phantom.get_run_data(key='multi_connection_query_construct:query')) # collect data for 'query_connections' call parameters = [] # build parameters list for 'query_connections' call parameters.append({ 'query': multi_connection_query_construct__query, 'command': "search", 'display': "", 'parse_only': False, }) phantom.act(action="run query", parameters=parameters, assets=['splunk-demo'], callback=filter_nonzero_bytes, name="query_connections") return
def create_containers(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('create_containers() called') read_list__peer_list = json.loads( phantom.get_run_data(key='read_list:peer_list')) ################################################################################ ## Custom Code Start ################################################################################ # Write your custom code here... for server in read_list__peer_list: if server[2] in ["critical"]: phantom.debug("%s is priority %s" % (server[0], server[2])) status, message, cid = phantom.create_container( name="Possible server malware", label="events") #phantom.set_severity(cid, "high") phantom.add_artifact(container=cid, raw_data={}, cef_data={"sourceAddress": server[0]}, label="infection", name="Possibly infected host", severity="high", artifact_type="host") ################################################################################ ## Custom Code End ################################################################################ return
def run_source_dest_query(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug('run_source_dest_query() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) IP_regex_and_format_source_dest_query__query = json.loads( phantom.get_run_data( key='IP_regex_and_format_source_dest_query:query')) # collect data for 'run_source_dest_query' call parameters = [] # build parameters list for 'run_source_dest_query' call parameters.append({ 'query': IP_regex_and_format_source_dest_query__query, 'command': "search", 'display': "", 'parse_only': False, }) phantom.act(action="run query", parameters=parameters, assets=['splunk-demo-main'], callback=If_traffic_between_the_two_units, name="run_source_dest_query") return
def join_send_deny_email_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('join_send_deny_email_2() called') # if the joined function has already been called, do nothing if phantom.get_run_data(key='join_send_deny_email_2_called'): return # check if all connected incoming actions are done i.e. have succeeded or failed if phantom.actions_done( ['virustotal_url_reputation', 'webpulse_url_reputation']): # save the state that the joined function has now been called phantom.save_run_data(key='join_send_deny_email_2_called', value='send_deny_email_2') # call connected block "send_deny_email_2" send_deny_email_2(container=container, handle=handle) return
def save_object_data(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('save_object_data() called') input_parameter_0 = "my_key" I_have_some_data__my_data = json.loads( phantom.get_run_data(key='I_have_some_data:my_data')) ################################################################################ ## Custom Code Start ################################################################################ # Write your custom code here... phantom.save_object(key=input_parameter_0, value={'value': "'" + I_have_some_data__my_data + "'"}, auto_delete=True, container_id=container['id']) ################################################################################ ## Custom Code End ################################################################################ get_object_data(container=container) return
def check_whitelist(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('check_whitelist() called') parsed_access_points = json.loads(phantom.get_run_data(key='parsed_access_points')) success, message, whitelist = phantom.get_list(list_name='Example Company WiFi ESSID Whitelist') whitelist_filtered_access_points = [ ap for ap in parsed_access_points if ( # all ESSIDs that aren't in the whitelist are suspicious [ap["ESSID"]] not in whitelist or # all non-WPA2 access points are suspicious 'WPA2' not in ap['security_protocol'] ) ] message = 'out of the {} access points identified by the scan, {} matched the whitelist and are being ignored'.format(len(parsed_access_points), len(parsed_access_points) - len(whitelist_filtered_access_points)) phantom.debug(message) live_comment(message) phantom.save_run_data(value=json.dumps(whitelist_filtered_access_points), key='whitelist_filtered_access_points') check_greylist() return
def join_set_status_set_severity_set_sensitivity_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None): phantom.debug('join_set_status_set_severity_set_sensitivity_1() called') # if the joined function has already been called, do nothing if phantom.get_run_data( key='join_set_status_set_severity_set_sensitivity_1_called'): return # check if all connected incoming playbooks, actions, or custom functions are done i.e. have succeeded or failed if phantom.completed(action_names=['update_ticket_3']): # save the state that the joined function has now been called phantom.save_run_data( key='join_set_status_set_severity_set_sensitivity_1_called', value='set_status_set_severity_set_sensitivity_1') # call connected block "set_status_set_severity_set_sensitivity_1" set_status_set_severity_set_sensitivity_1(container=container, handle=handle) return
def check_greylist(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('check_greylist() called') edit_distance_threshold = 5 success, message, potentials = phantom.get_list(list_name='Potential Rogue Access Point ESSIDs') whitelist_filtered_access_points = json.loads(phantom.get_run_data(key='whitelist_filtered_access_points')) scanned_ESSIDs = [ap['ESSID'] for ap in whitelist_filtered_access_points] # compare each ESSID against each potential evil twin and escalate those with a sufficiently small edit distance matches = 0 for ap in whitelist_filtered_access_points: ap['is_escalated'] = False ap['matched_rule'] = None for potential in potentials: if edit_distance(ap['ESSID'], potential[0]) < edit_distance_threshold: ap['is_escalated'] = True ap['matched_rule'] = potential matches += 1 break message = '{} out of {} access points fuzzy-matched "Potential Rogue Access Point ESSIDs"'.format( matches, len(whitelist_filtered_access_points)) phantom.debug(message) live_comment(message) phantom.save_run_data(value=json.dumps(whitelist_filtered_access_points), key='fuzzy_matched_access_points') get_pins() return
def detonate_url_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('detonate_url_1() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) Parsed_Proofpoint_URL__url_parsed = json.loads( phantom.get_run_data(key='Parsed_Proofpoint_URL:url_parsed')) # collect data for 'detonate_url_1' call parameters = [] # build parameters list for 'detonate_url_1' call parameters.append({ 'url': Parsed_Proofpoint_URL__url_parsed, }) phantom.act("detonate url", parameters=parameters, assets=['virustotal_api'], callback=filter_4, name="detonate_url_1") return
def playbook_wait(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("playbook_wait() called") decide_and_launch_playbooks__names = json.loads( phantom.get_run_data(key="decide_and_launch_playbooks:names")) ################################################################################ ## Custom Code Start ################################################################################ if phantom.completed(playbook_names=decide_and_launch_playbooks__names): # call connected block "indicators_not_blocked" get_indicators_status(container=container) # return early to avoid calling connected block too soon return ################################################################################ ## Custom Code End ################################################################################ get_indicators_status(container=container) return
def create_generator(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('create_generator() called') #phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) format_generator__generator = json.loads( phantom.get_run_data(key='format_generator:generator')) # collect data for 'create_generator' call parameters = [] # build parameters list for 'create_generator' call parameters.append({ 'body': format_generator__generator, 'headers': "", 'location': "/rest/asset", 'verify_certificate': False, }) phantom.act("post data", parameters=parameters, assets=['http'], callback=create_custom_list, name="create_generator") return
def join_format_prompt(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None): phantom.debug('join_format_prompt() called') # if the joined function has already been called, do nothing if phantom.get_run_data(key='join_format_prompt_called'): return # check if all connected incoming playbooks, actions, or custom functions are done i.e. have succeeded or failed if phantom.completed(action_names=['get_process_details']): # save the state that the joined function has now been called phantom.save_run_data(key='join_format_prompt_called', value='format_prompt') # call connected block "format_prompt" format_prompt(container=container, handle=handle) return