def process_vts(self, vts): """ Add single VTs and their parameters. """ vts_list = [] vts_params = [] vtgroups = vts.pop('vt_groups') ctx = openvas_db.db_find(nvti.NVTICACHE_STR) openvas_db.set_global_redisctx(ctx) if vtgroups: vts_list = self.get_vts_in_groups(ctx, vtgroups) for vtid, vt_params in vts.items(): vts_list.append(vtid) nvt_name = self.vts[vtid].get('name') for vt_param_id, vt_param_value in vt_params.items(): param_type = self.get_vt_param_type(vtid, vt_param_id) if vt_param_id == 'timeout': type_aux = 'integer' else: type_aux = param_type if self.check_param_type(vt_param_value, type_aux): logger.debug( 'Expected {} type for parameter value {}'.format( type_aux, str(vt_param_value))) param = [ "{0}[{1}]:{2}".format(nvt_name, param_type, vt_param_id), str(vt_param_value) ] vts_params.append(param) return vts_list, vts_params
def redis_nvticache_init(self): """ Loads NVT's metadata into Redis DB. """ try: logger.debug('Loading NVTs in Redis DB') subprocess.check_call(['openvassd', '-C']) except subprocess.CalledProcessError as err: logger.error('OpenVAS Scanner failed to load NVTs.') raise err
def stop_scan(self, global_scan_id): """ Set a key in redis to indicate the wrapper is stopped. It is done through redis because it is a new multiprocess instance and it is not possible to reach the variables of the grandchild process. Send SIGUSR2 to openvas to stop each running scan.""" ctx = self.openvas_db.kb_connect() for current_kbi in range(0, self.openvas_db.max_dbindex): self.openvas_db.select_kb(ctx, str(current_kbi), set_global=True) scan_id = self.openvas_db.get_single_item( 'internal/%s/globalscanid' % global_scan_id) if scan_id: self.openvas_db.set_single_item('internal/%s' % scan_id, [ 'stop_all', ]) ovas_pid = self.openvas_db.get_single_item('internal/ovas_pid') parent = psutil.Process(int(ovas_pid)) self.openvas_db.release_db(current_kbi) parent.send_signal(signal.SIGUSR2) logger.debug('Stopping process: {0}'.format(parent))
def stop_scan(global_scan_id): """ Set a key in redis to indicate the wrapper is stopped. It is done through redis because it is a new multiprocess instance and it is not possible to reach the variables of the grandchild process. Send SIGUSR2 to openvas to stop each running scan.""" ctx = openvas_db.kb_connect() for current_kbi in range(0, openvas_db.MAX_DBINDEX): ctx.execute_command('SELECT ' + str(current_kbi)) openvas_db.set_global_redisctx(ctx) scan_id = openvas_db.item_get_single( ('internal/%s/globalscanid' % global_scan_id)) if scan_id: openvas_db.item_set_single(('internal/%s' % scan_id), [ 'stop_all', ]) ovas_pid = openvas_db.item_get_single('internal/ovas_pid') parent = psutil.Process(int(ovas_pid)) openvas_db.release_db(current_kbi) parent.send_signal(signal.SIGUSR2) logger.debug('Stopping process: {0}'.format(parent))
def check_feed(self): """ Check if there is a feed update. Wait until all the running scans finished. Set a flag to anounce there is a pending feed update, which avoid to start a new scan. """ _running_scan = False for scan_id in self.scan_processes: if self.scan_processes[scan_id].is_alive(): _running_scan = True if self.pending_feed: _pending_feed = True else: _pending_feed = self.get_vts_version() != nvti.get_feed_version() if _running_scan and _pending_feed: if not self.pending_feed: self.pending_feed = True logger.debug('There is a running scan. Therefore the feed ' 'update will be performed later.') elif not _running_scan and _pending_feed: self.vts = dict() self.load_vts()
def exec_scan(self, scan_id, target): """ Starts the OpenVAS scanner for scan_id scan. """ if self.pending_feed: logger.info('%s: There is a pending feed update. ' 'The scan can not be started.' % scan_id) self.add_scan_error( scan_id, name='', host=target, value=('It was not possible to start the scan,' 'because a pending feed update. Please try later')) return 2 global MAIN_KBINDEX ports = self.get_scan_ports(scan_id, target) if not ports: self.add_scan_error(scan_id, name='', host=target, value='No port list defined.') return 2 # Get scan options options = self.get_scan_options(scan_id) prefs_val = [] ctx = openvas_db.kb_new() openvas_db.set_global_redisctx(ctx) MAIN_KBINDEX = openvas_db.DB_INDEX # To avoid interference between scan process during a parallel scanning # new uuid is used internally for each scan. openvas_scan_id = str(uuid.uuid4()) openvas_db.item_add_single(('internal/%s' % openvas_scan_id), [ 'new', ]) openvas_db.item_add_single(('internal/%s/globalscanid' % scan_id), [ openvas_scan_id, ]) # Set scan preferences for item in options.items(): item_type = '' if item[0] in OSPD_PARAMS: item_type = OSPD_PARAMS[item[0]].get('type') if item_type == 'boolean' and item[1] == 1: val = 'yes' else: val = str(item[1]) prefs_val.append(item[0] + "|||" + val) openvas_db.item_add_single( str('internal/%s/scanprefs' % (openvas_scan_id)), prefs_val) # Store MAIN_KBINDEX as global preference ov_maindbid = ('ov_maindbid|||%d' % MAIN_KBINDEX) openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id), [ ov_maindbid, ]) # Set target target_aux = ('TARGET|||%s' % target) openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id), [ target_aux, ]) # Set port range port_range = ('port_range|||%s' % ports) openvas_db.item_add_single(('internal/%s/scanprefs' % openvas_scan_id), [ port_range, ]) # Set credentials credentials = self.get_scan_credentials(scan_id, target) if credentials: cred_prefs = self.build_credentials_as_prefs(credentials) openvas_db.item_add_single( str('internal/%s/scanprefs' % openvas_scan_id), cred_prefs) # Set plugins to run nvts = self.get_scan_vts(scan_id) if nvts != '': nvts_list, nvts_params = self.process_vts(nvts) # Select the scan KB again. ctx.execute_command('SELECT ' + str(MAIN_KBINDEX)) openvas_db.set_global_redisctx(ctx) # Add nvts list separ = ';' plugin_list = ('plugin_set|||%s' % separ.join(nvts_list)) openvas_db.item_add_single( ('internal/%s/scanprefs' % openvas_scan_id), [ plugin_list, ]) # Add nvts parameters for elem in nvts_params: item = ('%s|||%s' % (elem[0], elem[1])) openvas_db.item_add_single( ('internal/%s/scanprefs' % openvas_scan_id), [ item, ]) else: openvas_db.release_db(MAIN_KBINDEX) self.add_scan_error(scan_id, name='', host=target, value='No VTS to run.') return 2 # Create a general log entry about executing OpenVAS # It is important to send at least one result, otherwise # the host details won't be stored. self.add_scan_log(scan_id, host=target, name='OpenVAS summary', value='An OpenVAS Scanner was started for %s.' % target) self.add_scan_log(scan_id, host=target, name='KB location Found', value='KB location path was found: %s.' % openvas_db.DB_ADDRESS) self.add_scan_log(scan_id, host=target, name='Feed Update', value='Feed version: %s.' % nvti.get_feed_version()) cmd = ['openvassd', '--scan-start', openvas_scan_id] try: result = subprocess.Popen(cmd, shell=False) except OSError: # the command is not available return False ovas_pid = result.pid logger.debug('pid = {0}'.format(ovas_pid)) openvas_db.item_add_single(('internal/ovas_pid'), [ ovas_pid, ]) # Wait until the scanner starts and loads all the preferences. while openvas_db.item_get_single('internal/' + openvas_scan_id) == 'new': time.sleep(1) no_id_found = False while True: time.sleep(3) # Check if the client stopped the whole scan if self.scan_is_stopped(openvas_scan_id): return 1 ctx = openvas_db.kb_connect(MAIN_KBINDEX) openvas_db.set_global_redisctx(ctx) dbs = openvas_db.item_get_set('internal/dbindex') for i in list(dbs): if i == MAIN_KBINDEX: continue ctx.execute_command('SELECT ' + str(i)) openvas_db.set_global_redisctx(ctx) id_aux = ctx.execute_command('srandmember internal/scan_id') if not id_aux: continue if id_aux == openvas_scan_id: no_id_found = False self.get_openvas_timestamp_scan_host(scan_id, target) self.get_openvas_result(scan_id) self.get_openvas_status(scan_id, target) if self.scan_is_finished(openvas_scan_id): ctx.execute_command('SELECT ' + str(MAIN_KBINDEX)) openvas_db.remove_set_member('internal/dbindex', i) openvas_db.release_db(i) # Scan end. No kb in use for this scan id if no_id_found: break no_id_found = True # Delete keys from KB related to this scan task. openvas_db.release_db(MAIN_KBINDEX) return 1
def load_vts(self): """ Load the NVT's metadata into the vts global dictionary. """ logger.debug('Loading vts in memory.') oids = dict(nvti.get_oids()) for filename, vt_id in oids.items(): _vt_params = nvti.get_nvt_params(vt_id) _vt_refs = nvti.get_nvt_refs(vt_id) _custom = nvti.get_nvt_metadata(vt_id) _name = _custom.pop('name') _vt_creation_time = _custom.pop('creation_date') _vt_modification_time = _custom.pop('last_modification') _summary = None _impact = None _affected = None _insight = None _solution = None _solution_t = None _vuldetect = None _qod_t = None _qod_v = None if 'summary' in _custom: _summary = _custom.pop('summary') if 'impact' in _custom: _impact = _custom.pop('impact') if 'affected' in _custom: _affected = _custom.pop('affected') if 'insight' in _custom: _insight = _custom.pop('insight') if 'solution' in _custom: _solution = _custom.pop('solution') if 'solution_type' in _custom: _solution_t = _custom.pop('solution_type') if 'vuldetect' in _custom: _vuldetect = _custom.pop('vuldetect') if 'qod_type' in _custom: _qod_t = _custom.pop('qod_type') elif 'qod' in _custom: _qod_v = _custom.pop('qod') _severity = dict() if 'severity_base_vector' in _custom: _severity_vector = _custom.pop('severity_base_vector') else: _severity_vector = _custom.pop('cvss_base_vector') _severity['severity_base_vector'] = _severity_vector if 'severity_type' in _custom: _severity_type = custom.pop('severity_type') else: _severity_type = 'cvss_base_v2' _severity['severity_type'] = _severity_type if 'severity_origin' in _custom: _severity['severity_origin'] = _custom.pop('severity_origin') _vt_dependencies = list() if 'dependencies' in _custom: _deps = _custom.pop('dependencies') _deps_list = _deps.split(', ') for dep in _deps_list: _vt_dependencies.append(oids.get('filename:' + dep)) ret = self.add_vt(vt_id, name=_name, vt_params=_vt_params, vt_refs=_vt_refs, custom=_custom, vt_creation_time=_vt_creation_time, vt_modification_time=_vt_modification_time, vt_dependencies=_vt_dependencies, summary=_summary, impact=_impact, affected=_affected, insight=_insight, solution=_solution, solution_t=_solution_t, detection=_vuldetect, qod_t=_qod_t, qod_v=_qod_v, severities=_severity) if ret == -1: logger.info("Dupplicated VT with OID: {0}".format(vt_id)) if ret == -2: logger.info("{0}: Invalid OID.".format(vt_id)) _feed_version = nvti.get_feed_version() self.set_vts_version(vts_version=_feed_version) self.pending_feed = False logger.debug('Finish loading up vts.')