{ "blockly": false, "blockly_xml": "", "category": "Identifier Reputation Analysis", "coa": { "data": { "description": "Accepts a URL, IP, Domain, or File_Hash and does reputation analysis on the objects. Generates a global report and a per observable sub-report and normalized score. The score can be customized based on a variety of factors.\n\nRef: https://d3fend.mitre.org/technique/d3f:IdentifierReputationAnalysis/", "edges": [ { "id": "port_5_to_port_6", "sourceNode": "5", "sourcePort": "5_out", "targetNode": "6", "targetPort": "6_in" }, { "id": "port_13_to_port_17", "sourceNode": "13", "sourcePort": "13_out", "targetNode": "17", "targetPort": "17_in" }, { "id": "port_15_to_port_18", "sourceNode": "15", "sourcePort": "15_out", "targetNode": "18", "targetPort": "18_in" }, { "id": "port_16_to_port_19", "sourceNode": "16", "sourcePort": "16_out", "targetNode": "19", "targetPort": "19_in" }, { "conditions": [ { "index": 0 } ], "id": "port_21_to_port_2", "sourceNode": "21", "sourcePort": "21_out", "targetNode": "2", "targetPort": "2_in" }, { "conditions": [ { "index": 1 } ], "id": "port_21_to_port_10", "sourceNode": "21", "sourcePort": "21_out", "targetNode": "10", "targetPort": "10_in" }, { "conditions": [ { "index": 2 } ], "id": "port_21_to_port_11", "sourceNode": "21", "sourcePort": "21_out", "targetNode": "11", "targetPort": "11_in" }, { "conditions": [ { "index": 3 } ], "id": "port_21_to_port_12", "sourceNode": "21", "sourcePort": "21_out", "targetNode": "12", "targetPort": "12_in" }, { "id": "port_17_to_port_22", "sourceNode": "17", "sourcePort": "17_out", "targetNode": "22", "targetPort": "22_in" }, { "id": "port_18_to_port_23", "sourceNode": "18", "sourcePort": "18_out", "targetNode": "23", "targetPort": "23_in" }, { "id": "port_19_to_port_24", "sourceNode": "19", "sourcePort": "19_out", "targetNode": "24", "targetPort": "24_in" }, { "id": "port_6_to_port_1", "sourceNode": "6", "sourcePort": "6_out", "targetNode": "1", "targetPort": "1_in" }, { "id": "port_22_to_port_1", "sourceNode": "22", "sourcePort": "22_out", "targetNode": "1", "targetPort": "1_in" }, { "id": "port_23_to_port_1", "sourceNode": "23", "sourcePort": "23_out", "targetNode": "1", "targetPort": "1_in" }, { "id": "port_24_to_port_1", "sourceNode": "24", "sourcePort": "24_out", "targetNode": "1", "targetPort": "1_in" }, { "id": "port_0_to_port_21", "sourceNode": "0", "sourcePort": "0_out", "targetNode": "21", "targetPort": "21_in" }, { "id": "port_2_to_port_27", "sourceNode": "2", "sourcePort": "2_out", "targetNode": "27", "targetPort": "27_in" }, { "conditions": [ { "index": 0 } ], "id": "port_27_to_port_9", "sourceNode": "27", "sourcePort": "27_out", "targetNode": "9", "targetPort": "9_in" }, { "id": "port_9_to_port_5", "sourceNode": "9", "sourcePort": "9_out", "targetNode": "5", "targetPort": "5_in" }, { "id": "port_10_to_port_29", "sourceNode": "10", "sourcePort": "10_out", "targetNode": "29", "targetPort": "29_in" }, { "conditions": [ { "index": 0 } ], "id": "port_29_to_port_13", "sourceNode": "29", "sourcePort": "29_out", "targetNode": "13", "targetPort": "13_in" }, { "id": "port_11_to_port_30", "sourceNode": "11", "sourcePort": "11_out", "targetNode": "30", "targetPort": "30_in" }, { "conditions": [ { "index": 0 } ], "id": "port_30_to_port_15", "sourceNode": "30", "sourcePort": "30_out", "targetNode": "15", "targetPort": "15_in" }, { "id": "port_12_to_port_31", "sourceNode": "12", "sourcePort": "12_out", "targetNode": "31", "targetPort": "31_in" }, { "conditions": [ { "index": 0 } ], "id": "port_31_to_port_16", "sourceNode": "31", "sourcePort": "31_out", "targetNode": "16", "targetPort": "16_in" } ], "globalCustomCode": "from math import log", "hash": "47f9704059c3b3c0ba13938c86d86e45a60fe41d", "nodes": { "0": { "data": { "advanced": { "join": [] }, "functionName": "on_start", "id": "0", "type": "start" }, "errors": {}, "id": "0", "type": "start", "warnings": {}, "x": 530, "y": -4.476419235288631e-13 }, "1": { "data": { "advanced": { "join": [] }, "functionId": 1, "functionName": "on_finish", "id": "1", "type": "end" }, "errors": {}, "id": "1", "type": "end", "userCode": "\n # This function is called after all actions are completed.\n # summary of all the action and/or all details of actions\n # can be collected here.\n\n # summary_json = phantom.get_summary()\n # if 'result' in summary_json:\n # for action_result in summary_json['result']:\n # if 'action_run_id' in action_result:\n # action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)\n # phantom.debug(action_results)\n\n", "warnings": {}, "x": 530, "y": 1236 }, "10": { "data": { "action": "domain reputation", "actionType": "investigate", "advanced": { "customName": "domain reputation", "customNameId": 0, "description": "Queries VirusTotal for information about the provided Domain(s)", "join": [], "note": "Queries VirusTotal for information about the provided Domain(s)" }, "connector": "VirusTotal v3", "connectorConfigs": [ "virustotal_v3" ], "connectorId": "3fe4875d-a4a7-47d3-9ef1-f9e63a6653a4", "connectorVersion": "v1", "functionId": 1, "functionName": "domain_reputation", "id": "10", "parameters": { "domain": "filtered-data:inputs_filter:condition_2:playbook_input:domain" }, "requiredParameters": [ { "data_type": "string", "field": "domain" } ], "type": "action" }, "errors": {}, "id": "10", "type": "action", "warnings": {}, "x": 340, "y": 328 }, "11": { "data": { "action": "ip reputation", "actionType": "investigate", "advanced": { "customName": "ip reputation", "customNameId": 0, "description": "Queries VirusTotal for information about the provided IP(s)", "join": [], "note": "Queries VirusTotal for information about the provided IP(s)" }, "connector": "VirusTotal v3", "connectorConfigs": [ "virustotal_v3" ], "connectorId": "3fe4875d-a4a7-47d3-9ef1-f9e63a6653a4", "connectorVersion": "v1", "functionId": 1, "functionName": "ip_reputation", "id": "11", "parameters": { "ip": "filtered-data:inputs_filter:condition_3:playbook_input:ip" }, "requiredParameters": [ { "data_type": "string", "field": "ip" } ], "type": "action" }, "errors": {}, "id": "11", "type": "action", "warnings": {}, "x": 680, "y": 328 }, "12": { "data": { "action": "file reputation", "actionType": "investigate", "advanced": { "customName": "file hash reputation", "customNameId": 0, "description": "Queries VirusTotal for information about the provided File Hash(es)", "join": [], "note": "Queries VirusTotal for information about the provided File Hash(es)" }, "connector": "VirusTotal v3", "connectorConfigs": [ "virustotal_v3" ], "connectorId": "3fe4875d-a4a7-47d3-9ef1-f9e63a6653a4", "connectorVersion": "v1", "functionId": 1, "functionName": "file_hash_reputation", "id": "12", "parameters": { "hash": "filtered-data:inputs_filter:condition_4:playbook_input:file_hash" }, "requiredParameters": [ { "data_type": "string", "field": "hash" } ], "type": "action" }, "errors": {}, "id": "12", "type": "action", "warnings": {}, "x": 1020, "y": 328 }, "13": { "data": { "advanced": { "customName": "normalize score domain", "customNameId": 0, "description": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections.", "join": [], "note": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections." }, "functionId": 4, "functionName": "normalize_score_domain", "id": "13", "inputParameters": [ "filtered-data:domain_result_filter:condition_1:domain_reputation:action_result.data.*.attributes.categories", "filtered-data:domain_result_filter:condition_1:domain_reputation:action_result.summary" ], "outputVariables": [ "domain_score_object", "score", "categories" ], "type": "code" }, "errors": {}, "id": "13", "type": "code", "userCode": "\n # Reference for scores: https://schema.ocsf.io/objects/reputation\n score_table = {\n \"0\":\"Unknown\",\n \"1\":\"Very_Safe\",\n \"2\":\"Safe\",\n \"3\":\"Probably_Safe\",\n \"4\":\"Leans_Safe\",\n \"5\":\"May_not_be_Safe\",\n \"6\":\"Exercise_Caution\",\n \"7\":\"Suspicious_or_Risky\",\n \"8\":\"Possibly_Malicious\",\n \"9\":\"Probably_Malicious\",\n \"10\":\"Malicious\"\n }\n \n # Assign Variables\n domain_categories_list = filtered_result_0_data___attributes_categories\n domain_summary_list = filtered_result_0_summary\n normalize_score_domain__domain_score_object = []\n normalize_score_domain__score = []\n normalize_score_domain__categories = []\n \n # VirusTotal v3 URL Data\n # Adjust logic as desired\n for category, summary_data in zip(domain_categories_list, domain_summary_list):\n \n # Set confidence based on percentage of vendors undetected\n # Reduce the confidence by percentage of vendors undetected.\n vendors = summary_data['harmless'] + summary_data['undetected'] + summary_data['malicious'] + summary_data['suspicious']\n confidence = 100 - int((summary_data['undetected']/vendors) * 100)\n \n # Normalize reputation on a 10 point scale based on number of malicious and suspicious divided by harmless vendors\n # This can be adjusted to include whatever logic is desired.\n suspect = summary_data['malicious'] + summary_data['suspicious']\n # If there are only harmless verdicts and no suspicious entries, set score_id to 1.\n if summary_data['harmless'] and not suspect:\n score_id = 1\n else:\n # customize score calculation as desired\n log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block\n score_id = int(log_result * 10) + 3\n if score_id > 10:\n score_id = 10\n \n categories = [cat.lower() for cat in category.values()]\n categories = list(set(categories))\n score = score_table[str(score_id)]\n \n # Attach final object\n normalize_score_domain__domain_score_object.append({'score': score, 'score_id': score_id, 'confidence': confidence, 'categories': categories})\n normalize_score_domain__score.append(score)\n normalize_score_domain__categories.append(categories)\n\n\n", "warnings": {}, "x": 340, "y": 700 }, "15": { "data": { "advanced": { "customName": "normalize score ip", "customNameId": 0, "description": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections.", "join": [], "note": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections." }, "functionId": 5, "functionName": "normalize_score_ip", "id": "15", "inputParameters": [ "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.summary" ], "outputVariables": [ "ip_score_object", "scores" ], "type": "code" }, "errors": {}, "id": "15", "type": "code", "userCode": "\n # Reference for scores: https://schema.ocsf.io/objects/reputation\n score_table = {\n \"0\":\"Unknown\",\n \"1\":\"Very_Safe\",\n \"2\":\"Safe\",\n \"3\":\"Probably_Safe\",\n \"4\":\"Leans_Safe\",\n \"5\":\"May_not_be_Safe\",\n \"6\":\"Exercise_Caution\",\n \"7\":\"Suspicious_or_Risky\",\n \"8\":\"Possibly_Malicious\",\n \"9\":\"Probably_Malicious\",\n \"10\":\"Malicious\"\n }\n \n ip_summary_list = filtered_result_0_summary\n normalize_score_ip__ip_score_object = []\n normalize_score_ip__scores = []\n \n for summary_data in ip_summary_list:\n # Set confidence based on percentage of vendors undetected\n # Reduce the confidence by percentage of vendors undetected.\n vendors = summary_data['harmless'] + summary_data['undetected'] + summary_data['malicious'] + summary_data['suspicious']\n confidence = 100 - int((summary_data['undetected']/vendors) * 100)\n \n # Normalize reputation on a 10 point scale based on number of malicious and suspicious divided by harmless vendors\n # This can be adjusted to include whatever logic is desired.\n suspect = summary_data['malicious'] + summary_data['suspicious']\n # If there are only harmless verdicts and no suspicious entries, set score_id to 1.\n if summary_data['harmless'] and not suspect:\n score_id = 1\n else:\n # customize score calculation as desired\n log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block\n score_id = int(log_result * 10) + 3\n if score_id > 10:\n score_id = 10\n \n score = score_table[str(score_id)]\n\n normalize_score_ip__ip_score_object.append({'score': score, 'score_id': score_id, 'confidence': confidence})\n normalize_score_ip__scores.append(score)\n \n", "warnings": {}, "x": 680, "y": 700 }, "16": { "data": { "advanced": { "customName": "normalize score file", "customNameId": 0, "description": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections.", "join": [], "note": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections." }, "functionId": 6, "functionName": "normalize_score_file", "id": "16", "inputParameters": [ "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.summary" ], "outputVariables": [ "file_score_object", "scores" ], "type": "code" }, "errors": {}, "id": "16", "type": "code", "userCode": "\n # Reference for scores: https://schema.ocsf.io/objects/reputation\n score_table = {\n \"0\":\"Unknown\",\n \"1\":\"Very_Safe\",\n \"2\":\"Safe\",\n \"3\":\"Probably_Safe\",\n \"4\":\"Leans_Safe\",\n \"5\":\"May_not_be_Safe\",\n \"6\":\"Exercise_Caution\",\n \"7\":\"Suspicious_or_Risky\",\n \"8\":\"Possibly_Malicious\",\n \"9\":\"Probably_Malicious\",\n \"10\":\"Malicious\"\n }\n \n file_summary_list = filtered_result_0_summary\n normalize_score_file__file_score_object = []\n normalize_score_file__scores = []\n \n for summary_data in file_summary_list:\n # Set confidence based on percentage of vendors undetected\n # Reduce the confidence by percentage of vendors undetected.\n vendors = summary_data['harmless'] + summary_data['undetected'] + summary_data['malicious'] + summary_data['suspicious']\n confidence = 100 - int((summary_data['undetected']/vendors) * 100)\n \n # Normalize reputation on a 10 point scale based on number of malicious and suspicious divided by harmless vendors\n # This can be adjusted to include whatever logic is desired.\n suspect = summary_data['malicious'] + summary_data['suspicious']\n # If there are only harmless verdicts and no suspicious entries, set score_id to 1.\n if summary_data['harmless'] and not suspect:\n score_id = 1\n else:\n # customize score calculation as desired\n log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block\n score_id = int(log_result * 10) + 3\n if score_id > 10:\n score_id = 10\n \n score = score_table[str(score_id)]\n\n normalize_score_file__file_score_object.append({'score': score, 'score_id': score_id, 'confidence': confidence})\n normalize_score_file__scores.append(score)\n", "warnings": {}, "x": 1020, "y": 680 }, "17": { "data": { "advanced": { "customName": "format report domain", "customNameId": 0, "description": "Format a summary table with the information gathered from the playbook.", "join": [], "note": "Format a summary table with the information gathered from the playbook." }, "functionId": 2, "functionName": "format_report_domain", "id": "17", "parameters": [ "filtered-data:domain_result_filter:condition_1:domain_reputation:action_result.parameter.domain", "normalize_score_domain:custom_function:score", "normalize_score_domain:custom_function:categories" ], "template": "SOAR analyzed Domain(s) using VirusTotal. The table below shows a summary of the information gathered.\n\n| Domain | Normalized Data | Categories | Report Link | Source |\n| --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | https://www.virustotal.com/gui/domain/{0} | VirusTotal v3 |\n%%", "type": "format" }, "errors": {}, "id": "17", "type": "format", "warnings": {}, "x": 340, "y": 880 }, "18": { "data": { "advanced": { "customName": "format report ip", "customNameId": 0, "description": "Format a summary table with the information gathered from the playbook.", "join": [], "note": "Format a summary table with the information gathered from the playbook." }, "functionId": 3, "functionName": "format_report_ip", "id": "18", "parameters": [ "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.parameter.ip", "normalize_score_ip:custom_function:scores" ], "template": "SOAR analyzed IP(s) using VirusTotal. The table below shows a summary of the information gathered.\n\n| IP Address | Normalized Data | Report Link | Source |\n| --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | | https://www.virustotal.com/gui/ip-address/{0} | VirusTotal v3 |\n%%", "type": "format" }, "errors": {}, "id": "18", "type": "format", "warnings": {}, "x": 680, "y": 880 }, "19": { "data": { "advanced": { "customName": "format report file", "customNameId": 0, "description": "Format a summary table with the information gathered from the playbook.", "join": [], "note": "Format a summary table with the information gathered from the playbook." }, "functionId": 4, "functionName": "format_report_file", "id": "19", "parameters": [ "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.parameter.hash", "normalize_score_file:custom_function:scores", "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.data.*.attributes.meaningful_name", "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.data.*.attributes.magic" ], "template": "SOAR analyzed file(s) using VirusTotal. The table below shows a summary of the information gathered.\n\n| File | VT Name | VT Decription | Normalized Score | Report Link | Source |\n| --- | --- | --- | --- | --- | --- |\n%%\n| `{0}` | {2} | {3} | {1} | https://www.virustotal.com/gui/file/{0} | VirusTotal v3 |\n%%\n\n", "type": "format" }, "errors": {}, "id": "19", "type": "format", "warnings": {}, "x": 1020, "y": 880 }, "2": { "data": { "action": "url reputation", "actionType": "investigate", "advanced": { "customName": "url reputation", "customNameId": 0, "description": "Queries VirusTotal for information about the provided URL(s)", "join": [], "note": "Queries VirusTotal for information about the provided URL(s)" }, "connector": "VirusTotal v3", "connectorConfigs": [ "virustotal_v3" ], "connectorId": "3fe4875d-a4a7-47d3-9ef1-f9e63a6653a4", "connectorVersion": "v1", "functionId": 1, "functionName": "url_reputation", "id": "2", "parameters": { "url": "filtered-data:inputs_filter:condition_1:playbook_input:url" }, "requiredParameters": [ { "data_type": "string", "field": "url" } ], "type": "action" }, "errors": {}, "id": "2", "type": "action", "warnings": {}, "x": 0, "y": 328 }, "21": { "data": { "advanced": { "customName": "inputs filter", "customNameId": 0, "description": "Determine branches based on provided inputs.", "join": [], "note": "Determine branches based on provided inputs." }, "conditions": [ { "comparisons": [ { "conditionIndex": 0, "op": "!=", "param": "playbook_input:url", "value": "" } ], "conditionIndex": 0, "customName": "url", "logic": "and" }, { "comparisons": [ { "conditionIndex": 1, "op": "!=", "param": "playbook_input:domain", "value": "" } ], "conditionIndex": 1, "customName": "domain", "logic": "and" }, { "comparisons": [ { "conditionIndex": 2, "op": "!=", "param": "playbook_input:ip", "value": "" } ], "conditionIndex": 2, "customName": "ip", "logic": "and" }, { "comparisons": [ { "conditionIndex": 3, "op": "!=", "param": "playbook_input:file_hash", "value": "" } ], "conditionIndex": 3, "customName": "file_hash", "logic": "and" } ], "functionId": 1, "functionName": "inputs_filter", "id": "21", "type": "filter" }, "errors": {}, "id": "21", "type": "filter", "warnings": {}, "x": 570, "y": 148 }, "22": { "data": { "advanced": { "customName": "build domain output", "customNameId": 0, "description": "Generate an observable dictionary to output into the observables data path.", "join": [], "note": "Generate an observable dictionary to output into the observables data path." }, "functionId": 3, "functionName": "build_domain_output", "id": "22", "inputParameters": [ "filtered-data:domain_result_filter:condition_1:domain_reputation:action_result.parameter.domain", "normalize_score_domain:custom_function:domain_score_object" ], "outputVariables": [ "observable_array" ], "type": "code" }, "errors": {}, "id": "22", "type": "code", "userCode": "\n build_domain_output__observable_array = []\n\n # Build URL\n for domain, domain_object in zip(filtered_result_0_parameter_domain, normalize_score_domain__domain_score_object):\n observable_object = {\n \"value\": domain,\n \"type\": \"domain\",\n \"reputation\": {\n \"score_id\": domain_object['score_id'],\n \"score\": domain_object['score'],\n \"confidence\": domain_object['confidence']\n },\n \"categories\": domain_object['categories'],\n \"source\": \"VirusTotal v3\",\n \"source_link\": f\"https://www.virustotal.com/gui/domain/{domain}\"\n }\n build_domain_output__observable_array.append(observable_object)\n \n\n", "warnings": {}, "x": 340, "y": 1060 }, "23": { "data": { "advanced": { "customName": "build ip output", "customNameId": 0, "description": "Generate an observable dictionary to output into the observables data path.", "join": [], "note": "Generate an observable dictionary to output into the observables data path." }, "functionId": 7, "functionName": "build_ip_output", "id": "23", "inputParameters": [ "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.parameter.ip", "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.data.*.attributes.country", "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.data.*.attributes.network", "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.data.*.attributes.as_owner", "filtered-data:ip_result_filter:condition_1:ip_reputation:action_result.data.*.attributes.continent", "normalize_score_ip:custom_function:ip_score_object" ], "outputVariables": [ "observable_array" ], "type": "code" }, "errors": {}, "id": "23", "type": "code", "userCode": "\n build_ip_output__observable_array = []\n \n # Build IP\n for ip, country, network, as_owner, continent, ip_object in zip(\n filtered_result_0_parameter_ip, \n filtered_result_0_data___attributes_country,\n filtered_result_0_data___attributes_network,\n filtered_result_0_data___attributes_as_owner,\n filtered_result_0_data___attributes_continent,\n normalize_score_ip__ip_score_object\n ):\n observable_object = {\n \"value\": ip,\n \"type\": \"ip\",\n \"reputation\": {\n \"score_id\": ip_object['score_id'],\n \"score\": ip_object['score'],\n \"confidence\": ip_object['confidence']\n },\n \"enrichment\": {\n \"provider\": \"VirusTotal v3\",\n \"type\": \"whois\",\n \"data\": {\n \"country\": country,\n \"network\": network,\n \"as_owner\": as_owner,\n \"continent\": continent\n }\n },\n \"source\": \"VirusTotal v3\",\n \"source_link\": f\"https://www.virustotal.com/gui/ip-address/{ip}\"\n }\n build_ip_output__observable_array.append(observable_object)\n \n \n", "warnings": {}, "x": 680, "y": 1060 }, "24": { "data": { "advanced": { "customName": "build file hash output", "customNameId": 0, "description": "Generate an observable dictionary to output into the observables data path.", "join": [], "note": "Generate an observable dictionary to output into the observables data path." }, "functionId": 8, "functionName": "build_file_hash_output", "id": "24", "inputParameters": [ "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.parameter.hash", "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.data.*.attributes.meaningful_name", "filtered-data:file_result_filter:condition_1:file_hash_reputation:action_result.data.*.attributes.type_description", "normalize_score_file:custom_function:file_score_object" ], "outputVariables": [ "observable_array" ], "type": "code" }, "errors": {}, "id": "24", "type": "code", "userCode": " \n build_file_hash_output__observable_array = []\n # Build file_hash\n for file_hash, file_name, file_type, file_object in zip(filtered_result_0_parameter_hash, filtered_result_0_data___attributes_meaningful_name, filtered_result_0_data___attributes_type_description, normalize_score_file__file_score_object):\n observable_object = {\n \"value\": file_hash,\n \"type\": \"hash\",\n \"reputation\": {\n \"score_id\": file_object['score_id'],\n \"score\": file_object['score'],\n \"confidence\": file_object['confidence']\n },\n \"enrichment\": {\n \"provider\": \"VirusTotal v3\",\n \"type\": \"file\",\n \"data\": {\n \"meaningful_name\": file_name,\n \"magic\": file_type\n }\n },\n \"source\": \"VirusTotal v3\",\n \"source_link\": f\"https://www.virustotal.com/gui/file/{file_hash}\"\n }\n \n build_file_hash_output__observable_array.append(observable_object)\n\n", "warnings": {}, "x": 1020, "y": 1060 }, "27": { "data": { "advanced": { "customName": "url result filter", "customNameId": 0, "description": "Filters successful url reputation results.", "join": [], "note": "Filters successful url reputation results." }, "conditions": [ { "comparisons": [ { "conditionIndex": 0, "op": "==", "param": "url_reputation:action_result.status", "value": "success" } ], "conditionIndex": 0, "customName": "success", "logic": "and" } ], "functionId": 2, "functionName": "url_result_filter", "id": "27", "type": "filter" }, "errors": {}, "id": "27", "type": "filter", "warnings": {}, "x": 60, "y": 506 }, "29": { "data": { "advanced": { "customName": "domain result filter", "customNameId": 0, "description": "Filters successful domain reputation results.", "join": [], "note": "Filters successful domain reputation results." }, "conditions": [ { "comparisons": [ { "conditionIndex": 0, "op": "==", "param": "domain_reputation:action_result.status", "value": "success" } ], "conditionIndex": 0, "customName": "success", "logic": "and" } ], "functionId": 3, "functionName": "domain_result_filter", "id": "29", "type": "filter" }, "errors": {}, "id": "29", "type": "filter", "warnings": {}, "x": 400, "y": 506 }, "30": { "data": { "advanced": { "customName": "ip result filter", "customNameId": 0, "description": "Filters successful ip reputation results.", "join": [], "note": "Filters successful ip reputation results." }, "conditions": [ { "comparisons": [ { "conditionIndex": 0, "op": "==", "param": "ip_reputation:action_result.status", "value": "success" } ], "conditionIndex": 0, "customName": "success", "logic": "and" } ], "functionId": 4, "functionName": "ip_result_filter", "id": "30", "type": "filter" }, "errors": {}, "id": "30", "type": "filter", "warnings": {}, "x": 740, "y": 506 }, "31": { "data": { "advanced": { "customName": "file result filter", "customNameId": 0, "description": "Filters successful file reputation results.", "join": [], "note": "Filters successful file reputation results." }, "conditions": [ { "comparisons": [ { "conditionIndex": 0, "op": "==", "param": "file_hash_reputation:action_result.status", "value": "success" } ], "conditionIndex": 0, "customName": "success", "logic": "and" } ], "functionId": 5, "functionName": "file_result_filter", "id": "31", "type": "filter" }, "errors": {}, "id": "31", "type": "filter", "warnings": {}, "x": 1080, "y": 506 }, "5": { "data": { "advanced": { "customName": "format report url", "customNameId": 0, "description": "Format a summary table with the information gathered from the playbook.", "join": [], "note": "Format a summary table with the information gathered from the playbook." }, "functionId": 1, "functionName": "format_report_url", "id": "5", "parameters": [ "filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url", "normalize_score_url:custom_function:score", "normalize_score_url:custom_function:categories", "filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.id" ], "template": "SOAR analyzed URL(s) using VirusTotal. The table below shows a summary of the information gathered.\n\n| URL | Normalized Score | Categories | Report Link | Source |\n| --- | --- | --- | --- | --- |\n%%\n| `{0}` | {1} | {2} | https://www.virustotal.com/gui/url/{3} | VirusTotal v3 |\n%%", "type": "format" }, "errors": {}, "id": "5", "type": "format", "warnings": {}, "x": 0, "y": 880 }, "6": { "data": { "advanced": { "customName": "build url output", "customNameId": 0, "description": "Generate an observable dictionary to output into the observables data path.", "join": [], "note": "Generate an observable dictionary to output into the observables data path." }, "functionId": 1, "functionName": "build_url_output", "id": "6", "inputParameters": [ "filtered-data:url_result_filter:condition_1:url_reputation:action_result.parameter.url", "filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.id", "normalize_score_url:custom_function:url_score_object" ], "outputVariables": [ "observable_array" ], "type": "code" }, "errors": {}, "id": "6", "type": "code", "userCode": " from urllib.parse import urlparse\n build_url_output__observable_array = []\n\n # Build URL\n for url, external_id, url_object in zip(filtered_result_0_parameter_url, filtered_result_0_data___id, normalize_score_url__url_score_object):\n parsed_url = urlparse(url)\n observable_object = {\n \"value\": url,\n \"type\": \"url\",\n \"reputation\": {\n \"score_id\": url_object['score_id'],\n \"score\": url_object['score'],\n \"confidence\": url_object['confidence']\n },\n \"attributes\": {\n \"hostname\": parsed_url.hostname,\n \"scheme\": parsed_url.scheme\n },\n \"categories\": url_object['categories'],\n \"source\": \"VirusTotal v3\",\n \"source_link\": f\"https://www.virustotal.com/gui/url/{external_id}\"\n }\n if parsed_url.path:\n observable_object['attributes']['path'] = parsed_url.path\n if parsed_url.query:\n observable_object['attributes']['query'] = parsed_url.query\n if parsed_url.port:\n observable_object['attributes']['port'] = parsed_url.port\n \n build_url_output__observable_array.append(observable_object)\n \n", "warnings": {}, "x": 0, "y": 1060 }, "9": { "data": { "advanced": { "customName": "normalize score url", "customNameId": 0, "description": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections.", "join": [], "note": "Contains custom code for normalizing score. Adjust the logic as desired in the documented sections." }, "functionId": 2, "functionName": "normalize_score_url", "id": "9", "inputParameters": [ "filtered-data:url_result_filter:condition_1:url_reputation:action_result.data.*.attributes.categories", "filtered-data:url_result_filter:condition_1:url_reputation:action_result.summary" ], "outputVariables": [ "url_score_object", "score", "categories" ], "type": "code" }, "errors": {}, "id": "9", "type": "code", "userCode": " \n # Reference for scores: https://schema.ocsf.io/objects/reputation\n score_table = {\n \"0\":\"Unknown\",\n \"1\":\"Very_Safe\",\n \"2\":\"Safe\",\n \"3\":\"Probably_Safe\",\n \"4\":\"Leans_Safe\",\n \"5\":\"May_not_be_Safe\",\n \"6\":\"Exercise_Caution\",\n \"7\":\"Suspicious_or_Risky\",\n \"8\":\"Possibly_Malicious\",\n \"9\":\"Probably_Malicious\",\n \"10\":\"Malicious\"\n }\n \n # Assign Variables\n url_categories_list = filtered_result_0_data___attributes_categories\n url_summary_list = filtered_result_0_summary\n normalize_score_url__url_score_object = []\n normalize_score_url__score = []\n normalize_score_url__categories = []\n \n # VirusTotal v3 URL Data\n # Adjust logic as desired\n for category, summary_data in zip(url_categories_list, url_summary_list):\n\n # Set confidence based on percentage of vendors undetected\n # Reduce the confidence by percentage of vendors undetected.\n vendors = summary_data['harmless'] + summary_data['undetected'] + summary_data['malicious'] + summary_data['suspicious']\n confidence = 100 - int((summary_data['undetected']/vendors) * 100)\n \n # Normalize reputation on a 10 point scale based on number of malicious and suspicious divided by harmless vendors\n # This can be adjusted to include whatever logic is desired.\n suspect = summary_data['malicious'] + summary_data['suspicious']\n # If there are only harmless verdicts and no suspicious entries, set score_id to 1.\n if summary_data['harmless'] and not suspect:\n score_id = 1\n else:\n # customize score calculation as desired\n log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block\n score_id = int(log_result * 10) + 3\n if score_id > 10:\n score_id = 10\n \n categories = [cat.lower() for cat in category.values()]\n categories = list(set(categories))\n \n score = score_table[str(score_id)]\n \n # Attach final object\n normalize_score_url__url_score_object.append({'score': score, 'score_id': score_id, 'confidence': confidence, 'categories': categories})\n normalize_score_url__score.append(score)\n normalize_score_url__categories.append(categories)\n\n", "warnings": {}, "x": 0, "y": 694 } }, "notes": "Inputs: url, ip, domain, file_hash\nInteractions: VirusTotal v3\nActions: url reputation, ip reputation, domain reputation, file reputation\nOutputs: report, observables" }, "input_spec": [ { "contains": [ "url" ], "description": "A URL provided for reputation analysis", "name": "url" }, { "contains": [ "domain" ], "description": "A Domain provided for reputation analysis", "name": "domain" }, { "contains": [ "ip" ], "description": "A IP provided for reputation analysis", "name": "ip" }, { "contains": [ "hash", "sha1", "sha256", "sha512", "md5" ], "description": "A file_hash provided for reputation analysis", "name": "file_hash" } ], "output_spec": [ { "contains": [], "datapaths": [ "build_url_output:custom_function:observable_array", "build_domain_output:custom_function:observable_array", "build_ip_output:custom_function:observable_array", "build_file_hash_output:custom_function:observable_array" ], "deduplicate": false, "description": "An array of observable dictionaries with value, type, score, score_id, and categories.", "metadata": {}, "name": "observable" }, { "contains": [], "datapaths": [ "format_report_url:formatted_data", "format_report_domain:formatted_data", "format_report_ip:formatted_data", "format_report_file:formatted_data" ], "deduplicate": false, "description": "An array of reports. One report per reputation category.", "metadata": {}, "name": "markdown_report" } ], "playbook_type": "data", "python_version": "3", "schema": "5.0.8", "version": "5.5.0.108488" }, "create_time": "2023-01-09T21:04:59.712759+00:00", "draft_mode": false, "labels": [ "*" ], "tags": [ "reputation", "url", "ip", "domain", "file_hash", "D3-IRA", "D3-URA", "D3-DNRA", "D3-IPRA", "D3-FHRA", "VirusTotal_v3" ] }