From 1f6d283c6391c8c3df45efa32f3856aa1ae3fd69 Mon Sep 17 00:00:00 2001 From: Kelby Shelton Date: Wed, 7 Jun 2023 13:58:16 -0500 Subject: [PATCH] VirusTotal Scoring Algo Fixes --- playbooks/VirusTotal_v3_Dynamic_Analysis.json | 26 +++--- playbooks/VirusTotal_v3_Dynamic_Analysis.py | 46 ++++++---- ...tal_v3_Identifier_Reputation_Analysis.json | 30 ++++--- ...Total_v3_Identifier_Reputation_Analysis.py | 86 ++++++++++++------- 4 files changed, 118 insertions(+), 70 deletions(-) mode change 100755 => 100644 playbooks/VirusTotal_v3_Dynamic_Analysis.json mode change 100755 => 100644 playbooks/VirusTotal_v3_Dynamic_Analysis.py diff --git a/playbooks/VirusTotal_v3_Dynamic_Analysis.json b/playbooks/VirusTotal_v3_Dynamic_Analysis.json old mode 100755 new mode 100644 index dc8fdd2e2b..1697b284b1 --- a/playbooks/VirusTotal_v3_Dynamic_Analysis.json +++ b/playbooks/VirusTotal_v3_Dynamic_Analysis.json @@ -120,7 +120,7 @@ } ], "globalCustomCode": "\n\n\nfrom math import log", - "hash": "c62a83f2b885857ecb0ed931a92f20293e4829a0", + "hash": "94337eb6a3725d1ec82b66a9f16e3f0dd4fbe956", "nodes": { "0": { "data": { @@ -136,7 +136,7 @@ "type": "start", "warnings": {}, "x": 180, - "y": 0 + "y": -6.394884621840902e-14 }, "1": { "data": { @@ -159,6 +159,8 @@ "advanced": { "customName": "file detonate filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Filters successful file detonation results.", "join": [], "note": "Filters successful file detonation results." @@ -214,7 +216,7 @@ "errors": {}, "id": "11", "type": "code", - "userCode": " # Reference for scores: https://schema.ocsf.io/objects/reputation\n #phantom.debug(\"filtered_result_0_summary: {}\".format(filtered_result_0_summary))\n #phantom.debug(\"filtered_result_0_data: {}\".format(filtered_result_0_data))\n #phantom.debug(\"filtered_result_0_data___scans: {}\".format(filtered_result_0_data___scans))\n #phantom.debug(\"filtered_result_0_data___attributes___category: {}\".format(filtered_result_0_data___attributes___category))\n #phantom.debug(\"vault_id_detonation_result_item_0: {}\".format(vault_id_detonation_result_item_0))\n \n\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 normalize_score_file__categories = []\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 # If there are only harmless verdicts and no suspicious entries, set score_id to 1.\n elif not summary_data['harmless'] and not suspect:\n score_id = 0\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\n phantom.debug(\"log_result: {}\".format(log_result))\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 #phantom.debug(\"normalize_score_file__file_score_object: {}\".format(normalize_score_file__file_score_object))\n #phantom.debug(\"normalize_score_file__scores: {}\".format(normalize_score_file__scores))\n\n", + "userCode": " # Reference for scores: https://schema.ocsf.io/objects/reputation\n #phantom.debug(\"filtered_result_0_summary: {}\".format(filtered_result_0_summary))\n #phantom.debug(\"filtered_result_0_data: {}\".format(filtered_result_0_data))\n #phantom.debug(\"filtered_result_0_data___scans: {}\".format(filtered_result_0_data___scans))\n #phantom.debug(\"filtered_result_0_data___attributes___category: {}\".format(filtered_result_0_data___attributes___category))\n #phantom.debug(\"vault_id_detonation_result_item_0: {}\".format(vault_id_detonation_result_item_0))\n \n\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 normalize_score_file__categories = []\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 # If there are only harmless verdicts and no suspicious entries, set score_id to 1.\n elif not summary_data['harmless'] and not suspect:\n score_id = 0\n else:\n if suspect and vendors:\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 \n if score_id > 10:\n score_id = 10\n \n elif suspect == 0:\n score_id = 0\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 #phantom.debug(\"normalize_score_file__file_score_object: {}\".format(normalize_score_file__file_score_object))\n #phantom.debug(\"normalize_score_file__scores: {}\".format(normalize_score_file__scores))\n\n", "warnings": {}, "x": 340, "y": 686 @@ -282,6 +284,8 @@ "advanced": { "customName": "url detonate filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Filters successful url reputation results.", "join": [], "note": "Filters successful url reputation results." @@ -318,6 +322,8 @@ "advanced": { "customName": "input filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Determine branches based on provided inputs.", "join": [], "note": "Determine branches based on provided inputs." @@ -358,11 +364,7 @@ "errors": {}, "id": "2", "type": "filter", - "warnings": { - "config": [ - "Reconfigure invalid datapath." - ] - }, + "warnings": {}, "x": 220, "y": 140 }, @@ -471,7 +473,7 @@ "errors": {}, "id": "6", "type": "code", - "userCode": "\n # Write your custom code here...\n #phantom.debug(\"filtered_result_0_data___attributes_categories: {}\".format(filtered_result_0_data___data_attributes_results___category))\n #phantom.debug(\"filtered_result_0_summary: {}\".format(filtered_result_0_summary))\n #phantom.debug(\"filtered_result_1_data___scans: {}\".format(filtered_result_1_data___scans))\n #phantom.debug(\"url_detonation_result_item_0: {}\".format(url_detonation_result_item_0))\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 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 #for category, summary_data in zip(url_categories_list, url_summary_list):\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 #phantom.debug(\"vendors: {}\".format(vendors))\n #phantom.debug(\"confidence: {}\".format(confidence))\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 #log_result = (suspect/vendors) # log imported from math in global code block\n #score_id = int(log_result * 100)\n #phantom.debug(\"log_result: {}\".format(log_result))\n \n if score_id > 10:\n score_id = 10\n \n if category != None:\n categories = [cat.lower() for cat in category.values()]\n categories = list(set(categories))\n else:\n 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 #phantom.debug(\"normalize_score_url__url_score_object: {}\".format(normalize_score_url__url_score_object))\n #phantom.debug(\"normalize_score_url__score: {}\".format(normalize_score_url__score))\n #phantom.debug(\"normalize_score_url__categories: {}\".format(normalize_score_url__categories))\n\n\n", + "userCode": "\n # Write your custom code here...\n #phantom.debug(\"filtered_result_0_data___attributes_categories: {}\".format(filtered_result_0_data___data_attributes_results___category))\n #phantom.debug(\"filtered_result_0_summary: {}\".format(filtered_result_0_summary))\n #phantom.debug(\"filtered_result_1_data___scans: {}\".format(filtered_result_1_data___scans))\n #phantom.debug(\"url_detonation_result_item_0: {}\".format(url_detonation_result_item_0))\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 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 #for category, summary_data in zip(url_categories_list, url_summary_list):\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 #phantom.debug(\"vendors: {}\".format(vendors))\n #phantom.debug(\"confidence: {}\".format(confidence))\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 if suspect and vendors:\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 \n if score_id > 10:\n score_id = 10\n \n elif suspect == 0:\n score_id = 0\n \n if category != None:\n categories = [cat.lower() for cat in category.values()]\n categories = list(set(categories))\n else:\n 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 #phantom.debug(\"normalize_score_url__url_score_object: {}\".format(normalize_score_url__url_score_object))\n #phantom.debug(\"normalize_score_url__score: {}\".format(normalize_score_url__score))\n #phantom.debug(\"normalize_score_url__categories: {}\".format(normalize_score_url__categories))\n\n\n", "warnings": {}, "x": 0, "y": 686 @@ -580,10 +582,10 @@ ], "playbook_type": "data", "python_version": "3", - "schema": "5.0.9", - "version": "6.0.0.114895" + "schema": "5.0.10", + "version": "6.0.1.123902" }, - "create_time": "2023-04-12T11:31:47.902551+00:00", + "create_time": "2023-06-07T18:52:45.928084+00:00", "draft_mode": false, "labels": [ "*" diff --git a/playbooks/VirusTotal_v3_Dynamic_Analysis.py b/playbooks/VirusTotal_v3_Dynamic_Analysis.py old mode 100755 new mode 100644 index a6e370baa3..a0a39fb8d7 --- a/playbooks/VirusTotal_v3_Dynamic_Analysis.py +++ b/playbooks/VirusTotal_v3_Dynamic_Analysis.py @@ -42,7 +42,8 @@ def input_filter(action=None, success=None, container=None, results=None, handle conditions=[ ["playbook_input:url", "!=", ""] ], - name="input_filter:condition_1") + name="input_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -54,7 +55,8 @@ def input_filter(action=None, success=None, container=None, results=None, handle conditions=[ ["playbook_input:vault_id", "!=", ""] ], - name="input_filter:condition_2") + name="input_filter:condition_2", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_2 or matched_results_2: @@ -201,15 +203,16 @@ def normalize_score_url(action=None, success=None, container=None, results=None, if summary_data['harmless'] and not suspect: score_id = 1 else: - # customize score calculation as desired - log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block - score_id = int(log_result * 10) + 3 - #log_result = (suspect/vendors) # log imported from math in global code block - #score_id = int(log_result * 100) - #phantom.debug("log_result: {}".format(log_result)) + if suspect and vendors: + # customize score calculation as desired + log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block + score_id = int(log_result * 10) + 3 - if score_id > 10: - score_id = 10 + if score_id > 10: + score_id = 10 + + elif suspect == 0: + score_id = 0 if category != None: categories = [cat.lower() for cat in category.values()] @@ -353,7 +356,8 @@ def file_detonate_filter(action=None, success=None, container=None, results=None conditions=[ ["file_detonation:action_result.status", "==", "success"] ], - name="file_detonate_filter:condition_1") + name="file_detonate_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -424,13 +428,16 @@ def normalize_score_file(action=None, success=None, container=None, results=None elif not summary_data['harmless'] and not suspect: score_id = 0 else: - # customize score calculation as desired - log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block - score_id = int(log_result * 10) + 3 - - phantom.debug("log_result: {}".format(log_result)) - if score_id > 10: - score_id = 10 + if suspect and vendors: + # customize score calculation as desired + log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block + score_id = int(log_result * 10) + 3 + + if score_id > 10: + score_id = 10 + + elif suspect == 0: + score_id = 0 score = score_table[str(score_id)] @@ -556,7 +563,8 @@ def url_detonate_filter(action=None, success=None, container=None, results=None, conditions=[ ["url_detonation_1:action_result.status", "==", "success"] ], - name="url_detonate_filter:condition_1") + name="url_detonate_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: diff --git a/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.json b/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.json index f8d5dd87b9..62dc4b317b 100644 --- a/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.json +++ b/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.json @@ -223,7 +223,7 @@ } ], "globalCustomCode": "from math import log", - "hash": "47f9704059c3b3c0ba13938c86d86e45a60fe41d", + "hash": "a8238a3c739344494a1e62969d380c8f4791d45f", "nodes": { "0": { "data": { @@ -239,7 +239,7 @@ "type": "start", "warnings": {}, "x": 530, - "y": -4.476419235288631e-13 + "y": -6.394884621840902e-13 }, "1": { "data": { @@ -399,7 +399,7 @@ "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", + "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 if suspect and vendors:\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 \n if score_id > 10:\n score_id = 10\n \n elif suspect == 0:\n score_id = 0\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 @@ -428,7 +428,7 @@ "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", + "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 if suspect and vendors:\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 \n if score_id > 10:\n score_id = 10\n \n elif suspect == 0:\n score_id = 0\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 @@ -457,7 +457,7 @@ "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", + "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 if suspect and vendors:\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 \n if score_id > 10:\n score_id = 10\n \n elif suspect == 0:\n score_id = 0\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 @@ -505,7 +505,7 @@ "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%%", + "template": "SOAR analyzed IP(s) using VirusTotal. The table below shows a summary of the information gathered.\n\n| IP Address | Normalized Score | Report Link | Source |\n| --- | --- | --- | --- |\n%%\n| `{0}` | {1} | https://www.virustotal.com/gui/ip-address/{0} | VirusTotal v3 |\n%%", "type": "format" }, "errors": {}, @@ -586,6 +586,8 @@ "advanced": { "customName": "inputs filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Determine branches based on provided inputs.", "join": [], "note": "Determine branches based on provided inputs." @@ -754,6 +756,8 @@ "advanced": { "customName": "url result filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Filters successful url reputation results.", "join": [], "note": "Filters successful url reputation results." @@ -790,6 +794,8 @@ "advanced": { "customName": "domain result filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Filters successful domain reputation results.", "join": [], "note": "Filters successful domain reputation results." @@ -826,6 +832,8 @@ "advanced": { "customName": "ip result filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Filters successful ip reputation results.", "join": [], "note": "Filters successful ip reputation results." @@ -862,6 +870,8 @@ "advanced": { "customName": "file result filter", "customNameId": 0, + "delimiter": ",", + "delimiter_enabled": true, "description": "Filters successful file reputation results.", "join": [], "note": "Filters successful file reputation results." @@ -977,7 +987,7 @@ "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", + "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 if suspect and vendors:\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 \n if score_id > 10:\n score_id = 10\n \n elif suspect == 0:\n score_id = 0\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 @@ -1049,10 +1059,10 @@ ], "playbook_type": "data", "python_version": "3", - "schema": "5.0.8", - "version": "5.5.0.108488" + "schema": "5.0.10", + "version": "6.0.1.123902" }, - "create_time": "2023-01-09T21:04:59.712759+00:00", + "create_time": "2023-06-07T18:53:28.722388+00:00", "draft_mode": false, "labels": [ "*" diff --git a/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.py b/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.py index d4885a7ba9..246f27dbf9 100644 --- a/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.py +++ b/playbooks/VirusTotal_v3_Identifier_Reputation_Analysis.py @@ -215,11 +215,16 @@ def normalize_score_url(action=None, success=None, container=None, results=None, if summary_data['harmless'] and not suspect: score_id = 1 else: - # customize score calculation as desired - log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block - score_id = int(log_result * 10) + 3 - if score_id > 10: - score_id = 10 + if suspect and vendors: + # customize score calculation as desired + log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block + score_id = int(log_result * 10) + 3 + + if score_id > 10: + score_id = 10 + + elif suspect == 0: + score_id = 0 categories = [cat.lower() for cat in category.values()] categories = list(set(categories)) @@ -412,11 +417,16 @@ def normalize_score_domain(action=None, success=None, container=None, results=No if summary_data['harmless'] and not suspect: score_id = 1 else: - # customize score calculation as desired - log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block - score_id = int(log_result * 10) + 3 - if score_id > 10: - score_id = 10 + if suspect and vendors: + # customize score calculation as desired + log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block + score_id = int(log_result * 10) + 3 + + if score_id > 10: + score_id = 10 + + elif suspect == 0: + score_id = 0 categories = [cat.lower() for cat in category.values()] categories = list(set(categories)) @@ -493,11 +503,16 @@ def normalize_score_ip(action=None, success=None, container=None, results=None, if summary_data['harmless'] and not suspect: score_id = 1 else: - # customize score calculation as desired - log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block - score_id = int(log_result * 10) + 3 - if score_id > 10: - score_id = 10 + if suspect and vendors: + # customize score calculation as desired + log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block + score_id = int(log_result * 10) + 3 + + if score_id > 10: + score_id = 10 + + elif suspect == 0: + score_id = 0 score = score_table[str(score_id)] @@ -568,11 +583,16 @@ def normalize_score_file(action=None, success=None, container=None, results=None if summary_data['harmless'] and not suspect: score_id = 1 else: - # customize score calculation as desired - log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block - score_id = int(log_result * 10) + 3 - if score_id > 10: - score_id = 10 + if suspect and vendors: + # customize score calculation as desired + log_result = log((suspect/vendors) * 100, 100) # log imported from math in global code block + score_id = int(log_result * 10) + 3 + + if score_id > 10: + score_id = 10 + + elif suspect == 0: + score_id = 0 score = score_table[str(score_id)] @@ -632,7 +652,7 @@ def format_report_ip(action=None, success=None, container=None, results=None, ha # Format a summary table with the information gathered from the playbook. ################################################################################ - 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%%""" + template = """SOAR analyzed IP(s) using VirusTotal. The table below shows a summary of the information gathered.\n\n| IP Address | Normalized Score | Report Link | Source |\n| --- | --- | --- | --- |\n%%\n| `{0}` | {1} | https://www.virustotal.com/gui/ip-address/{0} | VirusTotal v3 |\n%%""" # parameter list for template variable replacement parameters = [ @@ -706,7 +726,8 @@ def inputs_filter(action=None, success=None, container=None, results=None, handl conditions=[ ["playbook_input:url", "!=", ""] ], - name="inputs_filter:condition_1") + name="inputs_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -718,7 +739,8 @@ def inputs_filter(action=None, success=None, container=None, results=None, handl conditions=[ ["playbook_input:domain", "!=", ""] ], - name="inputs_filter:condition_2") + name="inputs_filter:condition_2", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_2 or matched_results_2: @@ -730,7 +752,8 @@ def inputs_filter(action=None, success=None, container=None, results=None, handl conditions=[ ["playbook_input:ip", "!=", ""] ], - name="inputs_filter:condition_3") + name="inputs_filter:condition_3", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_3 or matched_results_3: @@ -742,7 +765,8 @@ def inputs_filter(action=None, success=None, container=None, results=None, handl conditions=[ ["playbook_input:file_hash", "!=", ""] ], - name="inputs_filter:condition_4") + name="inputs_filter:condition_4", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_4 or matched_results_4: @@ -934,7 +958,8 @@ def url_result_filter(action=None, success=None, container=None, results=None, h conditions=[ ["url_reputation:action_result.status", "==", "success"] ], - name="url_result_filter:condition_1") + name="url_result_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -957,7 +982,8 @@ def domain_result_filter(action=None, success=None, container=None, results=None conditions=[ ["domain_reputation:action_result.status", "==", "success"] ], - name="domain_result_filter:condition_1") + name="domain_result_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -980,7 +1006,8 @@ def ip_result_filter(action=None, success=None, container=None, results=None, ha conditions=[ ["ip_reputation:action_result.status", "==", "success"] ], - name="ip_result_filter:condition_1") + name="ip_result_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: @@ -1003,7 +1030,8 @@ def file_result_filter(action=None, success=None, container=None, results=None, conditions=[ ["file_hash_reputation:action_result.status", "==", "success"] ], - name="file_result_filter:condition_1") + name="file_result_filter:condition_1", + delimiter=",") # call connected blocks if filtered artifacts or results if matched_artifacts_1 or matched_results_1: