Last active
January 15, 2025 14:42
-
-
Save dreizehnutters/e01d3a466617ef958a29fa4300036edc to your computer and use it in GitHub Desktop.
export nessus reports via CLI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
__version__ = "1.0" | |
__about__ = "nessus report exporter" | |
from time import sleep | |
from os import environ | |
import requests | |
from requests.packages.urllib3.exceptions import InsecureRequestWarning | |
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) | |
# DEFAULTS | |
AK = environ.get('NESSUS_AK') # CHANGE ME | |
SK = environ.get('NESSUS_SK') # CHANGE ME | |
TEMPLATE_ID = 1321 # CHANGE ME | |
CHUNK_SIZE = 1024 | |
NESSUS_INSTANCE = "localhost:8834" | |
OUT_DIR= "~/Desktop" | |
def trigger_download(scan_id, export_format='html'): | |
""" | |
return file_id | |
""" | |
burp0_url = f"https://{NESSUS_INSTANCE}/scans/{scan_id}/export" | |
burp0_headers = {"Content-Type": "application/json",\ | |
"X-Requested-With": "XMLHttpRequest",\ | |
"X-ApiKeys": f"accessKey={AK}; secretKey={SK}", "Connection": "close"} | |
burp0_json={"format": export_format, "template_id": TEMPLATE_ID} | |
resp = requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False, timeout=10) | |
if resp.status_code == 200: | |
try: | |
file_id = resp.json()['file'] | |
except Exception as err: | |
raise Exception(err) | |
else: | |
raise Exception(f"[!] {resp.text} (scan_id: {scan_id})") | |
return file_id | |
def download_report(scan_id, file_id, filename): | |
""" | |
return True if downloaded else False | |
""" | |
burp0_url = f"https://{NESSUS_INSTANCE}/scans/{scan_id}/export/{file_id}/download" | |
burp0_headers = {"Content-Type": "application/json",\ | |
"X-Requested-With": "XMLHttpRequest",\ | |
"X-ApiKeys": f"accessKey={AK}; secretKey={SK};",\ | |
"Connection": "close"} | |
resp = requests.get(burp0_url, headers=burp0_headers, verify=False, timeout=10) | |
if resp.status_code != 200: | |
return False | |
with open(f"{OUT_DIR}/{filename}", 'wb') as fd: | |
for chunk in resp.iter_content(CHUNK_SIZE): | |
fd.write(chunk) | |
return True | |
def select_scan_id(): | |
""" | |
return scan_id from user input | |
""" | |
choices = get_all_scan_ids() | |
for idx, name in enumerate(choices): | |
print(f"[{idx}] {name[0]}") | |
choice = -1 | |
while choice not in range(len(choices)): | |
try: | |
choice = int(input(f"[?] select a scan: 0-{len(choices)-1}: ")) | |
print("") | |
except Exception as err: | |
continue | |
if choice in range(len(choices)): | |
return (choices[choice][0], choices[choice][1]) | |
def get_all_scan_ids(): | |
""" | |
return list of scan ids that are ready to be exported (not in trash and completed) | |
""" | |
burp0_url = f"https://{NESSUS_INSTANCE}/scans" | |
burp0_headers = {"Content-Type": "application/json", | |
"X-Requested-With": "XMLHttpRequest", | |
"X-ApiKeys": f"accessKey={AK}; secretKey={SK};", | |
"Connection": "close"} | |
resp = requests.get(burp0_url, headers=burp0_headers, verify=False, timeout=10) | |
if resp.json()['scans'] is None: | |
exit("[!] no scans is ready to be exported") | |
trash_folder_id = [x['id'] for x in resp.json()['folders'] if x['type'] == 'trash'][-1] | |
scan_ids = [(x['name'], x['id']) for x in resp.json()['scans'] if x['status'] in ('completed', 'canceled', 'imported') and x['folder_id'] != trash_folder_id] | |
if len(scan_ids) > 0: | |
return scan_ids | |
exit("[!] no scans is ready to be exported") | |
def do_download(scan_id, file_id, filename): | |
""" | |
download file if status is ready | |
""" | |
code = False | |
n_sek = 0 | |
while code is not True: | |
print(f"\t[z] the report is being generated since {n_sek:02d} sec", end='\r') | |
code = download_report(scan_id, file_id, filename) | |
sleep(1) | |
n_sek+=1 | |
print(f"{' '*80}",end='\r') | |
if __name__ == '__main__': | |
option = input("[?] export all scans (y/n): ") | |
print("") | |
if (option.lower() == 'y') or (option.lower() == 'j'): | |
scan_ids = get_all_scan_ids() | |
else: | |
scan_ids = [select_scan_id()] | |
for scan_tuple in scan_ids: | |
print(f"[*] downloading report: '{scan_tuple[0]}'") | |
scan_id = scan_tuple[1] | |
for export_format in ['html', 'nessus']: | |
print(f"\t[.] getting the .{export_format} version") | |
try: | |
file_id = trigger_download(scan_id, export_format) | |
except Exception as err: | |
print(err) | |
continue | |
do_download(scan_id, file_id, filename=scan_tuple[0].replace(' ','_').replace('\\','_').replace('/','_')+f'.{export_format}') | |
print(f"{'-'*10}") | |
print("[$] done!") |
hey there,
I tried using your script but failed doing so.
all the commands from your script are working fine, if executed one by one. but that is not what i want. ;)
do you have any idea, why i receive these following errors?
any input is highly appreciated
Traceback (most recent call last):
File "/Users/xyz/Downloads/e01d3a466617ef958a29fa4300036edc-c595390ce15bbbae8fb8f50551e82edc186c326a/nessus_report_exporter.py", line 117, in <module>
scan_ids = get_all_scan_ids()
^^^^^^^^^^^^^^^^^^
File "/Users/xyz/Downloads/e01d3a466617ef958a29fa4300036edc-c595390ce15bbbae8fb8f50551e82edc186c326a/nessus_report_exporter.py", line 89, in get_all_scan_ids
if resp.json()['scans'] is None:
~~~~~~~~~~~^^^^^^^^^
KeyError: 'scans'
Inspect why the resp.json()
does not contain the key scans
. I dont know if nessus changed their API and cannot provide further support.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nessus Report Exporter
This Python script automates the process of exporting Nessus scan reports in HTML and Nessus formats. It leverages the Nessus API to trigger report generation and download the resulting files. The script prompts users to select specific scans or export all available ones. It also includes error handling and retry mechanisms for downloading reports. Designed for ease of use and flexibility in managing Nessus scan data.
Features
Usage
NESSUS_AK
andNESSUS_SK
are set, corresponding to the Nessus access key and secret key.Requirements
pip install requests
)Configuration
Ensure that the following environment variables are set:
NESSUS_AK
: Nessus access keyNESSUS_SK
: Nessus secret keyAdditionally, you may customize the following default settings in the script:
TEMPLATE_ID
: Nessus template ID for report generationCHUNK_SIZE
: Size of chunks for downloading filesOUT_DIR
: Output directory for saving exported reportsExample
License
This project is licensed under the MIT License - see the LICENSE file for details.