class OpenVASTool(): def __init__(self, connection=OPENVAS_CONN, username="******", password="******"): self.gmp = Gmp(connection=connection) self.username=username self.password=password try: self.gmp.authenticate(self.username, self.password) except GvmError as e: print('An error occurred', e, file=sys.stderr) def push_command(self, command, params): """ :param command: 执行的命令, 同openvasmd的cmd :param params: 命令中传递的参数 :return: 返回响应的内容 """ with self.gmp: if not params: responce = self.gmp.__getattribute__(command)() else: responce = self.gmp.__getattribute__(command)(**params) result = json.loads(json.dumps(xmltodict.parse(responce))) try: return result[command+"_response"] except: return result
def connect_gvm(username, password): """connect via TLS and create a target for gvm this assumes you have connected to gvmd through local ssh forward, if not configure hostname to match hostname or ip address and change the port if needed, this will use the default port 9390""" transform = EtreeCheckCommandTransform() connection = TLSConnection() connection.hostname = '127.0.0.1' connection.port = '9390' gmp = Gmp(connection=connection, transform=transform) gmp.authenticate(username, password) return gmp
class OpenvasRemote: def __init__(self, path, connection, transform): self.path = path self.connection = connection self.gmp = Gmp(connection=connection, transform=transform) def create_task(self, task_name, config_id, target_id, scanner_id, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.create_task( task_name, config_id, target_id, scanner_id) pretty_print(response) id = response.xpath('@id') return id[0] except GvmError as e: print(e) return 'bad' def create_target(self, target_name, targets_list, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.create_target( target_name, hosts=targets_list,alive_test=AliveTest.CONSIDER_ALIVE) pretty_print(response) if(response.xpath("@status_text")[0] == 'Target exists already'): with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_targets( filter="name={0}".format(target_name)) target_id = response.xpath('target/@id')[0] return target_id else: id = response.xpath('@id')[0] return id except GvmError as e: print(e) return 'bad' #this also delete all the reports def delete_all_tasks(self, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_tasks() for task in response.xpath('task'): task_id = task.xpath('@id')[0] response = self.gmp.delete_task(task_id) pretty_print(response) result = {'status': 'good'} return result except GvmError as e: print(e) result = {'status': 'bad'} return result def delete_all_targets(self, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_targets() for target in response.xpath('target'): target_id = target.xpath('@id')[0] response = self.gmp.delete_target(target_id) pretty_print(response) result = {'status': 'good'} return result except GvmError as e: print(e) result = {'status': 'bad'} return result @staticmethod def get_full_and_fast_config_id(): return 'daba56c8-73ec-11df-a475-002264764cea' @staticmethod def get_default_openvas_scanner_id(): return '08b69003-5fc2-4037-a479-93b440211c73' def get_report(self, id, target_list, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_report(id) running_status = response.xpath( 'report/report/scan_run_status/text()')[0] if(running_status == 'Done'): print(response.xpath('report/@id')[0]) report = {} hosts = [] for IP_address in target_list: host = {} host['ip_address'] = IP_address host['results'] = [] host['results_count'] = 0 hosts.append(host) for report_result in response.xpath('report/report/results/result'): print( '=======================================================================') result = {} result['report_id'] = report_result.xpath('@id')[0] result['description'] = report_result.xpath( 'description/text()')[0] result['name'] = report_result.xpath('name/text()')[0] result['port'] = report_result.xpath('port/text()')[0] result['nvt_bid'] = report_result.xpath( 'nvt/bid/text()')[0] result['nvt_cve'] = report_result.xpath( 'nvt/cve/text()')[0] result['nvt_cvss_base'] = report_result.xpath( 'nvt/cvss_base/text()')[0] result['nvt_family'] = report_result.xpath( 'nvt/family/text()')[0] result['nvt_oid'] = report_result.xpath('nvt/@oid')[0] result['nvt_tags'] = report_result.xpath( 'nvt/tags/text()')[0] result['nvt_type'] = report_result.xpath( 'nvt/type/text()')[0] result['nvt_xref'] = report_result.xpath( 'nvt/xref/text()')[0] result['quality_of_detection_value'] = report_result.xpath( 'qod/value/text()')[0] result['quality_of_detection_type'] = report_result.xpath( 'qod/type/text()')[0] result['threat'] = report_result.xpath( 'threat/text()')[0] result['severity'] = report_result.xpath( 'severity/text()')[0] for host in hosts: if(host['ip_address'] == report_result.xpath('host/text()')[0]): host['results'].append(result) report['hosts'] = hosts report['ip_address_count'] = len(target_list) report['status'] = 'received' print(json.dumps(report)) return report else: report = {'status': 'running'} return report except GvmError as e: no_report = {'status': 'bad'} print(e) return no_report def get_reports(self, id, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_reports() pretty_print(response) except GvmError as e: print(e) def get_full_report(self, id, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_report(id) pretty_print(response) except GvmError as e: print(e) def get_targets(self, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_targets() pretty_print(response) for target in response.xpath('target'): pretty_print(target.xpath('@id')) except GvmError as e: print(e) def get_task(self, id, username, password): try: with self.gmp: self.gmp.authenticate(username, password) reponse = self.gmp.get_task(id) pretty_print(reponse) except GvmError as e: print(e) def get_tasks(self, username, password): try: with self.gmp: self.gmp.authenticate(username, password) response = self.gmp.get_tasks() for task in response.xpath('task'): pretty_print(task.xpath('@id')) except GvmError as e: print(e) def scan_target(self, task_name, target_name, targets_list, username, password): try: target_id = self.create_target( target_name, targets_list, username, password) if(target_id == 'bad'): return ('bad','bad','bad','bad') task_id = self.create_task(task_name, self.get_full_and_fast_config_id(), target_id, self.get_default_openvas_scanner_id(), username, password) if(task_id == 'bad'): return ('bad','bad','bad','bad') task_tuple = self.start_task(task_id, username, password) if(task_tuple[0] =='bad'): return ('bad','bad','bad','bad') report_id = task_tuple[0] status = task_tuple[1] return (target_id,task_id,report_id, status) except GvmError as e: print(e) return ('bad','bad','bad','bad') def start_task(self, id, username, password): try: with self.gmp: print(id) self.gmp.authenticate(username, password) reponse = self.gmp.start_task(id) report_id = reponse.xpath('report_id/text()') status = 'start' if(len(report_id) == 0): return ('bad','bad') return (report_id[0], status) except GvmError as e: print(e) return ('bad', 'bad') def test1(self, task_name, target_name,ip_address_list,ip_address_count_per_report,username,password): run_task_name = task_name + '_' + str(uuid4()) total_ip_addresses = len(ip_address_list) remainder = total_ip_addresses % ip_address_count_per_report chopped_ip_addresses = total_ip_addresses - remainder count = 0 left_index = 0 right_index = ip_address_count_per_report for batch in range(chopped_ip_addresses//ip_address_count_per_report): slice_object = slice(left_index,right_index) sub_ip_address_list = ip_address_list[slice_object] left_index = left_index + ip_address_count_per_report right_index = right_index + ip_address_count_per_report run_task_name_id = run_task_name + '_batch_number_' + str(batch) run_target_name_id = run_task_name_id + '_target_' + target_name count = count + 1 report_tuple = self.scan_target(run_task_name_id,run_target_name_id, sub_ip_address_list, username, password) if( remainder > 0): slice_object = slice(-remainder,total_ip_addresses) sub_ip_address_list = ip_address_list[slice_object] run_task_name_id = run_task_name + '_batch_number_' + str(count) run_target_name_id = run_task_name_id + '_target_' + target_name report_tuple = self.scan_target(run_task_name_id,run_target_name_id, sub_ip_address_list, username, password)
class OpenVASScanner(Scanner): name = 'OpenVAS' def __init__(self): connection = UnixSocketConnection(path=config['OPENVAS_SOCKET']) transform = EtreeTransform() self.gmp = Gmp(connection, transform=transform) self.storage_service = StorageService() # Login try: self.gmp.authenticate(config['OPENVAS_USERNAME'], config['OPENVAS_PASSWORD']) except: print(f'[{self.name}] Not able to connect to the {self.name}: ', sys.exc_info()) return # Getting Version # version = self.gmp.get_version() # pretty_print(version) def start(self, scan_name, target): print(f'[{self.name}] Starting Scan for Target: {target}') try: return self.scan(scan_name, target) except: print(f'[{self.name}] Not able to connect to the {self.name}: ', sys.exc_info()) return False def scan(self, scan_name, target): print(f'[{self.name}] Scan Name: {scan_name}') address = self._get_address(target) # Creating Target target_response = self.gmp.create_target(name=scan_name, hosts=[address]) # print('target_response') pretty_print(target_response) target_id = target_response.get('id') if not target_id: print(f'[{self.name}] could not able to create target: ', target_response.get('status_text')) return False # target_id = '69ca3c65-af09-48b8-bb3a-59e2e6cccb96' print(f'[{self.name}] Target Created: {target_id}') scan_data = self.storage_service.get_by_name(scan_name) if not scan_data: scan_data = { 'scan_name': scan_name, 'scan_id': '', 'target': target, 'status': '' } self.storage_service.add(scan_data) scan_data['OPENVAS'] = { 'openvas_id': target_id, 'target_id': target_id, 'scan_status': { 'status': 'INPROGRESS' } } self.storage_service.update_by_name(scan_name, scan_data) time.sleep(4) self._create_report(scan_name) return scan_data def _create_report(self, scan_name): scan_data = self.storage_service.get_by_name(scan_name) openvas_id = scan_data['OPENVAS']['openvas_id'] scan_config_id = config['SCAN_CONFIG_ID'] scanner_id = config['SCANNER_ID'] report_format_id = config['REPORT_FORMAT_ID'] # Creating Task task_response = self.gmp.create_task(name=scan_name, config_id=scan_config_id, target_id=openvas_id, scanner_id=scanner_id) # print('task_response') # pretty_print(task_response) task_id = task_response.get('id') # Starting Task start_task_response = self.gmp.start_task(task_id) # print('start_task_response') # pretty_print(start_task_response) report_id = start_task_response[0].text scan_data['OPENVAS']['report_id'] = report_id scan_data['OPENVAS']['report_format_id'] = report_format_id scan_data['OPENVAS']['scan_config_id'] = scan_config_id scan_data['OPENVAS']['scanner_id'] = scanner_id scan_data['OPENVAS']['task_id'] = task_id print( f'[{self.name}] Created Report: {report_id} with Task: {task_id}') self.storage_service.update_by_name(scan_name, scan_data) return scan_data def get_scan_status(self, scan_name, scan_status_list=[]): if not self.is_valid_scan(scan_name): return False scan_data = self.storage_service.get_by_name(scan_name) scan_status = scan_data.get('OPENVAS', {}).get('scan_status', {}) openvas_id = scan_data.get('OPENVAS', {})['openvas_id'] target = scan_data['target'] print(f'[{self.name}] Getting Scan Status for Target: {target}') print(f'[{self.name}] Scan Name: {scan_name}') print(f'[{self.name}] Scan Id: {openvas_id}') try: scan_info = self.get_scan_results(scan_name) # print('scan_info') # pretty_print(scan_info) except: print(f'[{self.name}] Could not get the scan {openvas_id}: ', sys.exc_info()) return False scan_status['status'] = 'COMPLETE' if scan_info else 'INPROGRESS' scan_data['OPENVAS']['scan_status'] = scan_status self.storage_service.update_by_name(scan_name, scan_data) if scan_status['status'] is 'COMPLETE': print(f'[{self.name}] Scan {scan_name} Completed') scan_status_list.append({ 'scanner': self.name, 'status': scan_status['status'] }) return scan_status_list def get_scan_results(self, scan_name, scan_results={}): if not self.is_valid_scan(scan_name): return False scan_data = self.storage_service.get_by_name(scan_name) # if scan_data.get('OPENVAS', {}).get('scan_status').get('status', None) != 'COMPLETE': # print(f'[{self.name}] Scan is in progress') # return False openvas_id = scan_data.get('OPENVAS', {})['openvas_id'] report_id = scan_data.get('OPENVAS', {})['report_id'] report_format_id = scan_data.get('OPENVAS', {})['report_format_id'] # report_id = '79bf4984-9a0e-435a-807b-9dd530fb532f' try: report_response = self.gmp.get_report( report_id=report_id, report_format_id=report_format_id) # print('report_response') # pretty_print(report_response) except: print(f'[{self.name}] Could not get the scan {openvas_id}: ', sys.exc_info()) return False self._process_results(report_response, scan_results) return scan_results def _process_results(self, report_response, scan_results={}): report_response_str = ElementTree.tostring(report_response, encoding='unicode') report_response_dict = xmltodict.parse(report_response_str) report_results = report_response_dict.get( 'get_reports_response', {}).get('report', {}).get('report', {}).get('results', {}).get('result', []) # print(json.dumps(report_results, indent=2)) # print('report_results', report_results) for vuln in report_results: name = vuln.get('name') print('name: ', name) if scan_results.get(name): print('--- Duplicate name: ', name) continue nvt = vuln.get('nvt', {}) scan_result = {} scan_result['name'] = name scan_result['severity'] = float(nvt.get('cvss_base', 0)) scan_result['risk'] = vuln.get('threat') scan_result['cve_id'] = nvt.get( 'cve', 'N/A') if nvt.get('cve') != 'NOCVE' else 'N/A' scan_result['description'] = vuln.get('description') scan_result['solution'] = 'N/A' scan_result['reported_by'] = 'OpenVAS' scan_results[name] = scan_result return scan_results def is_valid_scan(self, scan_name): scan_data = self.storage_service.get_by_name(scan_name) if not scan_data: print(f'[{self.name}] Invalid Scan Name: {scan_name}') return False if not scan_data.get('OPENVAS'): print(f'[{self.name}] No Scan Details found for {scan_name}') return False return True def pause(self, scan_name): if not self.is_valid_scan(scan_name): return False # scan = self.storage_service.get_by_name(scan_name) # nexpose_id = scan['nexpose_id'] # response = self.nexpose.set_scan_status(nexpose_id, 'pause') # pprint(response) # return response def resume(self, scan_name): if not self.is_valid_scan(scan_name): return False # scan = self.storage_service.get_by_name(scan_name) # nexpose_id = scan['nexpose_id'] # response = self.nexpose.set_scan_status(nexpose_id, 'resume') # pprint(response) # return response def stop(self, scan_name): if not self.is_valid_scan(scan_name): return False # scan = self.storage_service.get_by_name(scan_name) # nexpose_id = scan['nexpose_id'] # response = self.nexpose.set_scan_status(nexpose_id, 'stop') # pprint(response) # return response def remove(self, scan_name): if not self.is_valid_scan(scan_name): return False # scan = self.storage_service.get_by_name(scan_name) # nexpose_id = scan['nexpose_id'] # response = self.nexpose.set_scan_status(nexpose_id, 'remove') # pprint(response) # return response def list_scans(self): pass
scan_results[name] = scan_result return scan_results connection = UnixSocketConnection(path='/var/run/openvasmd.sock') transform = EtreeTransform() gmp = Gmp(connection, transform=transform) # Retrieve GMP version supported by the remote daemon version = gmp.get_version() # Prints the XML in beautiful form pretty_print(version) # Login gmp.authenticate('admin', 'admin') name = 'name-5' ip_address = 'scanme.nmap.org' # ip_address = 'webscantest.com' # ip_address = 'slack.com' # response = gmp.create_target(name=name, hosts=[ip_address]) # pretty_print(response) # target_id = response.get('id') # print('target_id: ', target_id) # target_id = 'b7b3b26d-5e19-482c-a1b5-d5c46b89edaa' target_id = '69ca3c65-af09-48b8-bb3a-59e2e6cccb96' scan_config_id = 'daba56c8-73ec-11df-a475-002264764cea' scanner_id = '08b69003-5fc2-4037-a479-93b440211c73'
def main(): parser = create_parser(description=HELP_TEXT, logfilename='gvm-cli.log') parser.add_argument('-X', '--xml', help='XML request to send') parser.add_argument('-r', '--raw', help='Return raw XML', action='store_true', default=False) parser.add_argument('infile', nargs='?', type=open, default=sys.stdin) args = parser.parse_args() # If timeout value is -1, then the socket has no timeout for this session if args.timeout == -1: args.timeout = None xml = '' if args.xml is not None: xml = args.xml else: # If this returns False, then some data are in sys.stdin if not args.infile.isatty(): try: xml = args.infile.read() except (EOFError, BlockingIOError) as e: print(e) # If no command was given, program asks for one if len(xml) == 0: xml = input() # Ask for password if none are given if args.gmp_username and not args.gmp_password: args.gmp_password = getpass.getpass('Enter password for ' + args.gmp_username + ': ') connection = create_connection(**vars(args)) if args.raw: transform = None else: transform = CheckCommandTransform() gvm = Gmp(connection, transform=transform) if args.gmp_username: gvm.authenticate(args.gmp_username, args.gmp_password) try: result = gvm.send_command(xml) print(result) except Exception as e: # pylint: disable=broad-except print(e) sys.exit(1) gvm.disconnect() sys.exit(0)
class OpenVASScanner(Scanner): name = 'OpenVAS' def __init__(self): connection = TLSConnection(hostname=config['HOST_NAME'], port=config['PORT'], certfile=None, cafile=None, keyfile=None, password=None, timeout=25) transform = EtreeTransform() self.gmp = Gmp(connection, transform=transform) self.storage_service = StorageService() # Login try: self.gmp.authenticate(config['OPENVAS_USERNAME'], config['OPENVAS_PASSWORD']) except: print(f'[{self.name}] Not able to connect to the {self.name}: ', sys.exc_info()) return def start(self, scan_name, target): print(f'[{self.name}] Starting Scan for Target: {target}') try: return self.scan(scan_name, target) except: print(f'[{self.name}] Not able to connect to the {self.name}: ', sys.exc_info()) return False def scan(self, scan_name, target): print(f'[{self.name}] Scan Name: {scan_name}') address = self._get_address(target) # Creating Target target_response = self.gmp.create_target( name=scan_name, hosts=[address], port_list_id='33d0cd82-57c6-11e1-8ed1-406186ea4fc5') # print('target_response') #pretty_print(target_response) target_id = target_response.get('id') if not target_id: print(f'[{self.name}] could not able to create target: ', target_response.get('status_text')) return False # target_id = '69ca3c65-af09-48b8-bb3a-59e2e6cccb96' print(f'[{self.name}] Target Created: {target_id}') scan_data = self.storage_service.get_by_name(scan_name) if not scan_data: scan_data = { 'scan_name': scan_name, 'scan_id': '', 'target': target, 'status': '' } self.storage_service.add(scan_data) scan_data['OPENVAS'] = { 'openvas_id': target_id, 'target_id': target_id, 'scan_status': { 'status': 'INPROGRESS' } } self.storage_service.update_by_name(scan_name, scan_data) time.sleep(4) self._create_task(scan_name) return scan_data def _create_task(self, scan_name): scan_data = self.storage_service.get_by_name(scan_name) openvas_id = scan_data['OPENVAS']['openvas_id'] scan_config_id = config['SCAN_CONFIG_ID'] scanner_id = config['SCANNER_ID'] report_format_id = config['REPORT_FORMAT_ID'] # Creating Task task_response = self.gmp.create_task(name=scan_name, config_id=scan_config_id, target_id=openvas_id, scanner_id=scanner_id) # print('task_response') # pretty_print(task_response) task_id = task_response.get('id') print(f'[{self.name}] Created Task: with : {task_id}') # Starting Task start_task_response = self.gmp.start_task(task_id) # print('start_task_response') # pretty_print(start_task_response) report_id = start_task_response[0].text scan_data['OPENVAS']['report_id'] = report_id scan_data['OPENVAS']['report_format_id'] = report_format_id scan_data['OPENVAS']['scan_config_id'] = scan_config_id scan_data['OPENVAS']['scanner_id'] = scanner_id scan_data['OPENVAS']['task_id'] = task_id self.storage_service.update_by_name(scan_name, scan_data) return scan_data def get_scan_status(self, scan_name, scan_status_list=[]): if not self.is_valid_scan(scan_name): return False scan_data = self.storage_service.get_by_name(scan_name) scan_status = scan_data.get('OPENVAS', {}).get('scan_status', {}) openvas_id = scan_data.get('OPENVAS', {})['openvas_id'] target = scan_data['target'] task_id = scan_data.get('OPENVAS', {})['task_id'] print(f'[{self.name}] Getting Scan Status for Target: {target}') print(f'[{self.name}] Scan Name: {scan_name}') print(f'[{self.name}] Scan Id: {openvas_id}') try: scan_info = self.gmp.get_task(task_id) status = scan_info.xpath('task/status/text()') progress = scan_info.xpath('task/progress/text()') except: print(f'[{self.name}] Could not get the scan {openvas_id}: ', sys.exc_info()) return False scan_status['status'] = 'COMPLETE' if status[ 0] == 'Done' else 'INPROGRESS' if status[ 0] == 'Running' else status[0] scan_status['progress'] = progress[0] scan_data['OPENVAS']['scan_status'] = scan_status self.storage_service.update_by_name(scan_name, scan_data) if scan_status['status'] is 'COMPLETE': print(f'[{self.name}] Scan {scan_name} Completed') scan_status_list.append({ 'scanner': self.name, 'status': f'{scan_status["status"]} {progress[0]}%' }) return scan_status_list def get_scan_results(self, scan_name, oscan_results={}): if not self.is_valid_scan(scan_name): return False scan_data = self.storage_service.get_by_name(scan_name) # if scan_data.get('OPENVAS', {}).get('scan_status').get('status', None) != 'COMPLETE': # print(f'[{self.name}] Scan is in progress') # return False openvas_id = scan_data.get('OPENVAS', {})['openvas_id'] report_id = scan_data.get('OPENVAS', {})['report_id'] report_format_id = scan_data.get('OPENVAS', {})['report_format_id'] try: report_response = self.gmp.get_report( report_id=report_id, report_format_id=report_format_id) # print('report_response') #pretty_print(report_response) except: print(f'[{self.name}] Could not get the scan {openvas_id}: ', sys.exc_info()) return False self._process_results(report_response, oscan_results) return oscan_results def _process_results(self, report_response, oscan_results={}): report_response_str = ElementTree.tostring(report_response, encoding='unicode') report_response_dict = xmltodict.parse(report_response_str) report_results = report_response_dict.get( 'get_reports_response', {}).get('report', {}).get('report', {}).get('results', {}).get('result', []) # print(json.dumps(report_results, indent=2)) # print('report_results', report_results) for vuln in report_results: name = vuln.get('name') #print('name: ', name) if oscan_results.get(name): # print('--- Duplicate name: ', name) continue nvt = vuln.get('nvt', {}) scan_result = {} scan_result['name'] = name scan_result['severity'] = float(nvt.get('cvss_base', 0)) scan_result['risk'] = vuln.get('threat') scan_result['cve_id'] = nvt.get( 'cve', 'N/A') if nvt.get('cve') != 'NOCVE' else 'N/A' scan_result['description'] = vuln.get('description') scan_result['solution'] = 'N/A' scan_result['reported_by'] = 'OpenVAS' oscan_results[name] = scan_result return oscan_results def is_valid_scan(self, scan_name): scan_data = self.storage_service.get_by_name(scan_name) if not scan_data: print(f'[{self.name}] Invalid Scan Name: {scan_name}') return False if not scan_data.get('OPENVAS'): print(f'[{self.name}] No Scan Details found for {scan_name}') return False return True def pause(self, scan_name): if not self.is_valid_scan(scan_name): return False scan = self.storage_service.get_by_name(scan_name) task_id = scan['OPENVAS']['task_id'] response = self.gmp.stop_task(task_id) #GMP does not support pause print(f'[{self.name}] scan paused ') return response def resume(self, scan_name): if not self.is_valid_scan(scan_name): return False scan = self.storage_service.get_by_name(scan_name) task_id = scan['OPENVAS']['task_id'] response = self.gmp.resume_task(task_id) print(f'[{self.name}] scan resumed ') return response def stop(self, scan_name): if not self.is_valid_scan(scan_name): return False scan = self.storage_service.get_by_name(scan_name) task_id = scan['OPENVAS']['task_id'] response = self.gmp.stop_task(task_id) print(f'[{self.name}] scan stopped ') return response def remove(self, scan_name): if not self.is_valid_scan(scan_name): return False scan = self.storage_service.get_by_name(scan_name) task_id = scan['OPENVAS']['task_id'] response = self.gmp.delete_task(task_id, ultimate=False) print(f'[{self.name}] scan removed ') return response def list_scans(self): self.tasks = self.gmp.get_tasks() task_names = self.tasks.xpath('task/name/text()') print("Available scan names from openvas") pretty_print(task_names) return task_names def start_sp(self, scan_name): if not self.is_valid_scan(scan_name): return False scan_data = self.storage_service.get_by_name(scan_name) print(f'[{self.name}] Starting Scan: {scan_name}') task_id = scan_data['OPENVAS']['task_id'] start_task_response = self.gmp.start_task(task_id) print(f'[{self.name}] Task started') report_id = start_task_response[0].text scan_data['OPENVAS'] = { 'report_id': report_id, 'scan_status': { 'status': 'INPROGRESS' } } self.storage_service.update_by_name(scan_name, scan_data)
class GVM_client: def __init__(self, password, socket_path='/var/run/gvmd.sock', user='******', timeout=10, loglevel=logging.ERROR): logging.basicConfig(level=loglevel) self.connection_errors = 0 self.container_tasks = {} self.password = password self.user = user self.socketconnection = UnixSocketConnection(path=socket_path, timeout=timeout) self.connection = DebugConnection(self.socketconnection) self.transform = EtreeCheckCommandTransform() self.gmp = Gmp(connection=self.connection, transform=self.transform) self.connect() def authenticate(self): try: self.gmp.authenticate(self.user, self.password) except Exception as ex: logging.error('Unable to authenticate: {}'.format(ex)) def connect(self): try: self.authenticate() return self.gmp._connected except Exception as ex: self.connection_errors += 1 logging.error('Can\'t connect to service: {}'.format(ex)) return False def get_xmls(self, directory): results = [] for file_name in os.listdir(directory): if file_name.lower().endswith(".xml"): file_path = os.path.join(directory, file_name) logging.info('Reading file {}'.format(file_path)) with io.open(file_path, 'r', encoding='utf-8') as file: results.append(''.join(file.readlines())) return results def wait_connection(self, connection_tries=10, secs_before_attempt=5): while not self.connect(): if self.connection_errors <= connection_tries: sleep(secs_before_attempt) else: raise Exception('Can\'t connect to gvmd in {} sec'.format(connection_tries*secs_before_attempt)) def wait_sync(self, interval=15): logging.info('Waiting for NVTs/Feeds sync to complete') while True: if self.connect(): families = self.gmp.get_nvt_families().xpath('families/family') feeds = self.gmp.get_feeds().xpath('feed/currently_syncing') if len(families) != 0 and len(feeds) == 0: break else: sleep(interval) def import_configs(self, directory): for config in self.get_xmls(directory): if self.connect(): try: response = self.gmp.import_config(config) if response.attrib['status'] == '201': config_root = ET.fromstring(config) config_name = config_root.findtext('config/name') logging.info('Importing config OK: {}'.format(config_name)) except Exception as ex: logging.error('Importing config error: {}'.format(ex)) def create_target(self, target:Target): if self.connect(): try: response = self.gmp.create_target( name=target.name, make_unique=target.make_unique, hosts=target.hosts, exclude_hosts=target.exclude_hosts, comment=target.comment, alive_tests=target.alive_tests, reverse_lookup_only=target.reverse_lookup_only, reverse_lookup_unify=target.reverse_lookup_unify, port_range=target.port_range, port_list_id=target.port_list_id, asset_hosts_filter=target.asset_hosts_filter, ssh_credential_id=target.ssh_credential_id, ssh_credential_port=target.ssh_credential_port, smb_credential_id=target.smb_credential_id, snmp_credential_id=target.snmp_credential_id, esxi_credential_id=target.esxi_credential_id) if response.attrib['status'] == '201': logging.info('Importing target OK: {}'.format(target.name)) except Exception as ex: logging.error('Importing target error: {}'.format(ex)) def import_targets(self, directory:str): ''' directory: path to exported targets in XML ''' for target_config in self.get_xmls(directory): if self.connect(): try: target = Target(target_config) self.create_target(target) except Exception as ex: logging.error('Importing target error: {}'.format(ex)) def create_task(self, task:Task): if self.connect(): try: response = self.gmp.create_task( name=task.name, target_id=task.target_id, scanner_id=task.scanner_id, config_id=task.config_id, comment=task.comment, alterable=task.alterable, alert_ids=task.alert_ids, hosts_ordering=task.hosts_ordering, schedule_id=task.schedule_id, schedule_periods=task.schedule_periods, observers=task.observers) if response.attrib['status'] == '201': logging.info('Importing task OK: {}'.format(task.name)) except Exception as ex: logging.error('Importing task error: {}'.format(ex)) def create_override(self, override:Override): if self.connect(): try: response = self.gmp.create_override( text=override.text, nvt_oid=override.nvt_oid, seconds_active=override.seconds_active, comment=override.comment, hosts=override.hosts, port=override.port, result_id=override.result_id, severity=override.severity, new_severity=override.new_severity, task_id=override.task_id, threat=override.threat, new_threat=override.new_threat) if response.attrib['status'] == '201': logging.info('Creating override OK: {}'.format(override.text)) except Exception as ex: logging.error('Creating override error: {}'.format(ex)) def import_overrides(self, directory:str): for override_xml in self.get_xmls(directory): if self.connect(): try: override = Override(override_xml) self.create_override(override) except Exception as ex: logging.error('Importing override error: {}'.format(ex)) def import_tasks(self, directory:str): for task_config in self.get_xmls(directory): if self.connect(): try: task = Task(task_config) task.target_id = None for target in self.gmp.get_targets().xpath('target'): target_name = target.find('name').text if target_name == task.name: task.target_id = target.attrib['id'] logging.log(logging.DEBUG, 'Importing task - target_id: {}'.format(task.target_id)) if task.target_id == None: logging.log(logging.DEBUG, 'Importing task - {}. No target_id found'.format(task.name)) continue task.config_id = None for config in self.gmp.get_configs().xpath('config'): if config.find('name').text == task.config['name']: task.config_id = config.attrib['id'] logging.log(logging.DEBUG, 'Importing task - config_id: {}'.format(task.config_id)) break self.create_task(task) except Exception as ex: logging.error('Importing task error: {}'.format(ex)) def import_reports(self, directory): for report_xml in self.get_xmls(directory): if self.connect(): try: report = Report(report_xml) if report.task_name not in self.container_tasks.keys(): response = self.gmp.import_report(report_xml, task_name=report.task_name, task_comment=report.task_comment) if response.attrib['status'] == '201': logging.info('Importing report OK: {}'.format(report.task_name)) tasks = self.gmp.get_tasks().xpath('task') for task in tasks: if task.find('name').text == report.task_name and self._is_container_task(task): logging.log(logging.DEBUG, 'Found container task: {}[{}]'.format(report.task_name, task.attrib['id'])) self.container_tasks[report.task_name] = task.attrib['id'] break else: response = self.gmp.import_report(report_xml, task_id=self.container_tasks[report.task_name]) if response.attrib['status'] == '201': logging.info('Importing report OK: {}'.format(report.task_name)) except Exception as ex: logging.error('Importing report error: {}'.format(ex)) def get_task(self, task_id): if self.connect(): try: response = self.gmp.get_task(task_id=task_id) if response.attrib['status'] == '200': task = Task(response.find('task')) logging.debug('Getting task OK: {} [{}]'.format(task.name, task_id)) return task else: return None except Exception as ex: logging.error('Getting task error: {}'.format(ex)) def get_task_status(self, task_id): if self.connect(): try: response = self.gmp.get_task(task_id=task_id) if response.attrib['status'] == '200': task_status = response.find('task/status').text logging.info('Getting task status OK: {} [{}]'.format(task_id, task_status)) return task_status else: return None except Exception as ex: logging.error('Getting task status error: {}'.format(ex)) def run_task(self, task_id:str): if self.connect(): try: response = self.gmp.start_task(task_id=task_id) if response.attrib['status'] == '202': logging.info('Running task OK: {}'.format(task_id)) return True else: return False except Exception as ex: logging.error('Running task error: {}'.format(ex)) return False def _is_container_task(self, task): return task.find('target').attrib['id'] == '' def get_targets(self): if self.connect(): try: targets = [Target(target) for target in self.gmp.get_targets().xpath('target')] logging.info('Targets found in DB: {}'.format(', '.join([target.name for target in targets]))) return targets except Exception as ex: logging.error('Getting targets error: {}'.format(ex)) return False def get_tasks(self, exclude_containers=True): if self.connect(): try: tasks = self.gmp.get_tasks().xpath('task') logging.info('Tasks found in DB: {}'.format(', '.join([task.find('name').text for task in tasks]))) if exclude_containers: return [Task(task) for task in tasks if not self._is_container_task(task)] else: return [Task(task) for task in tasks] except Exception as ex: logging.error('Getting tasks error: {}'.format(ex)) return False def save_report(self, report_id:str, directory:str): if self.connect(): try: raw_report = self.gmp.get_report(report_id).find('report') report = Report(raw_report) logging.info('Got report: {}'.format(report.name)) file_name = '{}-{}.xml'.format(report.task_name, report.name) file_path = os.path.join(directory, file_name) logging.info('Saving report to file {}'.format(file_path)) if os.path.isfile(file_path): raise Exception('File exists: {}'.format(file_path)) with io.open(file_path, 'wb') as file: file.write(ET.tostring(raw_report, encoding='utf-8', method='xml', pretty_print=True)) return True except Exception as ex: logging.error('Getting targets error: {}'.format(ex)) return False