From 3d6c4dcf4816e7adb6d7bcb436924a66b4d6ceaf Mon Sep 17 00:00:00 2001 From: Dante Acosta Date: Mon, 24 Jun 2024 13:59:34 -0300 Subject: [PATCH 1/4] fixed ommiting presets when data not available --- .../executors/official/cisco_cybervision.py | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py b/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py index 2ddfb825..9079d2db 100644 --- a/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py +++ b/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py @@ -3,12 +3,13 @@ import re import sys import json +import time import datetime import requests from urllib3.exceptions import InsecureRequestWarning from faraday_agent_dispatcher.utils.severity_utils import severity_from_score -API_BASE = "/api/3.0/" +API_BASE = "/api/3.0" def log(msg, end="\n"): @@ -22,7 +23,7 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): presets_id = {} # STAGE 1 - get preset list - req_url = f"{url}{API_BASE}presets" + req_url = f"{url}{API_BASE}/presets" try: resp = requests.get(req_url, headers=req_headers, timeout=20, verify=False).json() except TimeoutError: @@ -41,15 +42,46 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): presets_vuln_collection = {} step_c = 1 step_s = 100 + + for _id in presets_queue: # post to update to latest computed data + req_refresh_url = f"{url}{API_BASE}/presets/{_id}/refreshData" + try: + resp = requests.post(req_refresh_url, headers=req_headers, timeout=20, verify=False) + except TimeoutError: + log("Can't reach Cyber Vision: connection timed out") + sys.exit(1) + for _id in presets_queue: + serv_c = 0 + while True: # wait until data is ready + req_test_url = f"{url}{API_BASE}/presets/{_id}/visualisations/vulnerability-list?page=1&size=5" + try: + resp = requests.get(req_test_url, headers=req_headers, timeout=20, verify=False) + if "Service unavailable" in resp.content.decode("UTF-8"): + if serv_c == 0: + log(f"Preset {_id} data is not ready, waiting...") + serv_c += 1 + else: + log(f"Preset {_id} data is ready!") + serv_c = 0 + break + if serv_c >= 60: + break + except TimeoutError: + log("Can't reach Cyber Vision: connection timed out") + sys.exit(1) + time.sleep(1) + + if serv_c >= 60: + log(f"Error: Preset {_id} took many time to refresh data") + continue + step_c = 1 presets_vuln_collection[_id] = [] - while True: - req_url = f"{url}{API_BASE}presets/{_id}/visualisations/" f"vulnerability-list?page={step_c}&size={step_s}" + while True: # paged data fetch + req_url = f"{url}{API_BASE}/presets/{_id}/visualisations/vulnerability-list?page={step_c}&size={step_s}" try: resp = requests.get(req_url, headers=req_headers, timeout=20, verify=False) - if resp.content.decode("UTF-8") == "Service unavailable: data is not available yet": - raise ValueError(resp.content.decode("UTF-8")) resp = resp.json() except TimeoutError: log("Can't reach Cyber Vision: connection timed out") From 432eb12a84a087ad0bacfba4dce4250af67eb626 Mon Sep 17 00:00:00 2001 From: Diego Nadares Date: Tue, 25 Jun 2024 13:59:28 -0300 Subject: [PATCH 2/4] Add scans filtering at the moment of getting available scans. --- CHANGELOG/current/223.md | 1 + .../static/executors/official/tenablesc.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG/current/223.md diff --git a/CHANGELOG/current/223.md b/CHANGELOG/current/223.md new file mode 100644 index 00000000..6d1144ad --- /dev/null +++ b/CHANGELOG/current/223.md @@ -0,0 +1 @@ +[FIX] Implemented scan filtering by 'completed' status in Tenable SC Agent to prevent parsing errors. #223 diff --git a/faraday_agent_dispatcher/static/executors/official/tenablesc.py b/faraday_agent_dispatcher/static/executors/official/tenablesc.py index 01cb0fc7..5729acab 100644 --- a/faraday_agent_dispatcher/static/executors/official/tenablesc.py +++ b/faraday_agent_dispatcher/static/executors/official/tenablesc.py @@ -3,6 +3,7 @@ import io import sys import zipfile as zp + from tenable.sc import TenableSC from faraday_plugins.plugins.repo.nessus.plugin import NessusPlugin @@ -13,8 +14,11 @@ def log(msg): def get_only_usable_ids(tsc, scan_ids): tenable_scans = tsc.scan_instances.list() - usable_tenable_scans = [str(scan["id"]) for scan in tenable_scans["usable"]] + usable_tenable_scans = [str(scan["id"]) for scan in tenable_scans["usable"] if scan["status"] == "Completed"] + log("*" * 10) + log("Listing available scans ...") log(usable_tenable_scans) + log("*" * 10) return [_id for _id in scan_ids if str(_id) in usable_tenable_scans] @@ -81,7 +85,16 @@ def main(): tsc = TenableSC(host=TENABLE_HOST, access_key=TENABLE_ACCESS_KEY, secret_key=TENABLE_SECRET_KEY) usable_scan_ids = get_only_usable_ids(tsc, tenable_scan_ids_list) - log(usable_scan_ids) + if not usable_scan_ids: + log("*" * 10) + log("No Scan matched ...") + log("*" * 10) + exit(1) + + log("*" * 10) + log("Scans matched ...") + log(f"{usable_scan_ids}") + log("*" * 10) responses = [] for scan_id in usable_scan_ids: From 98b35cf12a3a2b62af238f9b191d00007dad6172 Mon Sep 17 00:00:00 2001 From: Dante Acosta Date: Wed, 26 Jun 2024 11:30:04 -0300 Subject: [PATCH 3/4] Fixed crash bc of CWE ALso made little adjustment to code. Fixed a severity calculator comparison --- .../executors/official/cisco_cybervision.py | 24 +++++++++++++------ .../utils/severity_utils.py | 4 ++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py b/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py index 9079d2db..a9357b8e 100644 --- a/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py +++ b/faraday_agent_dispatcher/static/executors/official/cisco_cybervision.py @@ -16,6 +16,13 @@ def log(msg, end="\n"): print(msg, file=sys.stderr, flush=True, end=end) +def parse_date(date_str): + try: + return datetime.datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ").timestamp() + except ValueError: + return "" + + def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): req_headers = {"accept": "application/json", "x-token-id": token} requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) @@ -37,6 +44,7 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): if preset["label"] == req_preset: presets_id[preset["label"]] = preset["id"] presets_queue.append(preset["id"]) + presets_id_inv = {v: k for k, v in presets_id.items()} # STAGE 2 - get all vulns per preset presets_vuln_collection = {} @@ -59,10 +67,10 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): resp = requests.get(req_test_url, headers=req_headers, timeout=20, verify=False) if "Service unavailable" in resp.content.decode("UTF-8"): if serv_c == 0: - log(f"Preset {_id} data is not ready, waiting...") + log(f"Preset {presets_id_inv[_id]} data is not ready, waiting...") serv_c += 1 else: - log(f"Preset {_id} data is ready!") + log(f"Preset {presets_id_inv[_id]} data is ready!") serv_c = 0 break if serv_c >= 60: @@ -73,7 +81,7 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): time.sleep(1) if serv_c >= 60: - log(f"Error: Preset {_id} took many time to refresh data") + log(f"Error: Preset {presets_id_inv[_id]} took many time to refresh data") continue step_c = 1 @@ -87,7 +95,7 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): log("Can't reach Cyber Vision: connection timed out") sys.exit(1) except ValueError as ve: - log(f"{str(ve)} at preset {_id}") + log(f"{str(ve)} at preset {presets_id_inv[_id]}") break if "error" in resp: log(f"API Error: {resp['error']}") @@ -100,6 +108,9 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): # STAGE 3 - processing vulns hosts = {} for pres_data in presets_id.items(): + if not pres_data[1] in presets_vuln_collection.keys(): + log(f"Error: No vulnerabilities loaded for {pres_data[0]} ({pres_data[1]})") + continue for vuln_pack in presets_vuln_collection[pres_data[1]]: for vuln in vuln_pack: if not vuln["device"]["label"] in hosts: @@ -127,10 +138,9 @@ def cybervision_report_composer(url, token, preset_list, asset_tags, vuln_tags): "data": vuln["fullDescription"], "status": "open", "cve": [x["cve"] for i, x in enumerate(vuln_pack) if x["title"] == vuln["title"]], - "run_date": datetime.datetime.strptime( - vuln["publishTime"], "%Y-%m-%dT%H:%M:%SZ" - ).timestamp(), + "run_date": parse_date(vuln["publishTime"]), "tags": vuln_tags, + "cwe": [], } ) data = {"hosts": [x[1] for x in hosts.items()]} diff --git a/faraday_agent_dispatcher/utils/severity_utils.py b/faraday_agent_dispatcher/utils/severity_utils.py index b6494ffd..28423014 100644 --- a/faraday_agent_dispatcher/utils/severity_utils.py +++ b/faraday_agent_dispatcher/utils/severity_utils.py @@ -21,6 +21,6 @@ def severity_from_score(score: float, max_score: float): return "medium" if max_score * 0.7 <= score < max_score * 0.9: return "high" - if max_score * 0.9 <= score < max_score: + if max_score * 0.9 <= score <= max_score: return "critical" - return "" + return "unclassified" From 601c574ecf91c8d597dd95daec71e6867f7e669d Mon Sep 17 00:00:00 2001 From: Diego Nadares Date: Wed, 26 Jun 2024 15:12:55 -0300 Subject: [PATCH 4/4] Ready for release 3.4.2 --- CHANGELOG/{current => 3.4.2}/223.md | 0 CHANGELOG/3.4.2/date.md | 1 + RELEASE.md | 4 ++++ faraday_agent_dispatcher/__init__.py | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) rename CHANGELOG/{current => 3.4.2}/223.md (100%) create mode 100644 CHANGELOG/3.4.2/date.md diff --git a/CHANGELOG/current/223.md b/CHANGELOG/3.4.2/223.md similarity index 100% rename from CHANGELOG/current/223.md rename to CHANGELOG/3.4.2/223.md diff --git a/CHANGELOG/3.4.2/date.md b/CHANGELOG/3.4.2/date.md new file mode 100644 index 00000000..055015ec --- /dev/null +++ b/CHANGELOG/3.4.2/date.md @@ -0,0 +1 @@ +Jun 26th, 2024 diff --git a/RELEASE.md b/RELEASE.md index 970ad8d4..7c9856d4 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,3 +1,7 @@ +3.4.2 [Jun 26th, 2024]: +--- + * [FIX] Implemented scan filtering by 'completed' status in Tenable SC Agent to prevent parsing errors. #223 + 3.4.1 [May 22th, 2024]: --- * [MOD] Plugins & Agent parameters types requirements updated. #220 diff --git a/faraday_agent_dispatcher/__init__.py b/faraday_agent_dispatcher/__init__.py index 90a69c3d..3f6349e5 100644 --- a/faraday_agent_dispatcher/__init__.py +++ b/faraday_agent_dispatcher/__init__.py @@ -20,4 +20,4 @@ __author__ = """Faraday Development Team""" __email__ = "devel@infobytesec.com" -__version__ = "3.4.1" +__version__ = "3.4.2"