Wazuh: обнаружение уязвимостей, обогащение KEV и EPSS и заявка по критичным

0
19
Обложка статьи: Wazuh: обнаружение уязвимостей, обогащение KEV и EPSS и заявка по критичным

Сканер раз в неделю или раз в месяц — это снимок. Между снимками выходят уязвимости, и о них вы узнаёте при следующем запуске. Агент Wazuh, который уже стоит на узлах, каждые несколько часов отправляет список установленных пакетов и сопоставляет его с базой уязвимостей, поэтому он показывает новую дыру почти сразу после выхода записи. Ниже как это включить, как проверить, что оно работает, как добавить сведения об эксплуатации и как превратить критичную находку в заявку или инцидент без ручного разбора каждой.

Сам Wazuh и его первые правила разобраны в статьях установка в Docker и правила обнаружения атак. Чем отличается SIEM от мониторинга, смотрите в разборе SOC и SIEM. Как устроен реестр, куда попадает результат, — реестр уязвимостей.

Что именно делает Wazuh и чем это не сканер

Сканер уязвимостей ходит по сети и проверяет узлы. Wazuh не сканирует: агент передаёт инвентарь (пакеты и версии), а сервер сопоставляет их с каталогами уязвимостей. Из этого следуют плюсы и минусы.

Свойство Следствие
Работает на постоянной основе, по мере обновления базы Не нужно ждать расписания скана
Использует данные производителя дистрибутива Учитывает исправления, перенесённые в старые версии пакетов (backport): ложных срабатываний меньше, чем у сканирования по баннерам
Видит только то, что ставится пакетами Вручную установленное ПО, веб-приложения и конфигурации остаются невидимыми: нужен сканер и проверка конфигураций
Требует агента Сетевое оборудование и устройства без агента не покрываются

Вывод: Wazuh дополняет регулярные сканы, а не заменяет их. Для периметра по-прежнему нужен сканирующий взгляд снаружи.

Шаг 1. Включение (Wazuh 4.8 и новее)

В версии 4.8 детектор уязвимостей переработан: результаты хранятся в индексе индексатора, а не только в оповещениях. Поведение зависит от версии, поэтому сначала проверьте, что у вас стоит.

/var/ossec/bin/wazuh-control info

Ожидаемо: строка WAZUH_VERSION="v4.x.y". Для версий до 4.8 порядок иной (детектор работает по оповещениям, группа правил vulnerability-detector) и поля ниже называются по-другому. В стандартной контейнерной установке модуль обычно включён. Если нет, добавьте блок в конфигурацию менеджера:

<vulnerability-detection>
  <enabled>yes</enabled>
  <index-status>yes</index-status>
  <feed-update-interval>60m</feed-update-interval>
</vulnerability-detection>

Затем перезапустите менеджер и дайте базе загрузиться: первое обновление занимает время. Не включайте детектор на слабой машине без запаса диска и памяти: индекс находок растёт вместе с числом узлов.

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

Шаг 2. Выгрузка критичных находок

Для автоматизации нужен доступ к индексу находок. Он хранится в индексе вида wazuh-states-vulnerabilities-*. Запрос к индексатору (создайте отдельного пользователя только на чтение, а не используйте администратора):

curl -sk -u reader:ПАРОЛЬ "https://127.0.0.1:9200/wazuh-states-vulnerabilities-*/_search?size=3" \
  -H 'Content-Type: application/json' \
  -d '{"query":{"term":{"vulnerability.severity":"Critical"}},
       "_source":["agent.name","package.name","package.version","vulnerability.id","vulnerability.score.base"]}'

Ожидаемо: JSON с массивом hits, в каждой записи имя узла, пакет, версия и идентификатор CVE. Названия полей и значение серьёзности («Critical») могут отличаться в вашей версии: сверьте с тем, что видно во вкладке просмотра документов индекса, и поправьте запрос.

Шаг 3. Обогащение: KEV, EPSS и доступность

Серьёзность по базе — это CVSS. Для решения «что делать сегодня» нужны ещё сведения об эксплуатации и о том, виден ли узел из интернета. Скрипт ниже берёт критичные и высокие находки из индекса, добавляет признак KEV и значение EPSS и присваивает приоритет по матрице из основной статьи. Доступность из интернета берётся из вашего файла соответствия «имя узла — периметр или внутренний», потому что Wazuh этого не знает.

#!/usr/bin/env python3
"""Находки Wazuh -> приоритет P1..P4 с учётом KEV, EPSS и доступности узла.
Использование: wazuh_prioritize.py exposure.csv
exposure.csv: строки вида имя_узла,internet|internal
Переменные среды: WAZUH_INDEXER (например https://127.0.0.1:9200), WAZUH_USER, WAZUH_PASSWORD."""
import base64
import csv
import json
import os
import ssl
import sys
import urllib.parse
import urllib.request

KEV = 'https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json'
EPSS = 'https://api.first.org/data/v1/epss'
ctx = ssl.create_default_context()
if os.environ.get('WAZUH_INSECURE') == '1':      # только для проверки на стенде
    ctx.check_hostname, ctx.verify_mode = False, ssl.CERT_NONE

def get_json(url, body=None, auth=None):
    req = urllib.request.Request(url, data=body, headers={'Content-Type': 'application/json'})
    if auth:
        req.add_header('Authorization', 'Basic ' + base64.b64encode(auth.encode()).decode())
    with urllib.request.urlopen(req, timeout=60, context=ctx) as r:
        return json.load(r)

exposure = {r[0]: r[1] for r in csv.reader(open(sys.argv[1], encoding='utf-8')) if len(r) >= 2}
kev = {v['cveID'] for v in get_json(KEV)['vulnerabilities']}

q = {'size': 1000, '_source': ['agent.name', 'package.name', 'package.version', 'vulnerability.id', 'vulnerability.score.base'],
     'query': {'terms': {'vulnerability.severity': ['Critical', 'High']}}}
hits = get_json(os.environ['WAZUH_INDEXER'] + '/wazuh-states-vulnerabilities-*/_search',
                json.dumps(q).encode(), f"{os.environ['WAZUH_USER']}:{os.environ['WAZUH_PASSWORD']}")['hits']['hits']

cves = sorted({h['_source']['vulnerability']['id'] for h in hits})
epss = {}
for i in range(0, len(cves), 50):
    data = get_json(EPSS + '?' + urllib.parse.urlencode({'cve': ','.join(cves[i:i + 50])}))
    epss.update({d['cve']: float(d['epss']) for d in data['data']})

def priority(cve, host, cvss):
    inet = exposure.get(host) == 'internet'
    e = epss.get(cve, 0)
    if (cve in kev and inet) or (inet and e >= 0.9):
        return 'P1'
    if cve in kev or e >= 0.5 or (inet and cvss >= 9):
        return 'P2'
    return 'P3' if cvss >= 7 or e >= 0.1 else 'P4'

rows = []
for h in hits:
    s = h['_source']
    cve, host = s['vulnerability']['id'], s['agent']['name']
    cvss = float(s['vulnerability'].get('score', {}).get('base', 0))
    rows.append((priority(cve, host, cvss), host, cve, s['package']['name'], s['package']['version'], cve in kev, epss.get(cve, 0)))
for r in sorted(rows):
    print(*r, sep=';')
sys.exit(1 if any(r[0] == 'P1' for r in rows) else 0)

Ожидаемо: строки «приоритет;узел;CVE;пакет;версия;в KEV;EPSS», отсортированные по приоритету, код выхода 1 при наличии P1. Запускайте на хосте, откуда доступен индексатор, и храните учётные данные в переменных среды, а не в файле. Скрипт можно ставить в cron раз в сутки; код выхода 1 используйте как условие для срочного уведомления.

Шаг 4. Заявка или инцидент по P1

Цепочка от находки до инцидентаАгент собирает пакеты, Wazuh сопоставляет с базой, скрипт обогащает KEV и EPSS, создаётся заявка или инцидент.Агентсписокпакетовна каждомузлеWazuhсопоставлениес базойиндекснаходокОбогащениеKEV и EPSSкритичностьактиваРешениеP1 или P2правилоэскалацииИнцидентзаявка иликарточкасрок ивладелецАвтоматизируйте обогащение и создание заявки; блокировку и остановку сервисаоставьте решением человека.
Цепочка делается по шагам: сначала заявка по P1, потом остальные приоритеты.

Автоматизируйте то, что безопасно: создание заявки и уведомление. Остановку сервиса и блокировку оставьте решением человека, пока не наберётся опыт. Правило эскалации:

Приоритет Автоматически Решает человек
P1 Заявка с меткой «срочно», уведомление ответственному за ИБ и владельцу узла, запись в реестр Снимать сервис с интернета или применять компенсирующую меру; открывать ли инцидент по критериям классификации
P2 Заявка со сроком, запись в реестр Окно обновления
P3 и P4 Запись в реестр, еженедельный отчёт Плановое обновление

Если по P1 есть признаки эксплуатации (необычные входы, новые процессы, исходящий трафик), заводите инцидент: порядок в карточке инцидента и плейбуке критичной уязвимости. Создание заявки через API трекера показано в статье про реестр уязвимостей.

Что считать анализом угроз для малой инфраструктуры

Четвёртый уровень зрелости требует решения класса Threat Intelligence, которое даёт контекст, критичность и актуальность угроз. В большой компании это коммерческая платформа. В небольшой разумный минимум другой, и его можно показать как работающее решение, если оно настроено и используется регулярно.

  • Каталог KEV и оценка EPSS как источники контекста об эксплуатации; обновление автоматическое, как в скрипте выше.
  • Списки индикаторов компрометации (адреса, домены, хэши) в формате списков Wazuh, которые подключаются к правилам и обогащают оповещения. Обновляйте их по расписанию из надёжных источников.
  • Для организаций, которые уже обмениваются индикаторами, платформа вроде MISP как хранилище и источник лент.

Как показать работу: перечень источников с настройками, отчёты по уязвимостям, в которых указаны данные KEV и EPSS, и журнал обновления лент. Выбирайте решение по реальной потребности: покупка платформы, которую никто не смотрит, на проверке не поможет.

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

Что хранить Что показывает
Конфигурация детектора уязвимостей и список агентов с их состоянием Обнаружение настроено и покрывает парк
Скрипт обогащения и расписание его запуска, журнал выполнения Данные KEV и EPSS используются при анализе
Примеры созданных заявок и инцидентов по P1 Критичные находки превращаются в действия, а не остаются в панели
Правило эскалации по приоритетам Разделение автоматических и ручных решений
Перечень источников анализа угроз с настройками Решение уровня TI существует и поддерживается

Диагностика

Симптом Причина и что делать
В модуле уязвимостей пусто при живых агентах База ещё не загружена или инвентарь не передан. Проверьте журнал менеджера и состояние модуля инвентаризации на агенте
Запрос к индексу возвращает ошибку 401 или 403 Неверный пользователь или нет прав на индекс. Создайте пользователя на чтение для этого индекса
Запрос возвращает ноль записей Другие названия полей или значение серьёзности. Откройте документ индекса и сверьте
Находка есть, а на узле пакет уже обновлён Инвентарь устарел или пакет в другом каталоге. Дождитесь передачи или перезапустите агент и повторите проверку
Слишком много P2 Порог EPSS слишком низкий для вашей среды. Поднимите значение и пересмотрите матрицу

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

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

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

  1. В модуле уязвимостей Wazuh видны все критичные узлы и числа по серьёзности.
  2. Скрипт обогащения на тестовом файле доступности выводит P1 для заведомо критичной находки на узле «internet» и P3–P4 для внутреннего узла.
  3. Для последней находки P1 есть заявка, дата и ответственный.
  4. Ленты KEV и EPSS обновляются по расписанию, в журнале нет ошибок сети.

Источники

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