From c4e565445bb54790b631cc5bbbe048ef6655953b Mon Sep 17 00:00:00 2001 From: Lou Stella Date: Thu, 30 Mar 2023 17:41:14 -0500 Subject: [PATCH 1/5] Initial Commit- CrowdStrike OAuth API Identifier Activity Analysis --- ...Auth_API_Identifier_Activity_Analysis.json | 596 ++++++++++++++++++ ...OAuth_API_Identifier_Activity_Analysis.png | Bin 0 -> 68535 bytes ..._OAuth_API_Identifier_Activity_Analysis.py | 433 +++++++++++++ ...OAuth_API_Identifier_Activity_Analysis.yml | 22 + 4 files changed, 1051 insertions(+) create mode 100644 playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json create mode 100644 playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.png create mode 100644 playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py create mode 100644 playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.yml diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json new file mode 100644 index 0000000000..1c1048bb20 --- /dev/null +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json @@ -0,0 +1,596 @@ +{ + "blockly": false, + "blockly_xml": "", + "category": "Identifier Activity Analysis", + "coa": { + "data": { + "description": "Accepts a file_hash or domain name, and asks CrowdStrike for a list of device IDs that have interacted with each. The list of IDs is then sent back to Crowdstrike to get more information, and then produces a normalized output and summary table.", + "edges": [ + { + "id": "port_0_to_port_2", + "sourceNode": "0", + "sourcePort": "0_out", + "targetNode": "2", + "targetPort": "2_in" + }, + { + "conditions": [ + { + "index": 0 + } + ], + "id": "port_2_to_port_3", + "sourceNode": "2", + "sourcePort": "2_out", + "targetNode": "3", + "targetPort": "3_in" + }, + { + "conditions": [ + { + "index": 1 + } + ], + "id": "port_2_to_port_4", + "sourceNode": "2", + "sourcePort": "2_out", + "targetNode": "4", + "targetPort": "4_in" + }, + { + "id": "port_3_to_port_5", + "sourceNode": "3", + "sourcePort": "3_out", + "targetNode": "5", + "targetPort": "5_in" + }, + { + "id": "port_4_to_port_6", + "sourceNode": "4", + "sourcePort": "4_out", + "targetNode": "6", + "targetPort": "6_in" + }, + { + "id": "port_7_to_port_9", + "sourceNode": "7", + "sourcePort": "7_out", + "targetNode": "9", + "targetPort": "9_in" + }, + { + "id": "port_8_to_port_10", + "sourceNode": "8", + "sourcePort": "8_out", + "targetNode": "10", + "targetPort": "10_in" + }, + { + "id": "port_9_to_port_1", + "sourceNode": "9", + "sourcePort": "9_out", + "targetNode": "1", + "targetPort": "1_in" + }, + { + "id": "port_10_to_port_1", + "sourceNode": "10", + "sourcePort": "10_out", + "targetNode": "1", + "targetPort": "1_in" + }, + { + "conditions": [ + { + "index": 0 + } + ], + "id": "port_5_to_port_12", + "sourceNode": "5", + "sourcePort": "5_out", + "targetNode": "12", + "targetPort": "12_in" + }, + { + "conditions": [ + { + "index": 0 + } + ], + "id": "port_6_to_port_13", + "sourceNode": "6", + "sourcePort": "6_out", + "targetNode": "13", + "targetPort": "13_in" + }, + { + "id": "port_12_to_port_7", + "sourceNode": "12", + "sourcePort": "12_out", + "targetNode": "7", + "targetPort": "7_in" + }, + { + "id": "port_13_to_port_8", + "sourceNode": "13", + "sourcePort": "13_out", + "targetNode": "8", + "targetPort": "8_in" + } + ], + "hash": "087adbe2d806f96cc17b09023f8b1ae68a56d1d9", + "nodes": { + "0": { + "data": { + "advanced": { + "join": [] + }, + "functionName": "on_start", + "id": "0", + "type": "start" + }, + "errors": {}, + "id": "0", + "type": "start", + "warnings": {}, + "x": 190, + "y": -2.5579538487363607e-13 + }, + "1": { + "data": { + "advanced": { + "join": [] + }, + "functionName": "on_finish", + "id": "1", + "type": "end" + }, + "errors": {}, + "id": "1", + "type": "end", + "warnings": {}, + "x": 190, + "y": 1100 + }, + "10": { + "data": { + "advanced": { + "customName": "build domain output", + "customNameId": 0, + "join": [] + }, + "functionId": 2, + "functionName": "build_domain_output", + "id": "10", + "inputParameters": [ + "hunt_domain:action_result.parameter.domain", + "get_systems_from_domain:action_result.data", + "hunt_domain:action_result.summary.device_count" + ], + "outputVariables": [ + "observable_array" + ], + "type": "code" + }, + "errors": {}, + "id": "10", + "type": "code", + "userCode": "\n\n build_domain_output__observable_array = []\n device_list = []\n indicator = hunt_domain_parameter_domain[0]\n count = hunt_domain_summary_device_count[0]\n \n # Build devices list\n for item in get_systems_from_domain_result_item_0:\n \n # if AIDs that no longer exist saw the artifact, they can still \n # be included in the middle of the hunt response, but will return\n # empty-ish objects from the `get system info` action, so we need\n # to length check them\n \n if len(item) > 0:\n device = item[0]\n device_filtered = {\n \"name\": device['hostname'],\n \"id\": device['device_id'],\n \"ip_address\": device['local_ip'],\n \"operating_system\": device['os_version']\n }\n device_list.append(device_filtered)\n \n \n # Build observable object\n observable_array = {\n \"indicator\": indicator,\n \"type\": \"domain\",\n \"total_count\": len(device_list),\n \"source\": \"Crowdstrike OAuth\",\n \"identifier_activity\": device_list\n }\n \n build_domain_output__observable_array.append(observable_array)\n", + "warnings": {}, + "x": 340, + "y": 960 + }, + "12": { + "data": { + "action": "get system info", + "actionType": "investigate", + "advanced": { + "customName": "get systems from file", + "customNameId": 0, + "join": [] + }, + "connector": "CrowdStrike OAuth API", + "connectorConfigs": [ + "crowdstrike" + ], + "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", + "connectorVersion": "v1", + "functionId": 1, + "functionName": "get_systems_from_file", + "id": "12", + "parameters": { + "id": "filtered-data:filter_2:condition_1:hunt_file:action_result.data.*.device_id" + }, + "requiredParameters": [ + { + "data_type": "string", + "field": "id" + } + ], + "type": "action" + }, + "errors": {}, + "id": "12", + "type": "action", + "warnings": {}, + "x": 0, + "y": 660 + }, + "13": { + "data": { + "action": "get system info", + "actionType": "investigate", + "advanced": { + "customName": "get systems from domain", + "customNameId": 0, + "join": [] + }, + "connector": "CrowdStrike OAuth API", + "connectorConfigs": [ + "crowdstrike" + ], + "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", + "connectorVersion": "v1", + "functionId": 2, + "functionName": "get_systems_from_domain", + "id": "13", + "parameters": { + "id": "filtered-data:filter_3:condition_1:hunt_domain:action_result.data.*.device_id" + }, + "requiredParameters": [ + { + "data_type": "string", + "field": "id" + } + ], + "tab": "byAction", + "type": "action" + }, + "errors": {}, + "id": "13", + "type": "action", + "warnings": {}, + "x": 340, + "y": 656 + }, + "2": { + "data": { + "advanced": { + "customName": "input filter", + "customNameId": 0, + "join": [] + }, + "conditions": [ + { + "comparisons": [ + { + "conditionIndex": 0, + "op": "!=", + "param": "playbook_input:file", + "value": "None" + } + ], + "conditionIndex": 0, + "customName": "file hash", + "logic": "and" + }, + { + "comparisons": [ + { + "conditionIndex": 1, + "op": "!=", + "param": "playbook_input:domain", + "value": "None" + } + ], + "conditionIndex": 1, + "customName": "domain", + "logic": "and" + } + ], + "functionId": 1, + "functionName": "input_filter", + "id": "2", + "type": "filter" + }, + "errors": {}, + "id": "2", + "type": "filter", + "warnings": { + "config": [ + "Reconfigure invalid datapath." + ] + }, + "x": 230, + "y": 148 + }, + "3": { + "data": { + "action": "hunt file", + "actionType": "investigate", + "advanced": { + "customName": "hunt file", + "customNameId": 0, + "join": [] + }, + "connector": "CrowdStrike OAuth API", + "connectorConfigs": [ + "crowdstrike" + ], + "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", + "connectorVersion": "v1", + "functionId": 1, + "functionName": "hunt_file", + "id": "3", + "parameters": { + "hash": "filtered-data:input_filter:condition_1:playbook_input:file", + "limit": "1000" + }, + "requiredParameters": [ + { + "data_type": "string", + "field": "hash" + }, + { + "data_type": "numeric", + "default": 100, + "field": "limit" + } + ], + "type": "action" + }, + "errors": {}, + "id": "3", + "type": "action", + "warnings": {}, + "x": 0, + "y": 328 + }, + "4": { + "data": { + "action": "hunt domain", + "actionType": "investigate", + "advanced": { + "customName": "hunt domain", + "customNameId": 0, + "join": [] + }, + "connector": "CrowdStrike OAuth API", + "connectorConfigs": [ + "crowdstrike" + ], + "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", + "connectorVersion": "v1", + "functionId": 1, + "functionName": "hunt_domain", + "id": "4", + "parameters": { + "domain": "filtered-data:input_filter:condition_2:playbook_input:domain", + "limit": "1000" + }, + "requiredParameters": [ + { + "data_type": "numeric", + "default": 100, + "field": "limit" + }, + { + "data_type": "string", + "field": "domain" + } + ], + "type": "action" + }, + "errors": {}, + "id": "4", + "type": "action", + "warnings": {}, + "x": 340, + "y": 328 + }, + "5": { + "data": { + "advanced": { + "join": [] + }, + "conditions": [ + { + "comparisons": [ + { + "conditionIndex": 0, + "op": ">", + "param": "hunt_file:action_result.summary.device_count", + "value": "0" + } + ], + "conditionIndex": 0, + "customName": "devices found", + "logic": "and" + } + ], + "functionId": 2, + "functionName": "filter_2", + "id": "5", + "type": "filter" + }, + "errors": {}, + "id": "5", + "type": "filter", + "warnings": {}, + "x": 60, + "y": 476 + }, + "6": { + "data": { + "advanced": { + "join": [] + }, + "conditions": [ + { + "comparisons": [ + { + "conditionIndex": 0, + "op": ">", + "param": "hunt_domain:action_result.summary.device_count", + "value": "0" + } + ], + "conditionIndex": 0, + "customName": "devices found", + "logic": "and" + } + ], + "functionId": 3, + "functionName": "filter_3", + "id": "6", + "type": "filter" + }, + "errors": {}, + "id": "6", + "type": "filter", + "warnings": {}, + "x": 400, + "y": 476 + }, + "7": { + "data": { + "advanced": { + "customName": "format report file", + "customNameId": 0, + "join": [] + }, + "functionId": 1, + "functionName": "format_report_file", + "id": "7", + "parameters": [ + "hunt_file:action_result.parameter.hash", + "get_systems_from_file:action_result.data.*.hostname", + "get_systems_from_file:action_result.data.*.local_ip", + "get_systems_from_file:action_result.data.*.os_version", + "get_systems_from_file:action_result.parameter.id" + ], + "template": "SOAR searched for occurrences of `{0}` within your environment using CrowdStrike. The table below shows a summary of the information gathered.\n\n| File | Computer | Last IP Address | OS | CrowdStrike AID | Source |\n| --- | --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | {3} | {4} | CrowdStrike OAuth API |\n%%\n\n", + "type": "format" + }, + "errors": {}, + "id": "7", + "type": "format", + "warnings": {}, + "x": 0, + "y": 800 + }, + "8": { + "data": { + "advanced": { + "customName": "format report domain", + "customNameId": 0, + "join": [] + }, + "functionId": 2, + "functionName": "format_report_domain", + "id": "8", + "parameters": [ + "hunt_domain:action_result.parameter.domain", + "get_systems_from_domain:action_result.data.*.hostname", + "get_systems_from_domain:action_result.data.*.local_ip", + "get_systems_from_domain:action_result.data.*.os_version", + "get_systems_from_domain:action_result.parameter.id" + ], + "template": "SOAR searched for occurrences of `{0}` within your environment using CrowdStrike. The table below shows a summary of the information gathered.\n\n| Domain | Computer | Last IP Address | OS | CrowdStrike AID | Source |\n| --- | --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | {3} | {4} | CrowdStrike OAuth API |\n%%\n", + "type": "format" + }, + "errors": {}, + "id": "8", + "type": "format", + "warnings": {}, + "x": 340, + "y": 804 + }, + "9": { + "data": { + "advanced": { + "customName": "build file output", + "customNameId": 0, + "join": [] + }, + "functionId": 1, + "functionName": "build_file_output", + "id": "9", + "inputParameters": [ + "hunt_file:action_result.parameter.hash", + "get_systems_from_file:action_result.data", + "hunt_file:action_result.summary.device_count" + ], + "outputVariables": [ + "observable_array" + ], + "type": "code" + }, + "errors": {}, + "id": "9", + "type": "code", + "userCode": "\n\n build_file_output__observable_array = []\n device_list = []\n indicator = hunt_file_parameter_hash[0]\n count = hunt_file_summary_device_count[0]\n \n # if AIDs that no longer exist saw the artifact, they can still \n # be included in the middle of the hunt response, but will return\n # empty-ish objects from the `get system info` action, so we need\n # to length check them\n \n # Build devices list\n for item in get_systems_from_file_result_item_0:\n if len(item) > 0:\n device = item[0]\n device_filtered = {\n \"name\": device['hostname'],\n \"id\": device['device_id'],\n \"ip_address\": device['local_ip'],\n \"operating_system\": device['os_version']\n }\n device_list.append(device_filtered)\n \n \n # Build observable object\n observable_array = {\n \"indicator\": indicator,\n \"type\": \"file\",\n \"total_count\": len(device_list),\n \"source\": \"Crowdstrike OAuth\",\n \"identifier_activity\": device_list\n }\n \n build_file_output__observable_array.append(observable_array)\n", + "warnings": {}, + "x": 0, + "y": 960 + } + }, + "notes": "Inputs: file, domain\nInteractions: CrowdStrike OAuth API\nActions: hunt file, hunt domain, get system info\nOutputs: observable, markdown report" + }, + "input_spec": [ + { + "contains": [ + "hash" + ], + "description": "", + "name": "file" + }, + { + "contains": [ + "domain" + ], + "description": "", + "name": "domain" + } + ], + "output_spec": [ + { + "contains": [], + "datapaths": [ + "build_file_output:custom_function:observable_array", + "build_domain_output:custom_function:observable_array" + ], + "deduplicate": false, + "description": "", + "metadata": {}, + "name": "observable" + }, + { + "contains": [], + "datapaths": [ + "format_report_file:formatted_data", + "format_report_domain:formatted_data" + ], + "deduplicate": false, + "description": "", + "metadata": {}, + "name": "markdown_report" + } + ], + "playbook_type": "data", + "python_version": "3", + "schema": "5.0.9", + "version": "6.0.0.114895" + }, + "create_time": "2023-03-30T22:25:27.497757+00:00", + "draft_mode": false, + "labels": [ + "*" + ], + "tags": [ + "identifier_activity", + "file_hash", + "domain", + "crowdstrike_oauth_api" + ] +} \ No newline at end of file diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.png b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1b25a10e46b741846b7be302465a5018961595 GIT binary patch literal 68535 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⃥!3Iuyevy=y*{WhDYi-y*C0NUd*kd*@fkv; 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 z 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 literal 0 HcmV?d00001 diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py new file mode 100644 index 0000000000..6926ea9a35 --- /dev/null +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py @@ -0,0 +1,433 @@ +""" +Accepts a file_hash or domain name, and asks CrowdStrike for a list of device IDs that have interacted with each. The list of IDs is then sent back to Crowdstrike to get more information, and then produces a normalized output and summary table. +""" + + +import phantom.rules as phantom +import json +from datetime import datetime, timedelta + + +@phantom.playbook_block() +def on_start(container): + phantom.debug('on_start() called') + + # call 'input_filter' block + input_filter(container=container) + + return + +@phantom.playbook_block() +def input_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("input_filter() called") + + # collect filtered artifact ids and results for 'if' condition 1 + matched_artifacts_1, matched_results_1 = phantom.condition( + container=container, + conditions=[ + ["playbook_input:file", "!=", None] + ], + name="input_filter:condition_1") + + # call connected blocks if filtered artifacts or results + if matched_artifacts_1 or matched_results_1: + hunt_file(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1) + + # collect filtered artifact ids and results for 'if' condition 2 + matched_artifacts_2, matched_results_2 = phantom.condition( + container=container, + conditions=[ + ["playbook_input:domain", "!=", None] + ], + name="input_filter:condition_2") + + # call connected blocks if filtered artifacts or results + if matched_artifacts_2 or matched_results_2: + hunt_domain(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_2, filtered_results=matched_results_2) + + return + + +@phantom.playbook_block() +def hunt_file(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("hunt_file() called") + + # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) + + filtered_input_0_file = phantom.collect2(container=container, datapath=["filtered-data:input_filter:condition_1:playbook_input:file"]) + + parameters = [] + + # build parameters list for 'hunt_file' call + for filtered_input_0_file_item in filtered_input_0_file: + if filtered_input_0_file_item[0] is not None: + parameters.append({ + "hash": filtered_input_0_file_item[0], + "limit": 1000, + }) + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.act("hunt file", parameters=parameters, name="hunt_file", assets=["crowdstrike"], callback=filter_2) + + return + + +@phantom.playbook_block() +def hunt_domain(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("hunt_domain() called") + + # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) + + filtered_input_0_domain = phantom.collect2(container=container, datapath=["filtered-data:input_filter:condition_2:playbook_input:domain"]) + + parameters = [] + + # build parameters list for 'hunt_domain' call + for filtered_input_0_domain_item in filtered_input_0_domain: + if filtered_input_0_domain_item[0] is not None: + parameters.append({ + "limit": 1000, + "domain": filtered_input_0_domain_item[0], + }) + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.act("hunt domain", parameters=parameters, name="hunt_domain", assets=["crowdstrike"], callback=filter_3) + + return + + +@phantom.playbook_block() +def filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("filter_2() called") + + # collect filtered artifact ids and results for 'if' condition 1 + matched_artifacts_1, matched_results_1 = phantom.condition( + container=container, + conditions=[ + ["hunt_file:action_result.summary.device_count", ">", 0] + ], + name="filter_2:condition_1") + + # call connected blocks if filtered artifacts or results + if matched_artifacts_1 or matched_results_1: + get_systems_from_file(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1) + + return + + +@phantom.playbook_block() +def filter_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("filter_3() called") + + # collect filtered artifact ids and results for 'if' condition 1 + matched_artifacts_1, matched_results_1 = phantom.condition( + container=container, + conditions=[ + ["hunt_domain:action_result.summary.device_count", ">", 0] + ], + name="filter_3:condition_1") + + # call connected blocks if filtered artifacts or results + if matched_artifacts_1 or matched_results_1: + get_systems_from_domain(action=action, success=success, container=container, results=results, handle=handle, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1) + + return + + +@phantom.playbook_block() +def format_report_file(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("format_report_file() called") + + template = """SOAR searched for occurrences of `{0}` within your environment using CrowdStrike. The table below shows a summary of the information gathered.\n\n| File | Computer | Last IP Address | OS | CrowdStrike AID | Source |\n| --- | --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | {3} | {4} | CrowdStrike OAuth API |\n%%\n\n""" + + # parameter list for template variable replacement + parameters = [ + "hunt_file:action_result.parameter.hash", + "get_systems_from_file:action_result.data.*.hostname", + "get_systems_from_file:action_result.data.*.local_ip", + "get_systems_from_file:action_result.data.*.os_version", + "get_systems_from_file:action_result.parameter.id" + ] + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.format(container=container, template=template, parameters=parameters, name="format_report_file") + + build_file_output(container=container) + + return + + +@phantom.playbook_block() +def format_report_domain(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("format_report_domain() called") + + template = """SOAR searched for occurrences of `{0}` within your environment using CrowdStrike. The table below shows a summary of the information gathered.\n\n| Domain | Computer | Last IP Address | OS | CrowdStrike AID | Source |\n| --- | --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | {3} | {4} | CrowdStrike OAuth API |\n%%\n""" + + # parameter list for template variable replacement + parameters = [ + "hunt_domain:action_result.parameter.domain", + "get_systems_from_domain:action_result.data.*.hostname", + "get_systems_from_domain:action_result.data.*.local_ip", + "get_systems_from_domain:action_result.data.*.os_version", + "get_systems_from_domain:action_result.parameter.id" + ] + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.format(container=container, template=template, parameters=parameters, name="format_report_domain") + + build_domain_output(container=container) + + return + + +@phantom.playbook_block() +def build_file_output(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("build_file_output() called") + + hunt_file_result_data = phantom.collect2(container=container, datapath=["hunt_file:action_result.parameter.hash","hunt_file:action_result.summary.device_count"], action_results=results) + get_systems_from_file_result_data = phantom.collect2(container=container, datapath=["get_systems_from_file:action_result.data"], action_results=results) + + hunt_file_parameter_hash = [item[0] for item in hunt_file_result_data] + hunt_file_summary_device_count = [item[1] for item in hunt_file_result_data] + get_systems_from_file_result_item_0 = [item[0] for item in get_systems_from_file_result_data] + + build_file_output__observable_array = None + + ################################################################################ + ## Custom Code Start + ################################################################################ + + + build_file_output__observable_array = [] + device_list = [] + indicator = hunt_file_parameter_hash[0] + count = hunt_file_summary_device_count[0] + + # if AIDs that no longer exist saw the artifact, they can still + # be included in the middle of the hunt response, but will return + # empty-ish objects from the `get system info` action, so we need + # to length check them + + # Build devices list + for item in get_systems_from_file_result_item_0: + if len(item) > 0: + device = item[0] + device_filtered = { + "name": device['hostname'], + "id": device['device_id'], + "ip_address": device['local_ip'], + "operating_system": device['os_version'] + } + device_list.append(device_filtered) + + + # Build observable object + observable_array = { + "indicator": indicator, + "type": "file", + "total_count": len(device_list), + "source": "Crowdstrike OAuth", + "identifier_activity": device_list + } + + build_file_output__observable_array.append(observable_array) + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.save_run_data(key="build_file_output:observable_array", value=json.dumps(build_file_output__observable_array)) + + return + + +@phantom.playbook_block() +def build_domain_output(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("build_domain_output() called") + + hunt_domain_result_data = phantom.collect2(container=container, datapath=["hunt_domain:action_result.parameter.domain","hunt_domain:action_result.summary.device_count"], action_results=results) + get_systems_from_domain_result_data = phantom.collect2(container=container, datapath=["get_systems_from_domain:action_result.data"], action_results=results) + + hunt_domain_parameter_domain = [item[0] for item in hunt_domain_result_data] + hunt_domain_summary_device_count = [item[1] for item in hunt_domain_result_data] + get_systems_from_domain_result_item_0 = [item[0] for item in get_systems_from_domain_result_data] + + build_domain_output__observable_array = None + + ################################################################################ + ## Custom Code Start + ################################################################################ + + + build_domain_output__observable_array = [] + device_list = [] + indicator = hunt_domain_parameter_domain[0] + count = hunt_domain_summary_device_count[0] + + # Build devices list + for item in get_systems_from_domain_result_item_0: + + # if AIDs that no longer exist saw the artifact, they can still + # be included in the middle of the hunt response, but will return + # empty-ish objects from the `get system info` action, so we need + # to length check them + + if len(item) > 0: + device = item[0] + device_filtered = { + "name": device['hostname'], + "id": device['device_id'], + "ip_address": device['local_ip'], + "operating_system": device['os_version'] + } + device_list.append(device_filtered) + + + # Build observable object + observable_array = { + "indicator": indicator, + "type": "domain", + "total_count": len(device_list), + "source": "Crowdstrike OAuth", + "identifier_activity": device_list + } + + build_domain_output__observable_array.append(observable_array) + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.save_run_data(key="build_domain_output:observable_array", value=json.dumps(build_domain_output__observable_array)) + + return + + +@phantom.playbook_block() +def get_systems_from_file(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("get_systems_from_file() called") + + # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) + + filtered_result_0_data_filter_2 = phantom.collect2(container=container, datapath=["filtered-data:filter_2:condition_1:hunt_file:action_result.data.*.device_id"]) + + parameters = [] + + # build parameters list for 'get_systems_from_file' call + for filtered_result_0_item_filter_2 in filtered_result_0_data_filter_2: + if filtered_result_0_item_filter_2[0] is not None: + parameters.append({ + "id": filtered_result_0_item_filter_2[0], + }) + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.act("get system info", parameters=parameters, name="get_systems_from_file", assets=["crowdstrike"], callback=format_report_file) + + return + + +@phantom.playbook_block() +def get_systems_from_domain(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("get_systems_from_domain() called") + + # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) + + filtered_result_0_data_filter_3 = phantom.collect2(container=container, datapath=["filtered-data:filter_3:condition_1:hunt_domain:action_result.data.*.device_id"]) + + parameters = [] + + # build parameters list for 'get_systems_from_domain' call + for filtered_result_0_item_filter_3 in filtered_result_0_data_filter_3: + if filtered_result_0_item_filter_3[0] is not None: + parameters.append({ + "id": filtered_result_0_item_filter_3[0], + }) + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.act("get system info", parameters=parameters, name="get_systems_from_domain", assets=["crowdstrike"], callback=format_report_domain) + + return + + +@phantom.playbook_block() +def on_finish(container, summary): + phantom.debug("on_finish() called") + + format_report_file = phantom.get_format_data(name="format_report_file") + format_report_domain = phantom.get_format_data(name="format_report_domain") + build_file_output__observable_array = json.loads(_ if (_ := phantom.get_run_data(key="build_file_output:observable_array")) != "" else "null") # pylint: disable=used-before-assignment + build_domain_output__observable_array = json.loads(_ if (_ := phantom.get_run_data(key="build_domain_output:observable_array")) != "" else "null") # pylint: disable=used-before-assignment + + observable_combined_value = phantom.concatenate(build_file_output__observable_array, build_domain_output__observable_array) + markdown_report_combined_value = phantom.concatenate(format_report_file, format_report_domain) + + output = { + "observable": observable_combined_value, + "markdown_report": markdown_report_combined_value, + } + + ################################################################################ + ## Custom Code Start + ################################################################################ + + # Write your custom code here... + + ################################################################################ + ## Custom Code End + ################################################################################ + + phantom.save_playbook_output_data(output=output) + + return \ No newline at end of file diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.yml b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.yml new file mode 100644 index 0000000000..6f2199de38 --- /dev/null +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.yml @@ -0,0 +1,22 @@ +name: CrowdStrike OAuth API Identifier Activity Analysis +id: 5299d9dc-e9c4-42fa-b051-92ace0ff816d +version: 1 +date: '2023-03-30' +author: Lou Stella, Splunk +type: Investigation +description: "Accepts a file hash or domain name, and asks CrowdStrike for a list of device IDs that have interacted with each. The list of IDs is then sent back to Crowdstrike to get more information, and then produces a normalized output and summary table." +playbook: CrowdStrike_OAuth_API_Identifier_Activity_Analysis +how_to_implement: This input playbook requires the Crowdstrike OAuth API connector to be configured. It is designed to work in conjunction with the Dynamic Identifier Activity Analysis playbook or other playbooks in the same style. +references: [] +app_list: + - CrowdStrike OAuth API +tags: + platform_tags: + - identifier_activity + - domain + - file_hash + playbook_type: Input + vpe_type: Modern + playbook_fields: [] + product: + - Splunk SOAR From e418c6b4ea6adad05b9657bad53a60b1f1bfdb3a Mon Sep 17 00:00:00 2001 From: Lou Stella Date: Thu, 30 Mar 2023 17:50:32 -0500 Subject: [PATCH 2/5] Updated asset name --- ...ike_OAuth_API_Identifier_Activity_Analysis.json | 14 +++++++------- ...trike_OAuth_API_Identifier_Activity_Analysis.py | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json index 1c1048bb20..9cdcfdf1bf 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json @@ -118,7 +118,7 @@ "targetPort": "8_in" } ], - "hash": "087adbe2d806f96cc17b09023f8b1ae68a56d1d9", + "hash": "9c4e7b32cc0b0e26cbefdc167d85e130fc59f118", "nodes": { "0": { "data": { @@ -134,7 +134,7 @@ "type": "start", "warnings": {}, "x": 190, - "y": -2.5579538487363607e-13 + "y": -3.197442310920451e-13 }, "1": { "data": { @@ -191,7 +191,7 @@ }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ - "crowdstrike" + "crowdstrike_oauth_api" ], "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", "connectorVersion": "v1", @@ -227,7 +227,7 @@ }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ - "crowdstrike" + "crowdstrike_oauth_api" ], "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", "connectorVersion": "v1", @@ -315,7 +315,7 @@ }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ - "crowdstrike" + "crowdstrike_oauth_api" ], "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", "connectorVersion": "v1", @@ -357,7 +357,7 @@ }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ - "crowdstrike" + "crowdstrike_oauth_api" ], "connectorId": "ae971ba5-3117-444a-8ac5-6ce779f3a232", "connectorVersion": "v1", @@ -582,7 +582,7 @@ "schema": "5.0.9", "version": "6.0.0.114895" }, - "create_time": "2023-03-30T22:25:27.497757+00:00", + "create_time": "2023-03-30T22:48:59.978744+00:00", "draft_mode": false, "labels": [ "*" diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py index 6926ea9a35..d04964da08 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py @@ -76,7 +76,7 @@ def hunt_file(action=None, success=None, container=None, results=None, handle=No ## Custom Code End ################################################################################ - phantom.act("hunt file", parameters=parameters, name="hunt_file", assets=["crowdstrike"], callback=filter_2) + phantom.act("hunt file", parameters=parameters, name="hunt_file", assets=["crowdstrike_oauth_api"], callback=filter_2) return @@ -109,7 +109,7 @@ def hunt_domain(action=None, success=None, container=None, results=None, handle= ## Custom Code End ################################################################################ - phantom.act("hunt domain", parameters=parameters, name="hunt_domain", assets=["crowdstrike"], callback=filter_3) + phantom.act("hunt domain", parameters=parameters, name="hunt_domain", assets=["crowdstrike_oauth_api"], callback=filter_3) return @@ -364,7 +364,7 @@ def get_systems_from_file(action=None, success=None, container=None, results=Non ## Custom Code End ################################################################################ - phantom.act("get system info", parameters=parameters, name="get_systems_from_file", assets=["crowdstrike"], callback=format_report_file) + phantom.act("get system info", parameters=parameters, name="get_systems_from_file", assets=["crowdstrike_oauth_api"], callback=format_report_file) return @@ -396,7 +396,7 @@ def get_systems_from_domain(action=None, success=None, container=None, results=N ## Custom Code End ################################################################################ - phantom.act("get system info", parameters=parameters, name="get_systems_from_domain", assets=["crowdstrike"], callback=format_report_domain) + phantom.act("get system info", parameters=parameters, name="get_systems_from_domain", assets=["crowdstrike_oauth_api"], callback=format_report_domain) return From e42d14a28284a3b2ec61cdb4b93f2c0247bdb704 Mon Sep 17 00:00:00 2001 From: Lou Stella Date: Wed, 5 Apr 2023 12:46:54 -0500 Subject: [PATCH 3/5] Added tooltips & renamed observable field values --- ...Auth_API_Identifier_Activity_Analysis.json | 40 ++++++++++++------- ..._OAuth_API_Identifier_Activity_Analysis.py | 16 +++++++- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json index 9cdcfdf1bf..e0a46d4553 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json @@ -118,7 +118,7 @@ "targetPort": "8_in" } ], - "hash": "9c4e7b32cc0b0e26cbefdc167d85e130fc59f118", + "hash": "347986cc4dc47b0ba94b00d3777abc45eb0311e6", "nodes": { "0": { "data": { @@ -134,7 +134,7 @@ "type": "start", "warnings": {}, "x": 190, - "y": -3.197442310920451e-13 + "y": -3.836930773104541e-13 }, "1": { "data": { @@ -157,7 +157,9 @@ "advanced": { "customName": "build domain output", "customNameId": 0, - "join": [] + "description": "First constructs a list of devices based upon details returned in previous actions, and then appends that list to the observable object which includes the context in which that list makes any sense", + "join": [], + "note": "Create Observable output for parent playbook" }, "functionId": 2, "functionName": "build_domain_output", @@ -175,7 +177,7 @@ "errors": {}, "id": "10", "type": "code", - "userCode": "\n\n build_domain_output__observable_array = []\n device_list = []\n indicator = hunt_domain_parameter_domain[0]\n count = hunt_domain_summary_device_count[0]\n \n # Build devices list\n for item in get_systems_from_domain_result_item_0:\n \n # if AIDs that no longer exist saw the artifact, they can still \n # be included in the middle of the hunt response, but will return\n # empty-ish objects from the `get system info` action, so we need\n # to length check them\n \n if len(item) > 0:\n device = item[0]\n device_filtered = {\n \"name\": device['hostname'],\n \"id\": device['device_id'],\n \"ip_address\": device['local_ip'],\n \"operating_system\": device['os_version']\n }\n device_list.append(device_filtered)\n \n \n # Build observable object\n observable_array = {\n \"indicator\": indicator,\n \"type\": \"domain\",\n \"total_count\": len(device_list),\n \"source\": \"Crowdstrike OAuth\",\n \"identifier_activity\": device_list\n }\n \n build_domain_output__observable_array.append(observable_array)\n", + "userCode": "\n\n build_domain_output__observable_array = []\n device_list = []\n indicator = hunt_domain_parameter_domain[0]\n count = hunt_domain_summary_device_count[0]\n \n # Build devices list\n for item in get_systems_from_domain_result_item_0:\n \n # if AIDs that no longer exist saw the artifact, they can still \n # be included in the middle of the hunt response, but will return\n # empty-ish objects from the `get system info` action, so we need\n # to length check them\n \n if len(item) > 0:\n device = item[0]\n device_filtered = {\n \"name\": device['hostname'],\n \"id\": device['device_id'],\n \"ip_address\": device['local_ip'],\n \"operating_system\": device['os_version']\n }\n device_list.append(device_filtered)\n \n \n # Build observable object\n observable_array = {\n \"value\": indicator,\n \"type\": \"domain\",\n \"total_count\": len(device_list),\n \"source\": \"Crowdstrike OAuth\",\n \"identifier_activity\": device_list\n }\n \n build_domain_output__observable_array.append(observable_array)\n", "warnings": {}, "x": 340, "y": 960 @@ -187,7 +189,8 @@ "advanced": { "customName": "get systems from file", "customNameId": 0, - "join": [] + "join": [], + "note": "Queries Crowdstrike for details about each of the agent IDs returned by the original query" }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ @@ -223,7 +226,8 @@ "advanced": { "customName": "get systems from domain", "customNameId": 0, - "join": [] + "join": [], + "note": "Queries Crowdstrike for details about each of the agent IDs returned by the original query" }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ @@ -311,7 +315,8 @@ "advanced": { "customName": "hunt file", "customNameId": 0, - "join": [] + "join": [], + "note": "Queries Crowdstrike for presence of hash within last 30 days" }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ @@ -344,7 +349,7 @@ "type": "action", "warnings": {}, "x": 0, - "y": 328 + "y": 320 }, "4": { "data": { @@ -353,7 +358,8 @@ "advanced": { "customName": "hunt domain", "customNameId": 0, - "join": [] + "join": [], + "note": "Queries Crowdstrike for presence of domain within last 30 days" }, "connector": "CrowdStrike OAuth API", "connectorConfigs": [ @@ -386,7 +392,7 @@ "type": "action", "warnings": {}, "x": 340, - "y": 328 + "y": 320 }, "5": { "data": { @@ -457,7 +463,8 @@ "advanced": { "customName": "format report file", "customNameId": 0, - "join": [] + "join": [], + "note": "Create Markdown report for parent playbook to output" }, "functionId": 1, "functionName": "format_report_file", @@ -484,7 +491,8 @@ "advanced": { "customName": "format report domain", "customNameId": 0, - "join": [] + "join": [], + "note": "Create Markdown report for parent playbook to output" }, "functionId": 2, "functionName": "format_report_domain", @@ -511,7 +519,9 @@ "advanced": { "customName": "build file output", "customNameId": 0, - "join": [] + "description": "First constructs a list of devices based upon details returned in previous actions, and then appends that list to the observable object which includes the context in which that list makes any sense", + "join": [], + "note": "Create Observable output for parent playbook" }, "functionId": 1, "functionName": "build_file_output", @@ -529,7 +539,7 @@ "errors": {}, "id": "9", "type": "code", - "userCode": "\n\n build_file_output__observable_array = []\n device_list = []\n indicator = hunt_file_parameter_hash[0]\n count = hunt_file_summary_device_count[0]\n \n # if AIDs that no longer exist saw the artifact, they can still \n # be included in the middle of the hunt response, but will return\n # empty-ish objects from the `get system info` action, so we need\n # to length check them\n \n # Build devices list\n for item in get_systems_from_file_result_item_0:\n if len(item) > 0:\n device = item[0]\n device_filtered = {\n \"name\": device['hostname'],\n \"id\": device['device_id'],\n \"ip_address\": device['local_ip'],\n \"operating_system\": device['os_version']\n }\n device_list.append(device_filtered)\n \n \n # Build observable object\n observable_array = {\n \"indicator\": indicator,\n \"type\": \"file\",\n \"total_count\": len(device_list),\n \"source\": \"Crowdstrike OAuth\",\n \"identifier_activity\": device_list\n }\n \n build_file_output__observable_array.append(observable_array)\n", + "userCode": "\n\n build_file_output__observable_array = []\n device_list = []\n indicator = hunt_file_parameter_hash[0]\n count = hunt_file_summary_device_count[0]\n \n # if AIDs that no longer exist saw the artifact, they can still \n # be included in the middle of the hunt response, but will return\n # empty-ish objects from the `get system info` action, so we need\n # to length check them\n \n # Build devices list\n for item in get_systems_from_file_result_item_0:\n if len(item) > 0:\n device = item[0]\n device_filtered = {\n \"name\": device['hostname'],\n \"id\": device['device_id'],\n \"ip_address\": device['local_ip'],\n \"operating_system\": device['os_version']\n }\n device_list.append(device_filtered)\n \n \n # Build observable object\n observable_array = {\n \"value\": indicator,\n \"type\": \"file\",\n \"total_count\": len(device_list),\n \"source\": \"Crowdstrike OAuth\",\n \"identifier_activity\": device_list\n }\n \n build_file_output__observable_array.append(observable_array)\n", "warnings": {}, "x": 0, "y": 960 @@ -582,7 +592,7 @@ "schema": "5.0.9", "version": "6.0.0.114895" }, - "create_time": "2023-03-30T22:48:59.978744+00:00", + "create_time": "2023-04-05T17:44:09.354587+00:00", "draft_mode": false, "labels": [ "*" diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py index d04964da08..14dae65999 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py @@ -220,6 +220,12 @@ def format_report_domain(action=None, success=None, container=None, results=None def build_file_output(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("build_file_output() called") + ################################################################################ + # First constructs a list of devices based upon details returned in previous actions, + # and then appends that list to the observable object which includes the context + # in which that list makes any sense + ################################################################################ + hunt_file_result_data = phantom.collect2(container=container, datapath=["hunt_file:action_result.parameter.hash","hunt_file:action_result.summary.device_count"], action_results=results) get_systems_from_file_result_data = phantom.collect2(container=container, datapath=["get_systems_from_file:action_result.data"], action_results=results) @@ -259,7 +265,7 @@ def build_file_output(action=None, success=None, container=None, results=None, h # Build observable object observable_array = { - "indicator": indicator, + "value": indicator, "type": "file", "total_count": len(device_list), "source": "Crowdstrike OAuth", @@ -280,6 +286,12 @@ def build_file_output(action=None, success=None, container=None, results=None, h def build_domain_output(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("build_domain_output() called") + ################################################################################ + # First constructs a list of devices based upon details returned in previous actions, + # and then appends that list to the observable object which includes the context + # in which that list makes any sense + ################################################################################ + hunt_domain_result_data = phantom.collect2(container=container, datapath=["hunt_domain:action_result.parameter.domain","hunt_domain:action_result.summary.device_count"], action_results=results) get_systems_from_domain_result_data = phantom.collect2(container=container, datapath=["get_systems_from_domain:action_result.data"], action_results=results) @@ -320,7 +332,7 @@ def build_domain_output(action=None, success=None, container=None, results=None, # Build observable object observable_array = { - "indicator": indicator, + "value": indicator, "type": "domain", "total_count": len(device_list), "source": "Crowdstrike OAuth", From abe03adbb846f5fa12109f5cb1cc128c15fc5887 Mon Sep 17 00:00:00 2001 From: Lou Stella Date: Tue, 11 Apr 2023 08:29:42 -0500 Subject: [PATCH 4/5] Added tooltips to filter blocks --- ...OAuth_API_Identifier_Activity_Analysis.json | 18 ++++++++++++------ ...e_OAuth_API_Identifier_Activity_Analysis.py | 12 ++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json index e0a46d4553..0297217dac 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json @@ -118,7 +118,7 @@ "targetPort": "8_in" } ], - "hash": "347986cc4dc47b0ba94b00d3777abc45eb0311e6", + "hash": "6fbaceb0c56e5b4cba3c787f795f38e72a4081f9", "nodes": { "0": { "data": { @@ -134,7 +134,7 @@ "type": "start", "warnings": {}, "x": 190, - "y": -3.836930773104541e-13 + "y": -4.476419235288631e-13 }, "1": { "data": { @@ -262,7 +262,9 @@ "advanced": { "customName": "input filter", "customNameId": 0, - "join": [] + "description": "Routing by indicator type", + "join": [], + "note": "Routing by indicator type" }, "conditions": [ { @@ -397,7 +399,9 @@ "5": { "data": { "advanced": { - "join": [] + "description": "Only proceed if there are results", + "join": [], + "note": "Only proceed if there are results" }, "conditions": [ { @@ -429,7 +433,9 @@ "6": { "data": { "advanced": { - "join": [] + "description": "Only proceed if there are results", + "join": [], + "note": "Only proceed if there are results" }, "conditions": [ { @@ -592,7 +598,7 @@ "schema": "5.0.9", "version": "6.0.0.114895" }, - "create_time": "2023-04-05T17:44:09.354587+00:00", + "create_time": "2023-04-11T13:28:13.131689+00:00", "draft_mode": false, "labels": [ "*" diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py index 14dae65999..221d712650 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py @@ -21,6 +21,10 @@ def on_start(container): def input_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("input_filter() called") + ################################################################################ + # Routing by indicator type + ################################################################################ + # collect filtered artifact ids and results for 'if' condition 1 matched_artifacts_1, matched_results_1 = phantom.condition( container=container, @@ -118,6 +122,10 @@ def hunt_domain(action=None, success=None, container=None, results=None, handle= def filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("filter_2() called") + ################################################################################ + # Only proceed if there are results + ################################################################################ + # collect filtered artifact ids and results for 'if' condition 1 matched_artifacts_1, matched_results_1 = phantom.condition( container=container, @@ -137,6 +145,10 @@ def filter_2(action=None, success=None, container=None, results=None, handle=Non def filter_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): phantom.debug("filter_3() called") + ################################################################################ + # Only proceed if there are results + ################################################################################ + # collect filtered artifact ids and results for 'if' condition 1 matched_artifacts_1, matched_results_1 = phantom.condition( container=container, From c5ea510e8fa0eb88494140905540206aa7dd4f25 Mon Sep 17 00:00:00 2001 From: Lou Stella Date: Thu, 4 May 2023 13:55:12 -0500 Subject: [PATCH 5/5] Addressed Kelby's points --- ...Auth_API_Identifier_Activity_Analysis.json | 29 ++++++++++------- ..._OAuth_API_Identifier_Activity_Analysis.py | 32 +++++++++---------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json index 0297217dac..3163993e1c 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.json @@ -118,7 +118,7 @@ "targetPort": "8_in" } ], - "hash": "6fbaceb0c56e5b4cba3c787f795f38e72a4081f9", + "hash": "c7b9d2b5a1844c8132fdec3f304241600cc45526", "nodes": { "0": { "data": { @@ -134,7 +134,7 @@ "type": "start", "warnings": {}, "x": 190, - "y": -4.476419235288631e-13 + "y": -5.115907697472721e-13 }, "1": { "data": { @@ -202,7 +202,7 @@ "functionName": "get_systems_from_file", "id": "12", "parameters": { - "id": "filtered-data:filter_2:condition_1:hunt_file:action_result.data.*.device_id" + "id": "filtered-data:file_results_filter:condition_1:hunt_file:action_result.data.*.device_id" }, "requiredParameters": [ { @@ -239,7 +239,7 @@ "functionName": "get_systems_from_domain", "id": "13", "parameters": { - "id": "filtered-data:filter_3:condition_1:hunt_domain:action_result.data.*.device_id" + "id": "filtered-data:domain_results_filter:condition_1:hunt_domain:action_result.data.*.device_id" }, "requiredParameters": [ { @@ -255,7 +255,7 @@ "type": "action", "warnings": {}, "x": 340, - "y": 656 + "y": 660 }, "2": { "data": { @@ -399,6 +399,8 @@ "5": { "data": { "advanced": { + "customName": "file results filter", + "customNameId": 0, "description": "Only proceed if there are results", "join": [], "note": "Only proceed if there are results" @@ -419,7 +421,7 @@ } ], "functionId": 2, - "functionName": "filter_2", + "functionName": "file_results_filter", "id": "5", "type": "filter" }, @@ -433,6 +435,8 @@ "6": { "data": { "advanced": { + "customName": "domain results filter", + "customNameId": 0, "description": "Only proceed if there are results", "join": [], "note": "Only proceed if there are results" @@ -453,7 +457,7 @@ } ], "functionId": 3, - "functionName": "filter_3", + "functionName": "domain_results_filter", "id": "6", "type": "filter" }, @@ -462,7 +466,7 @@ "type": "filter", "warnings": {}, "x": 400, - "y": 476 + "y": 480 }, "7": { "data": { @@ -558,14 +562,14 @@ "contains": [ "hash" ], - "description": "", + "description": "A file hash to look for within your Crowdstrike protected environment", "name": "file" }, { "contains": [ "domain" ], - "description": "", + "description": "A domain to look for within your Crowdstrike protected environment", "name": "domain" } ], @@ -598,7 +602,7 @@ "schema": "5.0.9", "version": "6.0.0.114895" }, - "create_time": "2023-04-11T13:28:13.131689+00:00", + "create_time": "2023-05-04T18:53:22.783269+00:00", "draft_mode": false, "labels": [ "*" @@ -607,6 +611,7 @@ "identifier_activity", "file_hash", "domain", - "crowdstrike_oauth_api" + "crowdstrike_oauth_api", + "D3-IAA" ] } \ No newline at end of file diff --git a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py index 221d712650..7838e41f6f 100644 --- a/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py +++ b/playbooks/CrowdStrike_OAuth_API_Identifier_Activity_Analysis.py @@ -80,7 +80,7 @@ def hunt_file(action=None, success=None, container=None, results=None, handle=No ## Custom Code End ################################################################################ - phantom.act("hunt file", parameters=parameters, name="hunt_file", assets=["crowdstrike_oauth_api"], callback=filter_2) + phantom.act("hunt file", parameters=parameters, name="hunt_file", assets=["crowdstrike_oauth_api"], callback=file_results_filter) return @@ -113,14 +113,14 @@ def hunt_domain(action=None, success=None, container=None, results=None, handle= ## Custom Code End ################################################################################ - phantom.act("hunt domain", parameters=parameters, name="hunt_domain", assets=["crowdstrike_oauth_api"], callback=filter_3) + phantom.act("hunt domain", parameters=parameters, name="hunt_domain", assets=["crowdstrike_oauth_api"], callback=domain_results_filter) return @phantom.playbook_block() -def filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): - phantom.debug("filter_2() called") +def file_results_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("file_results_filter() called") ################################################################################ # Only proceed if there are results @@ -132,7 +132,7 @@ def filter_2(action=None, success=None, container=None, results=None, handle=Non conditions=[ ["hunt_file:action_result.summary.device_count", ">", 0] ], - name="filter_2:condition_1") + name="file_results_filter:condition_1") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -142,8 +142,8 @@ def filter_2(action=None, success=None, container=None, results=None, handle=Non @phantom.playbook_block() -def filter_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): - phantom.debug("filter_3() called") +def domain_results_filter(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs): + phantom.debug("domain_results_filter() called") ################################################################################ # Only proceed if there are results @@ -155,7 +155,7 @@ def filter_3(action=None, success=None, container=None, results=None, handle=Non conditions=[ ["hunt_domain:action_result.summary.device_count", ">", 0] ], - name="filter_3:condition_1") + name="domain_results_filter:condition_1") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -367,15 +367,15 @@ def get_systems_from_file(action=None, success=None, container=None, results=Non # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) - filtered_result_0_data_filter_2 = phantom.collect2(container=container, datapath=["filtered-data:filter_2:condition_1:hunt_file:action_result.data.*.device_id"]) + filtered_result_0_data_file_results_filter = phantom.collect2(container=container, datapath=["filtered-data:file_results_filter:condition_1:hunt_file:action_result.data.*.device_id"]) parameters = [] # build parameters list for 'get_systems_from_file' call - for filtered_result_0_item_filter_2 in filtered_result_0_data_filter_2: - if filtered_result_0_item_filter_2[0] is not None: + for filtered_result_0_item_file_results_filter in filtered_result_0_data_file_results_filter: + if filtered_result_0_item_file_results_filter[0] is not None: parameters.append({ - "id": filtered_result_0_item_filter_2[0], + "id": filtered_result_0_item_file_results_filter[0], }) ################################################################################ @@ -399,15 +399,15 @@ def get_systems_from_domain(action=None, success=None, container=None, results=N # phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED'))) - filtered_result_0_data_filter_3 = phantom.collect2(container=container, datapath=["filtered-data:filter_3:condition_1:hunt_domain:action_result.data.*.device_id"]) + filtered_result_0_data_domain_results_filter = phantom.collect2(container=container, datapath=["filtered-data:domain_results_filter:condition_1:hunt_domain:action_result.data.*.device_id"]) parameters = [] # build parameters list for 'get_systems_from_domain' call - for filtered_result_0_item_filter_3 in filtered_result_0_data_filter_3: - if filtered_result_0_item_filter_3[0] is not None: + for filtered_result_0_item_domain_results_filter in filtered_result_0_data_domain_results_filter: + if filtered_result_0_item_domain_results_filter[0] is not None: parameters.append({ - "id": filtered_result_0_item_filter_3[0], + "id": filtered_result_0_item_domain_results_filter[0], }) ################################################################################