Greenbone (OpenVAS) в Docker: сканирование по расписанию и контроль завершения

0
15
Обложка статьи: Greenbone (OpenVAS) в Docker: сканирование по расписанию и контроль завершения

Таблица «что чем сканируем» в любой статье про уязвимости упирается в один вопрос: каким сканером. Бесплатный и достаточно сильный вариант для небольшой компании — Greenbone Community Edition (ядро OpenVAS). Ниже установка в Docker, настройка сканирования внешнего периметра и внутренней сети, расписание «раз в неделю» и «раз в месяц» и проверка, что скан прошёл, а не молча сломался. Если по закону или правилам вам нужны сертифицированные средства, берите их; логика расписания, оповещений и хранения результатов не меняется.

Как читать результат и превращать его в задачи — в разборе отчёта сканера. Куда складывать находки — в реестр уязвимостей.

Где запускать сканер

Сканеров обычно два, и это не прихоть. Для внешнего периметра сканер должен стоять снаружи вашей сети, например на недорогой виртуальной машине у стороннего хостера: только так видно то, что видит атакующий. Для внутренней сети сканер стоит внутри, в сегменте управления, и ему разрешён доступ к узлам по SSH и SMB. Один сканер внутри не заменит внешний: он покажет открытое, но не покажет, что из этого доступно из интернета.

Ресурсы: ориентируйтесь на четыре ядра и 8 ГБ памяти; для небольшого парка хватает и меньшего, но первая синхронизация лент тестов идёт заметно дольше. Диск: несколько десятков гигабайт под ленты и базу. Сканировать можно только свои адреса или адреса, на которые есть письменное разрешение владельца.

Шаг 1. Установка в Docker

Команды из официальной инструкции Greenbone для контейнеров Community Edition. Имя файла compose может смениться с выходом новой серии, поэтому актуальную ссылку проверьте в документации перед запуском.

export DOWNLOAD_DIR=$HOME/greenbone-community-container
mkdir -p "$DOWNLOAD_DIR" && cd "$DOWNLOAD_DIR"

curl -f -L https://greenbone.github.io/docs/latest/_static/docker-compose-22.4.yml -o docker-compose.yml

docker compose -f docker-compose.yml -p greenbone-community-edition pull
docker compose -f docker-compose.yml -p greenbone-community-edition up -d

Ожидаемо: команда pull скачивает с десяток образов, up -d поднимает контейнеры (gvmd, ospd-openvas, gsa, база pg-gvm, redis, брокер сообщений). Веб-интерфейс слушает только 127.0.0.1:9392, и так оставьте: не публикуйте его в интернет.

Если сканер на удалённой машине, заходите в интерфейс через SSH-туннель:

ssh -L 9392:127.0.0.1:9392 admin@scanner.example.com
# затем откройте в браузере http://127.0.0.1:9392

Сразу смените пароль администратора (в компоновке по умолчанию он известен):

docker compose -f docker-compose.yml -p greenbone-community-edition \
  exec -u gvmd gvmd gvmd --user=admin --new-password="$NEW_GVM_PASSWORD"

Первая загрузка лент тестов идёт десятки минут, а то и часа. Пока лента не загрузилась, в интерфейсе в разделе Administration → Feed Status статус будет отличаться от «Current», а скан запускать бессмысленно: он будет работать без большей части тестов и выдаст почти пустой отчёт.

Риск: контейнеры с данными лент и базой нужно сохранять в резервной копии или хотя бы не удалять по ошибке командой down -v: она сотрёт тома вместе с историей отчётов.

Шаг 2. Цель, список портов и учётная запись

Все настройки в Configuration. Порядок такой.

Раздел Что создать Замечания
Targets Цель «Периметр» с вашими внешними адресами; цель «Внутренняя сеть» Адреса берите из реестра активов, а не «весь /16». Исключите узлы, которые нельзя трогать (хрупкое оборудование, АСУ ТП), в поле Exclude Hosts
Port Lists Для периметра — все TCP-порты; для внутренней сети — стандартный набор Полный перебор 65535 портов на каждом узле занимает время, поэтому для внутренней сети обычно хватает порт-листа по умолчанию
Credentials Учётная запись для SSH (логин и ключ), для Windows — SMB-учётка Выделите отдельную учётку «scanuser» только для сканера. Без учётки сканер видит только баннеры

Для Linux достаточно непривилегированной учётной записи: список установленных пакетов читается без прав администратора. Права выше нужны только отдельным проверкам конфигурации. Создайте пользователя и ключ без права входа интерактивно с чужих адресов:

sudo useradd -m -s /bin/bash scanuser
sudo install -d -m 700 -o scanuser -g scanuser /home/scanuser/.ssh
# в authorized_keys добавьте публичный ключ сканера и ограничение по адресу
echo 'from="192.0.2.50" ssh-ed25519 ПУБЛИЧНЫЙ_КЛЮЧ_СКАНЕРА greenbone' | sudo tee /home/scanuser/.ssh/authorized_keys
sudo chmod 600 /home/scanuser/.ssh/authorized_keys
sudo chown scanuser:scanuser /home/scanuser/.ssh/authorized_keys

Ожидаемо: вход с адреса сканера по ключу работает, с других адресов — нет. Приватный ключ загрузите в Credentials, на самом сервере он не хранится. Если вы раскатываете учётку на парк, делайте это центральным средством: GPO и Ansible.

Для Windows используйте учётную запись с правом чтения реестра и WMI; точный набор прав описан в документации Greenbone. Не давайте сканеру учётку доменного администратора: компрометация сканера не должна означать компрометацию домена.

Шаг 3. Задача, профиль и нагрузка

В Scans → Tasks создайте задачу: выберите цель, сканер OpenVAS и профиль (Scan Config). Выбор профиля влияет на время и нагрузку.

Профиль Когда использовать Замечание
Full and fast Основной профиль для периметра и внутренней сети Запускает почти все тесты, кроме опасных для устойчивости сервисов
Discovery Инвентаризация: что живо и какие порты открыты Не ищет уязвимости, хорош для сверки с реестром активов
Base Быстрая проверка «ничего ли не сломали» Минимум тестов; не заменяет полный скан

В расширенных настройках задачи ограничьте число одновременно проверяемых узлов и тестов на узел. Для сети с хрупкими устройствами держите значения скромными: агрессивный скан способен положить принтер или старый коммутатор, и первые жалобы придут к вам.

Шаг 4. Расписание

В Configuration → Schedules создайте расписание по формату iCalendar. Для проверки «не реже раза в месяц» и «еженедельно для периметра» нужны два:

Задача Периодичность Когда запускать
Периметр Раз в неделю Ночью по будням, чтобы утром вы уже читали отчёт
Внутренняя сеть с учётной записью Раз в месяц В начале месяца, за неделю до окна обновлений, чтобы успеть выдать заявки
Критичные узлы Раз в неделю Отдельной задачей с мягким профилем, если их нельзя сканировать вместе со всеми

В карточке расписания укажите часовой пояс явно. Типичная причина «скан не запустился»: расписание создано в UTC, а ждали по местному времени, и задача ушла на другие сутки. Привяжите созданное расписание к задаче в её настройках.

Путь скана в Greenbone: от цели до заявкиЦель и учётная запись, задача с профилем и расписанием, сканер, отчёт, оповещение, заявка владельцу.Цельадреса изреестраисключенияучётка длясканаЗадачапрофиль сканарасписаниеiCalокно инагрузкаСканерospd-openvasленты тестовNotus попакетамОтчётCSV и PDFQoD и CVSSсравнение спрошлымОповещениеписьмо илиHTTPпри статусеDoneзаявка вреестрЕсли оповещение не пришло к концу окна, скан считается несостоявшимся: это иесть контроль завершения.
Каждый шаг оставляет артефакт: список целей, расписание, отчёт, оповещение.

Шаг 5. Оповещения и контроль завершения

Требование к расписанию звучит так: недостаточно настроить, надо контролировать, что каждый скан завершился. Для этого нужны два механизма.

Оповещение. В Configuration → Alerts создайте оповещение: событие «Task run status changed» со значением «Done», условие «Always», метод на выбор. Письмо требует настроенной почтовой службы внутри контейнера gvmd, поэтому в контейнерной установке проще использовать другие методы: HTTP Get на ваш вебхук или системный журнал (System Logger), откуда событие попадёт в Wazuh или Zabbix. Привяжите оповещение к задаче.

Контроль «молчания». Оповещение приходит только если скан завершился. Если задача не запустилась или зависла, не придёт ничего, и именно об этом надо узнавать. Скрипт ниже раз в сутки проверяет, что у задачи есть свежий отчёт, и возвращает код 1, если его нет. Его можно запускать из cron или из Zabbix. Он использует утилиту gvm-cli из пакета gvm-tools (установите её на хосте). Путь к сокету gvmd в вашей компоновке смотрите командой docker volume inspect для тома gvmd_socket_vol.

#!/usr/bin/env python3
"""Проверка свежести отчёта задачи Greenbone: код выхода 1, если отчёта нет или он старше N дней.
Использование: check_scan.py ИМЯ_ЗАДАЧИ ДНЕЙ
Пароль берётся из переменной окружения GVM_PASSWORD."""
import os
import subprocess
import sys
import xml.etree.ElementTree as ET
from datetime import datetime, timezone

SOCKET = '/var/lib/docker/volumes/greenbone-community-edition_gvmd_socket_vol/_data/gvmd.sock'  # проверьте путь
task, days = sys.argv[1], int(sys.argv[2])

xml = f'<get_tasks filter="name={task} rows=1"/>'
cmd = ['gvm-cli', '--gmp-username', 'admin', '--gmp-password', os.environ['GVM_PASSWORD'],
       'socket', '--socketpath', SOCKET, '--xml', xml]
out = subprocess.run(cmd, capture_output=True, text=True, check=True).stdout
root = ET.fromstring(out)
ts = root.findtext('.//last_report/report/timestamp')
if not ts:
    print(f'ПРОВАЛ: у задачи {task} нет ни одного отчёта')
    sys.exit(1)
age = (datetime.now(timezone.utc) - datetime.fromisoformat(ts.replace('Z', '+00:00'))).days
print(f'отчёт задачи {task}: {ts}, возраст {age} дн.')
sys.exit(1 if age > days else 0)

Ожидаемо: для исправной недельной задачи вывод вида «возраст 3 дн.» и код 0. Для задачи, которая не запускалась, код 1. Запустите вручную и убедитесь, что скрипт возвращает 1 на задаче без отчётов, прежде чем вешать его в мониторинг.

Шаг 6. Отчёт, фильтры и сравнение

Откройте последний отчёт и сразу выставьте фильтр: минимальный QoD 70 (так по умолчанию, но проверьте) и серьёзность не ниже средней. Дальше два полезных приёма.

  • Сравнение отчётов. Кнопка «Delta report» показывает, что появилось и что исчезло по сравнению с прошлым сканом. Это самый быстрый способ проверить закрытие после обновления.
  • Экспорт. CSV для импорта в реестр, PDF для людей. В имени файла сохраняйте дату и название задачи.

Разбор находок, группировка по действию и подтверждение закрытия описаны в отдельной статье.

Какие артефакты хранить

Для регулярного сканирования подтверждением служат пять вещей. Заведите для них одну папку или раздел трекера.

Что хранить Откуда взять Какое требование подтверждает
Скриншот или выгрузка списка задач с расписанием Scans → Tasks, Configuration → Schedules Скан настроен и запускается регулярно
Отчёты за последние три месяца Reports, экспорт PDF и CSV Скан реально проходил, а не только настроен
Перечень целей с датой актуализации Targets и реестр активов Охват: сканируется вся инфраструктура, включая периметр
Оповещения о завершении и вывод скрипта контроля Почта, вебхук, журнал Завершение каждого скана контролируется
Порядок действий при провале скана Регламент, раздел о сканировании Кто и за какое время реагирует, если отчёта нет

Диагностика

Симптом Причина и что делать
Скан завершается за несколько минут, находок почти нет Ленты тестов не загружены или сканер не авторизовался. Проверьте Feed Status и статус входа по каждому узлу
Задача зависла в состоянии «Running» сутками Слишком большой диапазон или недоступный узел с долгими тайм-аутами. Разбейте цель, уменьшите число одновременных узлов
После обновления контейнеров пропали отчёты Тома были удалены. Проверьте, что данные базы лежат в сохраняемом томе, и добавьте их в резервное копирование
Скан периметра изнутри показывает «всё закрыто» Он смотрит из-за межсетевого экрана. Периметр сканируйте снаружи
Узел внезапно перезагружается во время скана Агрессивный профиль или хрупкая служба. Вынесите узел в отдельную цель с мягкими настройками

Где это в модели зрелости

Материал относится к направлению «Управление уязвимостями» (хаб: уязвимости, карта: карта зрелости). Он закрывает вторую ступень: автоматический скан внешнего периметра и всей инфраструктуры, расписание не реже раза в месяц и контроль успешного завершения. Итоговые отчёты и их связь с задачами нужны уже для третьего уровня: реестр.

Как проверить

  1. В Feed Status все ленты в состоянии «Current».
  2. Для каждой задачи видно расписание и дату следующего запуска.
  3. В Reports есть отчёты за последние три месяца без пропущенных периодов.
  4. Скрипт контроля на тестовой задаче без отчётов возвращает код 1, на исправной — 0.
  5. Скан внутренней сети с учётной записью показывает версии пакетов, а не только баннеры.

Источники

Комментарии закрыты.