Exemplo n.º 1
0
    def tasks(self) -> Iterator[Union[str, str, str]]:
        """ extract ip, mac, task-IDs """

        raw_data = self._omp(['--xml', '<get_tasks/>'], 300)

        for result_line in re.findall(r"<task id=\"[0-9a-f-]*?\">.*?</task>",
                                      raw_data):
            try:
                name = re.findall('<target id=.*?>.*</name>', result_line)[0]
                name = re.findall('<name>.*?</name>', name)[0]
                ip = re.findall('\(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\)',
                                name)[0][1:-1]
                mac = re.findall(
                    '>[\dA-F]{2}:[\dA-F]{2}:[\dA-F]{2}:[\dA-F]{2}:[\dA-F]{2}:[\dA-F]{2}\s',
                    name)[0][1:-1]
                if len(ip) < 8 or len(mac) < 17:
                    log.err('task strange mac/ip')
                    continue

                status = re.findall('<status>.*?</status>', result_line)[0]
                running = True if rm_tags(status) == "Running" else False

            except IndexError:
                log.err('task index error')
                continue

            task = re.findall('<task id=\"[0-9a-f-]*?\">', result_line)[0]
            task = get_quote(task)

            yield ip, mac, task, running
Exemplo n.º 2
0
    def _omp(self, arg: list, timeout: int = 30) -> str:
        """ communication with OpenVAS """

        cmd = self.base_cmd.split() + arg
        label = cmd[0] + " " + " ".join(cmd[len(cmd) - 2:])

        tried = 0
        while tried < 3:
            stdout, _ = exe(cmd, timeout=timeout, label=label)

            if not stdout:
                raise SystemExit(66)

            stdout = stdout.replace('\n', ' ')
            if "Failed to authenticate." in stdout:
                tried += 1
                log.err("wrong password or openvas busy [{0}/3]".format(tried))
                sleep(43)

            elif "Failed to acquire socket." in stdout:
                log.crit("Failed to acquire socket.".format(self.port))
                raise SystemExit(6)

            else:
                return stdout

        log.crit("giving up, wrong password or openvas busy." \
                 "try `systemctl restart greenbone-security-assistant` @ {0}.".format(self.ip))
        raise SystemExit(4)
Exemplo n.º 3
0
    def reports(self) -> Iterator[Union[str, str, datetime]]:
        """ extract ip, reportID and time stamp from openvas report """

        raw_data = self._omp(['--xml', '<get_reports/>'], 300)

        for report_chunk in re.findall(
                r"<report id=\"[0-9a-f-]*?\">.*?</report>", raw_data):

            report = re.findall(r"<report id=\"[0-9a-f-]*?\">",
                                report_chunk)[0]
            report = get_quote(report)

            for result_chunk in re.findall(
                    r"<result id=\"[0-9a-f-]*?\">.*?</result>", report_chunk):

                ip = re.findall('<host>[0-9.]*?<.*?>', result_chunk)
                if not len(ip) == 1:
                    log.err('report: multiple hosts found')
                    continue
                ip = rm_tags(ip[0])

                stamp = re.findall(
                    '<modification_time>.*?</modification_time>', result_chunk)
                if not len(stamp) == 1:
                    log.err('report: multiple timestamps found')
                    continue

                stamp = rm_tags(stamp[0])
                stamp = datetime.strptime(stamp[:19], '%Y-%m-%dT%H:%M:%S')

                yield ip, report, stamp
Exemplo n.º 4
0
def import_targets(path: str) -> None:
    """ call method for file or folder """

    if os.path.isfile(path):
        import_target_file(path)

    elif os.path.isdir(path):
        import_target_folder(path)

    else:
        log.err('nothing to import from `{0}`?'.format(path))
Exemplo n.º 5
0
def exe(command: Union[list, str],
        **kwargs) -> Tuple[Union[str, bool], Union[str, Exception]]:
    """ execute external process, returns (stdout: str|false, stderr: str)
    
    kwargs:
        timeout: default = 300sec
        label: log-label
    """

    timeout = kwargs.pop('timeout', 300)
    if not isinstance(timeout, int):
        raise ValueError("timeout can be int only")

    if isinstance(command, str):
        command = command.split()

    elif not isinstance(command, list):
        raise ValueError("command can be list or string only")

    label = kwargs.pop('label', command[0])

    try:
        subp = Popen(command, stdout=PIPE, stderr=STDOUT)

    except OSError:
        log.crit("`{0}` not found".format(command[0]))
        return False, 'not found'

    except Exception as e:
        log.crit("`{0}` failed: {1}".format(command[0], e))
        return False, e

    try:
        stdout, stderr = subp.communicate(timeout=timeout)

    except TimeoutExpired:
        log.err('`{0}` exceeded timeout ({1} sesc}.'.format(
            command[0], timeout))
        subp.kill()
        return False, 'timeout'

    except Exception as e:
        log.crit("`{0}` communication failed: {1}".format(command[0], e))
        return False, e

    stdout = '' if not stdout else stdout.decode('utf8')
    stderr = '' if not stderr else stderr.decode('utf8')

    log.debug('`{0}` executed.'.format(label))
    return stdout, stderr
Exemplo n.º 6
0
def openvas_run_task() -> None:
    """ try to start OV task until success, ordered by last_report """

    if tasks_running() > config['run_limit']:
        log.info('limit of {0} running tasks reached, no new task.'.format(
            config['run_limit']))
        return

    for ip, _ in test_order('last_attempt'):
        if machine[ip].running:
            log.info('[{0}]: task already running'.format(
                machine[ip].data['mac']))
            continue

        machine[ip].data['last_attempt'] = now()

        if args.verify:
            real_mac = get_mac(ip)
            if real_mac and not machine[ip].data['mac'] == real_mac:
                log.warn('[{0}]: ERROR: address conflict {1} ({2})'.format(
                    machine[ip].data['mac'], real_mac, ip))
                continue

        if ov.run_task(machine[ip].task):
            log.notice('[{0}]: started OpenVAS task'.format(
                machine[ip].data['mac']))

            sleep(60 * 2)

            if task_running(ip):
                log.debug('[{0}]: running task verified'.format(
                    machine[ip].data['mac']))
                machine[ip].keep = True
                break

            else:
                log.warn('[{0}]: task was aborted'.format(
                    machine[ip].data['mac']))
                continue

        else:
            log.warn('[{0}]: FAILED starting OpenVAS task'.format(
                machine[ip].data['mac']))

            continue

    else:
        log.err('FAILED to start any OpenVAS task.')
Exemplo n.º 7
0
def clean_up():
    """ remove machines with last successfull test older than threshold days """
    now = datetime.now()
    for ip in machine:
        if machine[ip].running or machine[ip].keep:
            continue

        last_success = now - machine[ip].data['last_report']
        last_success = last_success.days
        last_attempt = now - machine[ip].data['last_attempt']
        last_attempt = last_attempt.days

        if not last_success > config['clean_up_threshold_days'] \
          or not last_attempt < config['clean_up_threshold_days']:
            continue

        if machine[ip].task and not (ov.rm('task', machine[ip].task)):
            log.err("[{0}]: failed removing task ({1})".format(
                machine[ip].data['mac'], ip))

        if machine[ip].target and not ov.rm('target', machine[ip].target):
            log.err("[{0}]: failed removing target ({1})".format(
                machine[ip].data['mac'], ip))
Exemplo n.º 8
0
def mk_machine(json_data: dict, source: str) -> None:
    """ create new machine object """

    try:
        json_data['ip'], json_data['mac']
    except KeyError:
        log.err('failed importing `{0}`'.format(source))

        return

    ip = json_data['ip']
    new = registered(ip, True)

    if not machine[ip].data['mac']:
        machine[ip].data['mac'] = json_data['mac'].upper()

    if json_data.get('skip', False):
        machine[ip].skip = machine[ip].data['skip'] = True

    machine[ip].data['comment'] = json_data['comment']

    if new:
        log.debug('config for {0} [{1}] imported'.format(
            machine[ip].data['ip'], machine[ip].data['mac']))