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 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 on_start(incident): # lets do VT lookup of file hashes in the artifacts of an incident # artifacts:event.cef.fileHash # artifacts:event.cef.* # artifacts:event.raw.* # artifacts:event.* hashes = phantom.collect(incident, 'artifact:event.cef.fileHash', 'all', 100) phantom.debug('1:' + str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.*.fileHash', 'all', 100) #phantom.debug('2:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.cef.*', 'all', 100) #phantom.debug('3:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.raw.*', 'all', 100) #phantom.debug('4:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.*', 'all', 100) #phantom.debug('5:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.source_data_identifier', 'all', 100) #phantom.debug('6:'+str(hashes)) #hashes = phantom.collect(incident, '*', 'all', 100) #phantom.debug('7:'+str(hashes)) return
def block_application_cb(action, success, incident, results, handle): if not success: return ips = set( phantom.collect(incident, 'artifact:*.cef.destinationAddress', scope='all')) parameters = [] for ip in ips: parameters.append({ "ip": ip, "from_zone": "trust", "to_zone": "untrust" }) if parameters: phantom.act('unblock ip', parameters=parameters, assets=["junipersrx"], callback=unblock_ip_cb) return
def on_start(incident): # lets do VT lookup of file hashes in the artifacts of an incident # artifacts:event.cef.fileHash # artifacts:event.cef.* # artifacts:event.raw.* # artifacts:event.* hashes = phantom.collect(incident, 'artifact:event.cef.fileHash', 'all', 100) phantom.debug('1:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.*.fileHash', 'all', 100) #phantom.debug('2:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.cef.*', 'all', 100) #phantom.debug('3:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.raw.*', 'all', 100) #phantom.debug('4:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.*', 'all', 100) #phantom.debug('5:'+str(hashes)) #hashes = phantom.collect(incident, 'artifact:event.source_data_identifier', 'all', 100) #phantom.debug('6:'+str(hashes)) #hashes = phantom.collect(incident, '*', 'all', 100) #phantom.debug('7:'+str(hashes)) return
def lookup_email_4(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('lookup_email_4() called') # collect data for 'lookup_email_4' call # container_data = phantom.collect2(container=container, datapath=['artifact:*.cef.fromEmail', 'artifact:*.id']) results_email = phantom.collect(container, "artifact:*.cef.fromEmail", scope='all') email = results_email[0] phantom.debug('email: {}'.format(email)) parameters = [] parameters.append({'email': re.search(r'<(.*?)>', email).group(1)}) phantom.act("lookup email", parameters=parameters, app={"name": 'Have I Been Pwned'}, name="lookup_email_4", callback=decision_1) return
def on_start(container): ips = set(phantom.collect(container, 'artifact:*.cef.sourceAddress')) boiler_plate = { "action": "reject", "policy": None, "rule name": None, "partition": "Common" } for ip in ips: parameters = boiler_plate parameters[ "policy"] = "Phantom_Inbound" # Policy name must exist on the F5 BIG-IP parameters["source"] = ip # Source IP we are blocking parameters[ "rule name"] = "Phantom" + ip # Make the rule name based on the source IP address phantom.debug("PARAMETERS \n%s" % parameters) phantom.act('block ip', parameters=[parameters], assets=["f5"], callback=block_IP_cb) return
def on_start(incident): ip_hostnames = set(phantom.collect(incident, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({ "last_n_days" : "2", "ip_hostname" : ip_hostname }) phantom.act('get host events', parameters=parameters, assets=["splunk_entr"], callback=get_host_events_cb) return
def on_start(incident): ip_hostnames = set(phantom.collect(incident, 'artifact:*.cef.sourceAddress')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({ "name" : "infostealer*.exe", "ip_hostname" : ip_hostname }) phantom.act('get process file', parameters=parameters, assets=["domainctrl1"], callback=get_process_file_cb) return
def on_start(offense): ips = set(phantom.collect(offense, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip in ips: parameters.append({ "ip" : ip }) phantom.act('geolocate ip', parameters=parameters, assets=["maxmind"], callback=geolocate_ip_cb) return
def on_start(container): sourceAddress = set( phantom.collect(container, 'artifact:*.cef.sourceAddress')) parameters = [] for ip in sourceAddress: parameters.append({ "ip": ip, }) phantom.act("query ip", parameters=parameters, assets=["shodan"]) # callback=query_ip_cb destinationAddress = set( phantom.collect(container, 'artifact:*.cef.destinationAddress')) parameters = [] for ip in destinationAddress: parameters.append({ "ip": ip, }) phantom.act("query ip", parameters=parameters, assets=["shodan"]) destinationDomains = set( phantom.collect(container, 'artifact:*.cef.destinationDnsDomain')) parameters = [] for domain in destinationDomains: parameters.append({ "domain": domain, }) phantom.act("query domain", parameters=parameters, assets=["shodan"]) return
def on_start(campaign): md5s = set(phantom.collect(campaign, 'artifact:*.cef.fileHash')) parameters = [] for md5 in md5s: parameters.append({ "md5" : md5 }) if parameters: phantom.act('hunt file', parameters=parameters, assets=["carbonblack"], callback=hunt_file_cb) return
def on_start(incident): phantom.debug('---------- ANALYZING FILE HASHES ----------') 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) phantom.debug('---------- ANALYZING 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}) phantom.act("geolocate ip", parameters=params, callback=generic_cb) phantom.debug('---------- ANALYZING VICTIM IPs ----------') # lets do system info for infected machines params = [] victim_ips = phantom.victim_ips(incident, scope='all') if len(victim_ips) > 0: for ip in victim_ips: params.append({'ip_hostname': ip}) phantom.act("get system info", parameters=params, callback=generic_cb) phantom.debug('---------- ANALYZING URLs ----------') params = [] urls = list( set(phantom.collect(incident, 'artifact:*.cef.requestURL', scope='all'))) if len(urls) > 0: for url in urls: params.append({'domain': url}) phantom.act("whois domain", parameters=params, callback=generic_cb) return
def on_start(incident): ips = set(phantom.collect(incident, 'artifact:*.cef.destinationAddress', scope='all')) parameters = [] for ip in ips: parameters.append({ "ip" : ip, "from_zone" : "trust", "to_zone" : "untrust" }) if parameters: phantom.act('block ip', parameters=parameters, assets=["junipersrx"], callback=block_ip_cb) return
def on_start(incident): # lets do geo lookup of attacker IPs phantom.debug(incident['name'] + 'has severity: ' + incident['sensitivity']) phantom.debug(incident['name'] + 'has sensitivity: ' + incident['severity']) phantom.debug(' ------------------ USER NAMES --------------------------------- ') params = [] victims = list(set(phantom.collect(incident, 'artifact:*.cef.sourceUserName', scope='all'))) victims.extend(list(set(phantom.collect(incident, 'artifact:*.cef.destinationUserName', scope='all')))) if len(victims) > 0: exec_victims = [] execs = phantom.datastore_get("executives") if execs is not None: exec_victims = [exec_info[0] for exec_info in execs if exec_info[0] in victims] if len(exec_victims) > 0: phantom.debug('Execs impacted by this incident: '+str(exec_victims)) phantom.set_sensitivity(incident, 'amber') phantom.set_severity(incident, 'high') return
def on_start(campaign): md5s = set(phantom.collect(campaign, 'artifact:*.cef.fileHash')) parameters = [] for md5 in md5s: parameters.append({ "hash" : md5 }) if parameters: phantom.act('hunt file', parameters=parameters, assets=["carbonblack"], callback=hunt_file_cb) return
def on_start(incident): ip_hostnames = set(phantom.collect(incident, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({ "ip_hostname" : ip_hostname, "name" : "infostealer*.exe" }) if parameters: phantom.act('get process file', parameters=parameters, assets=["domainctrl1"], callback=get_process_file_cb) return
def on_start(incident): # lets do VT lookup of file hashes params = [] hashes = list(set(phantom.collect(incident, 'artifact:*.cef.fileHash', scope='all'))) if len(hashes) == 0: return for filehash in hashes: params.append({'hash':filehash}) # specify the reviewer to review the prameters of the action before it is executed phantom.act("file reputation", parameters=params, callback=generic_cb, reviewer='*****@*****.**') return
def on_start(incident): ip_macaddresss = set(phantom.collect(incident, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip_macaddress in ip_macaddresss: parameters.append({ "ip_macaddress" : ip_macaddress, "ping_ip" : True, "vlan_id" : "170", "override_trunk" : False }) if parameters: phantom.act('vlan host', parameters=parameters, assets=["ciscocatalyst"], callback=set_system_vlan2_cb) return
def ip_reputation_cb(action, success, offense, results, handle): if not success: return victim_ips = list(set(phantom.collect(offense, 'artifact:*.cef.destinationAddress', scope='all'))) parameters = [] for ip in victim_ips: parameters.append({ "ip_hostname" : ip }) phantom.act('list connections', parameters=parameters, assets=["AD"], callback=list_connections_cb, ) return
def on_start(incident): params = [] hashes = list(set(phantom.collect(incident, 'artifact:*.cef.fileHash', scope='all'))) if len(hashes) == 0: phantom.debug('No hashes found to act on') return for filehash in hashes: params.append({'hash':filehash}) # action without specifying on assets executes action all matching assets using latest corresponding connectors/apps phantom.debug("1. calling action without specifying on assets executes action all matching assets using latest corresponding connectors/apps") phantom.act("file reputation", parameters=params, callback=generic_cb) # action on assets that support the action .. phantom.debug("2. calling action on specific assets that support the action 'file reputation'") selected_rep_assets=[] reputation_assets = phantom.get_assets(action="file reputation") for rep_asset in reputation_assets: selected_rep_assets.append(rep_asset["name"]) #selected_rep_assets = phantom.get_asset_names(action="file reputation") phantom.act("file reputation", assets=selected_rep_assets, parameters=params, callback=generic_cb) # action on critical assets my_tags = [] my_tags.append('Critical') phantom.debug("3. calling action with NO specific assets but tags 'Critical") phantom.act("file reputation", tags=my_tags, parameters=params, callback=generic_cb) # action on assets marked critical phantom.debug("4. calling action with any assets that were tagged 'Critical") critical_assets = phantom.get_asset_names(tags=my_tags) phantom.act("file reputation", assets=critical_assets, parameters=params, callback=generic_cb) # action on reputation assets marked critical phantom.debug("5. calling action with specific assets for the action that were taggged 'Critical") critical_reputation_assets = phantom.get_asset_names(action="file reputation", tags=my_tags) phantom.act("file reputation", assets=critical_reputation_assets, parameters=params, callback=generic_cb) # action on ALL assets phantom.debug("6. calling action on ALL assets!") all_assets = phantom.get_asset_names() phantom.act("file reputation", assets=all_assets, parameters=params, callback=generic_cb) # action on specified assets with specified tags phantom.debug("7. calling action on with specific assets and TAGs") phantom.act("file reputation", assets=selected_rep_assets, tags=my_tags, parameters=params, callback=generic_cb) return
def detonate_file_cb(action, success, incident, results, handle): phantom.debug('ThreatGrid action to detonate file,'+(' SUCCEEDED' if success else ' FAILED')) if not success: return score = results[0]['action_results'][0]['data'][0]['threat']['score'] phantom.debug('ThreatGrid threat score for this file: '+str(score)) if score > 60: for mac_addr in phantom.collect(incident,'artifact:event.cef.sourceMacAddress'): phantom.act('terminate session', parameters=[{'macaddress':mac_addr}], assets=['ciscoise'], callback=generic_cb) for a_ip in phantom.attacker_ips(incident): params = [{'src':'any','direction':'out','dest':a_ip,'interface':'outside','access-list':'inside_access_out'}] phantom.act('block ip', parameters=params, assets=['ciscoasa'], callback=generic_cb) for v_ip in phantom.victim_ips(incident): phantom.act('terminate process', parameters=[{'name':'*infostealer*','ip_hostname':v_ip}], assets=['domainctrl1'], callback=terminate_process_cb)
def locate_device_cb(action, success, container, results, handle): if not success: return paths = ['action_result.data.*.client.mac', 'action_result.data.*.client.description', 'action_result.data.*.device', 'action_result.data.*.network', 'action_result.data.*.organization'] data = phantom.collect(results, paths) phantom.debug(data) return
def on_start(incident): # lets do geo lookup of attacker IPs phantom.debug(incident['name'] + 'has severity: ' + incident['sensitivity']) phantom.debug(incident['name'] + 'has sensitivity: ' + incident['severity']) phantom.debug( ' ------------------ USER NAMES --------------------------------- ') params = [] victims = list( set( phantom.collect(incident, 'artifact:*.cef.sourceUserName', scope='all'))) victims.extend( list( set( phantom.collect(incident, 'artifact:*.cef.destinationUserName', scope='all')))) if len(victims) > 0: exec_victims = [] execs = phantom.datastore_get("executives") if execs is not None: exec_victims = [ exec_info[0] for exec_info in execs if exec_info[0] in victims ] if len(exec_victims) > 0: phantom.debug('Execs impacted by this incident: ' + str(exec_victims)) phantom.set_sensitivity(incident, 'amber') phantom.set_severity(incident, 'high') return
def on_start(incident): ip_hostnames = set(phantom.collect(incident, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip_hostname in ip_hostnames: if (re.match(internal_ip, ip_hostname)): phantom.debug("ip: {0} is internal, will be executing the action".format(ip_hostname)) parameters.append({ "ip_hostname" : ip_hostname, "name" : "infostealer*.exe" }) if parameters: phantom.act('get process file', parameters=parameters, assets=["domainctrl1"], callback=get_process_file_cb) return
def on_start(incident): phantom.debug('---------- ANALYZING FILE HASHES ----------') 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) phantom.debug('---------- ANALYZING 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}) phantom.act("geolocate ip", parameters=params, callback=generic_cb) phantom.debug('---------- ANALYZING VICTIM IPs ----------') # lets do system info for infected machines params = [] victim_ips = phantom.victim_ips(incident, scope='all') if len(victim_ips) > 0: for ip in victim_ips: params.append({'ip_hostname':ip}) phantom.act("get system info", parameters=params, callback=generic_cb) phantom.debug('---------- ANALYZING URLs ----------') params = [] urls = list(set(phantom.collect(incident, 'artifact:*.cef.requestURL', scope='all'))) if len(urls) > 0: for url in urls: params.append({'domain':url}) phantom.act("whois domain", parameters=params, callback=generic_cb) return
def geolocate_ip_cb(action, success, offense, results, handle): if not success: return ips = set(phantom.collect(offense, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip in ips: parameters.append({ "ip" : ip }) phantom.act('whois ip', parameters=parameters, assets=["whois"], callback=whois_ip_cb) return
def locate_device_cb(action, success, container, results, handle): if not success: return paths = [ 'action_result.data.*.client.mac', 'action_result.data.*.client.description', 'action_result.data.*.device', 'action_result.data.*.network', 'action_result.data.*.organization' ] data = phantom.collect(results, paths) phantom.debug(data) return
def on_start(container): sourceAddress = set(phantom.collect(container, 'artifact:*.cef.sourceHostName')) parameters = [] for ip_hostname in sourceAddress : parameters.append({ "ip_hostname": ip_hostname, "name": "notepad.exe", }) phantom.act("terminate process", parameters=parameters, assets=["tanium"], callback=terminate_process_cb) return
def on_start(container): ips = set(phantom.collect(container, 'artifact:*.cef.sourceAddress')) boiler_plate = { "action" : "reject", "policy" : None, "rule name" : None, "partition" : "Common"} for ip in ips: parameters = boiler_plate parameters["policy"] = "Phantom_Inbound" # Policy name must exist on the F5 BIG-IP parameters["source"] = ip # Source IP we are blocking parameters["rule name"] = "Phantom" + ip # Make the rule name based on the source IP address phantom.debug("PARAMETERS \n%s" % parameters) phantom.act('block ip', parameters=[parameters], assets=["f5"], callback=block_IP_cb) return
def on_start(offense): ips = set( phantom.collect(offense, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip in ips: parameters.append({"ip": ip}) phantom.act('geolocate ip', parameters=parameters, assets=["maxmind"], callback=geolocate_ip_cb) return
def block_application_cb(action, success, incident, results, handle): if not success: return ips = set(phantom.collect(incident, 'artifact:*.cef.destinationAddress', scope='all')) parameters = [] for ip in ips: parameters.append({ "ip" : ip, "from_zone" : "trust", "to_zone" : "untrust" }) if parameters: phantom.act('unblock ip', parameters=parameters, assets=["junipersrx"], callback=unblock_ip_cb) return
def on_start(incident): ip_hostnames = set( phantom.collect(incident, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({"last_n_days": "2", "ip_hostname": ip_hostname}) phantom.act('get host events', parameters=parameters, assets=["splunk_entr"], callback=get_host_events_cb) return
def on_start(incident): ip_hostnames = set( phantom.collect(incident, 'artifact:*.cef.sourceAddress')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({"ip_hostname": ip_hostname}) phantom.act('list services', parameters=parameters, assets=["domainctrl1"], callback=list_services_cb) return
def set_system_vlan2_cb(action, success, incident, results, handle): if not success: return ip_macaddresss = set(phantom.collect(incident, 'artifact:*.cef.sourceMacAddress', scope='all')) parameters = [] for ip_macaddress in ip_macaddresss: parameters.append({ "ip_macaddress" : ip_macaddress, "ping_ip" : False, "vlan_id" : "160", "override_trunk" : False }) if parameters: phantom.act('vlan host', parameters=parameters, assets=["ciscocatalyst"], callback=set_system_vlan1_cb) return
def format_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None): phantom.debug('format_1() called') pb_info = phantom.get_playbook_info() if not pb_info: return playbook_name = pb_info[0].get('name', None) ticket = phantom.collect(results, "action_result.summary.created_ticket_id") artifacts_data_1 = phantom.collect2(container=container, datapath=['artifact:*.cef.src']) if ticket: ticket = ticket[0] phantom.debug('Ticket {}'.format(ticket)) for artifacts_item_1 in artifacts_data_1: if artifacts_item_1: if phantom.valid_ip(artifacts_item_1[0]): addr = phantom.get_object(key=str(artifacts_item_1[0]), playbook_name=playbook_name) if addr: addr[0]['value']['ticket'] = ticket #phantom.debug('Saving object {} of type {} with key {}'.format(addr[0], type(addr[0]['value']), artifacts_item_1[0])) phantom.save_object(key=str(artifacts_item_1[0]), value=addr[0]['value'], auto_delete=False, playbook_name=playbook_name) template = """Ticket id: {0} number: {1}""" # parameter list for template variable replacement parameters = [ "create_ticket_1:action_result.summary.created_ticket_id", "create_ticket_1:action_result.data.*.number", ] phantom.format(container=container, template=template, parameters=parameters, name="format_1") return
def on_start(incident): # lets do VT lookup of file hashes params = [] hashes = list( set(phantom.collect(incident, 'artifact:*.cef.fileHash', scope='all'))) if len(hashes) == 0: return for filehash in hashes: params.append({'hash': filehash}) # specify the reviewer to review the prameters of the action before it is executed phantom.act("file reputation", parameters=params, callback=generic_cb, reviewer='*****@*****.**') return
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, name='my_file_lookup_action') # 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}) phantom.act("geolocate ip", parameters=params, callback=generic_cb, handle=str(params)) return
def terminate_process_cb(action, success, container, results, handle): if not success: return sourceAddress = set(phantom.collect(container, 'artifact:*.cef.sourceAddress')) parameters = [] for ip_hostname in sourceAddress : parameters.append({ "ip_hostname": ip_hostname, }) phantom.act("reboot system", parameters=parameters, assets=["tanium"], callback=reboot_system_cb) return
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
def list_services_cb(action, success, incident, results, handle): if not success: return ip_hostnames = set( phantom.collect(incident, 'artifact:*.cef.sourceAddress')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({"ip_hostname": ip_hostname}) phantom.act('get system info', parameters=parameters, assets=["domainctrl1"], callback=get_system_info_cb) return
def geolocate_ip_cb(action, success, offense, results, handle): if not success: return ips = set( phantom.collect(offense, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip in ips: parameters.append({"ip": ip}) phantom.act('whois ip', parameters=parameters, assets=["whois"], callback=whois_ip_cb) return
def list_connections_cb(action, success, offense, results, handle): if not success: return attacker_ips = list( set( phantom.collect(offense, 'artifact:*.cef.sourceAddress', scope='all'))) counter = 0 for result in results: for action_result in result['action_results']: for data in action_result['data']: phantom.debug('on infected machine: ' + str(action_result['parameter']['ip_hostname']) + ' process connected to remote_ip: ' + str(data['remote_ip'])) if data['remote_ip'] in attacker_ips: phantom.debug( 'on infected machine found process connected to attacker_ip: ' + str(data['remote_ip']) + ' on port: ' + str(data['remote_port'])) phantom.act('get process file', parameters=[{ "pid": str(data['pid']), "ip_hostname": action_result['parameter']['ip_hostname'] }], assets=["AD"], callback=get_process_file_cb) return # for now returning with just one call to get process image counter += 1 if counter == 3: return phantom.debug( "Attacker IP not found in list of connections. No process file to get." ) return
def ip_reputation_cb(action, success, offense, results, handle): if not success: return victim_ips = list( set( phantom.collect(offense, 'artifact:*.cef.destinationAddress', scope='all'))) parameters = [] for ip in victim_ips: parameters.append({"ip_hostname": ip}) phantom.act( 'list connections', parameters=parameters, assets=["AD"], callback=list_connections_cb, ) return
def list_connections_cb(action, success, offense, results, handle): if not success: return attacker_ips = list(set(phantom.collect(offense, 'artifact:*.cef.sourceAddress', scope='all'))) counter = 0 for result in results: for action_result in result['action_results']: for data in action_result['data']: phantom.debug('on infected machine: '+str(action_result['parameter']['ip_hostname'])+' process connected to remote_ip: '+str(data['remote_ip'])) if data['remote_ip'] in attacker_ips: phantom.debug('on infected machine found process connected to attacker_ip: '+str(data['remote_ip'])+' on port: '+str(data['remote_port'])) phantom.act('get process file', parameters=[{"pid":str(data['pid']), "ip_hostname" : action_result['parameter']['ip_hostname']}], assets=["AD"], callback=get_process_file_cb) return # for now returning with just one call to get process image counter += 1 if counter == 3: return phantom.debug("Attacker IP not found in list of connections. No process file to get.") return
def list_users_cb(action, success, incident, results, handle): if not success: return ip_hostnames = set( phantom.collect(incident, 'artifact:*.cef.sourceAddress')) parameters = [] for ip_hostname in ip_hostnames: parameters.append({ "query": "select SessionId from Win32_Process Where Name = 'notepad.exe'", "ip_hostname": ip_hostname }) phantom.act('run query', parameters=parameters, assets=["domainctrl1"], callback=run_query_cb) return
def on_start(incident): ips = set( phantom.collect(incident, 'artifact:*.cef.destinationAddress', scope='all')) parameters = [] for ip in ips: parameters.append({ "ip": ip, "from_zone": "trust", "to_zone": "untrust" }) if parameters: phantom.act('block ip', parameters=parameters, assets=["junipersrx"], callback=block_ip_cb) return
def on_start(incident): ip_hostnames = set( phantom.collect(incident, 'artifact:*.cef.sourceAddress', scope='all')) parameters = [] for ip_hostname in ip_hostnames: if (re.match(internal_ip, ip_hostname)): phantom.debug( "ip: {0} is internal, will be executing the action".format( ip_hostname)) parameters.append({ "ip_hostname": ip_hostname, "name": "infostealer*.exe" }) if parameters: phantom.act('get process file', parameters=parameters, assets=["domainctrl1"], callback=get_process_file_cb) return
def _check_value(l_value, data_path, results, action): # get the action Name action_name = action['action'] # Get the leaf node, this is the value that we are checking of leaf_node = data_path.split('.')[-1] # get the value in the results r_value = phantom.collect(results, data_path) # Init the values as if the comparison failed qa_pass_count = 0 qa_fail_count = 1 test_result = "Fail" expected_message = 'expecting "{0}"'.format(l_value) # Compare if (str(l_value) in str(r_value)): # Passed, set the vars accordingly qa_pass_count = 1 qa_fail_count = 0 test_result = "Pass" expected_message = 'as expected' # Now call save_data with what was detected _save_data(qa_fail_count=qa_fail_count, qa_pass_count=qa_pass_count, message='{result}: action "{action_name}" {leaf_node} is "{r_value}", {expected_message}'.format( result=test_result, action_name=action_name, leaf_node=leaf_node, r_value=r_value, expected_message=expected_message), offset=1) return True
def detonate_file_cb(action, success, incident, results, handle): phantom.debug('ThreatGrid action to detonate file,' + (' SUCCEEDED' if success else ' FAILED')) if not success: return score = results[0]['action_results'][0]['data'][0]['threat']['score'] phantom.debug('ThreatGrid threat score for this file: ' + str(score)) if score > 60: for mac_addr in phantom.collect(incident, 'artifact:event.cef.sourceMacAddress'): phantom.act('terminate session', parameters=[{ 'macaddress': mac_addr }], assets=['ciscoise'], callback=generic_cb) for a_ip in phantom.attacker_ips(incident): params = [{ 'src': 'any', 'direction': 'out', 'dest': a_ip, 'interface': 'outside', 'access-list': 'inside_access_out' }] phantom.act('block ip', parameters=params, assets=['ciscoasa'], callback=generic_cb) for v_ip in phantom.victim_ips(incident): phantom.act('terminate process', parameters=[{ 'name': '*infostealer*', 'ip_hostname': v_ip }], assets=['domainctrl1'], callback=terminate_process_cb)
def on_start(incident): params = [] hashes = list( set(phantom.collect(incident, 'artifact:*.cef.fileHash', scope='all'))) if len(hashes) == 0: phantom.debug('No hashes found to act on') return for filehash in hashes: params.append({'hash': filehash}) # action without specifying on assets executes action all matching assets using latest corresponding connectors/apps phantom.debug( "1. calling action without specifying on assets executes action all matching assets using latest corresponding connectors/apps" ) phantom.act("file reputation", parameters=params, callback=generic_cb) # action on assets that support the action .. phantom.debug( "2. calling action on specific assets that support the action 'file reputation'" ) selected_rep_assets = [] reputation_assets = phantom.get_assets(action="file reputation") for rep_asset in reputation_assets: selected_rep_assets.append(rep_asset["name"]) #selected_rep_assets = phantom.get_asset_names(action="file reputation") phantom.act("file reputation", assets=selected_rep_assets, parameters=params, callback=generic_cb) # action on critical assets my_tags = [] my_tags.append('Critical') phantom.debug( "3. calling action with NO specific assets but tags 'Critical") phantom.act("file reputation", tags=my_tags, parameters=params, callback=generic_cb) # action on assets marked critical phantom.debug( "4. calling action with any assets that were tagged 'Critical") critical_assets = phantom.get_asset_names(tags=my_tags) phantom.act("file reputation", assets=critical_assets, parameters=params, callback=generic_cb) # action on reputation assets marked critical phantom.debug( "5. calling action with specific assets for the action that were taggged 'Critical" ) critical_reputation_assets = phantom.get_asset_names( action="file reputation", tags=my_tags) phantom.act("file reputation", assets=critical_reputation_assets, parameters=params, callback=generic_cb) # action on ALL assets phantom.debug("6. calling action on ALL assets!") all_assets = phantom.get_asset_names() phantom.act("file reputation", assets=all_assets, parameters=params, callback=generic_cb) # action on specified assets with specified tags phantom.debug("7. calling action on with specific assets and TAGs") phantom.act("file reputation", assets=selected_rep_assets, tags=my_tags, parameters=params, callback=generic_cb) 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'))) # collect data for 'send_email_1' call results_lookup_email = phantom.collect2( container=container, datapath=[ 'lookup_email_4:action_result.summary.total_breaches', 'lookup_email_4:action_result.data.*.Title', 'lookup_email_4:action_result.data.*.BreachDate', 'lookup_email_4:action_result.parameter.context.artifact_id' ], action_results=results) #phantom.debug('{}'.format(results_data_1)) results_email = phantom.collect(container, "artifact:*.cef.fromEmail", scope='all') email = results_email[0] results_urls = phantom.collect(container, "artifact:*.cef.requestURL", scope='all') urls = set([]) for url in results_urls: #o=urlparse(url) #phantom.debug('url netloc: {}'.format(o.netloc)) urls.add(url) #urls=list(set(urls)) results_files = phantom.collect(container, "artifact:*.cef.fileName", scope='all') files = [] for file in results_files: files.append(file) results_reputation = phantom.collect2( container=container, datapath=['file_reputation_1:action_result.summary.positives'], action_results=results) positives = [] message = '' for positive in results_reputation: phantom.debug('positive: {}'.format(positive[0])) if positive[0] > 0: message = ' !!! infected attachment identified' positives.append(positive) phantom.debug('email: {} reputation: {}'.format(email, zip(files, positives))) parameters = [] body = "PhishReports summary:\n\nBreaches:\n" total1 = 0 _id = 0 # build parameters list for 'send_email_1' call for results_item_email in results_lookup_email: if results_item_email[0]: phantom.debug('Breaches: {0}->{1}->{2}->{3}'.format( results_item_email[0], results_item_email[1], results_item_email[2], results_item_email[3])) body = body + str(results_item_email[1]) + ' on ' + str( results_item_email[2]) + '\n' total1 = results_item_email[0] _id = results_item_email[3] if len(files) > 0: body = body + '\nReputations:\n' for item in zip(files, positives): body = body + str(item[0]) + ' has ' + str( item[1][0]) + ' positives\n' if len(urls) > 0: phantom.debug('urls type: {}'.format(type(urls))) body = body + '\nUrls:\n' santized_urls = [] for index, item in enumerate(urls): if item.startswith('http'): if not any(substring in item for substring in EXCLUDED): if 'urldefense.proofpoint.com/v2' in item: item = decodev2( item ) + ' <- urldefense.proofpoint.com/v2' #<a href="url">link text</a> sanitized_item = item.split(' ')[0] if sanitized_item not in santized_urls: santized_urls.append(sanitized_item) #phantom.debug('item {} added'.format(sanitized_item)) body = body + ' - ' + str(sanitized_item) + '\n' #phantom.debug('{}'.format(santized_urls)) phantom.debug('{}'.format(body)) if 'romaniuk' in email.lower(): to = "*****@*****.**" else: to = "*****@*****.**" parameters.append({ 'from': "*****@*****.**", 'to': to, 'subject': 'PhishReports for ' + email + message, 'body': body, 'attachments': "", # context (artifact id) is added to associate results with the artifact 'context': { 'artifact_id': _id }, }) phantom.debug('Breaches: {} Postives: {}'.format(int(total1), positive[0])) if int(total1) >= 0 or positive[0] >= 0: phantom.act("send email", parameters=parameters, app={"name": 'SMTP'}, name="send_email_1") return
def test_params(container, datapath, key_name): params = [] items = set(phantom.collect(container, datapath, scope='all')) for item in items: params.append({key_name: item}) return params
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