Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Diego Nadares committed Jun 26, 2024
2 parents fb9ae7c + 601c574 commit 43f0316
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG/3.4.2/223.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[FIX] Implemented scan filtering by 'completed' status in Tenable SC Agent to prevent parsing errors. #223
1 change: 1 addition & 0 deletions CHANGELOG/3.4.2/date.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Jun 26th, 2024
4 changes: 4 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion faraday_agent_dispatcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@

__author__ = """Faraday Development Team"""
__email__ = "[email protected]"
__version__ = "3.4.1"
__version__ = "3.4.2"
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,34 @@
import os
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"):
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)
presets_queue = []
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:
Expand All @@ -35,26 +43,58 @@ 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 = {}
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 {presets_id_inv[_id]} data is not ready, waiting...")
serv_c += 1
else:
log(f"Preset {presets_id_inv[_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 {presets_id_inv[_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")
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']}")
Expand All @@ -67,6 +107,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:
Expand Down Expand Up @@ -94,10 +137,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()]}
Expand Down
17 changes: 15 additions & 2 deletions faraday_agent_dispatcher/static/executors/official/tenablesc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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]


Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions faraday_agent_dispatcher/utils/severity_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,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"

0 comments on commit 43f0316

Please sign in to comment.