Сервис хранения единой базы уязвимостей#

В Platform V ASOC Control Center реализован Сервис хранения единой базы уязвимостей.

Описание Сервиса хранения единой базы уязвимостей приведено в документе Назначение.

Сервис хранения единой базы уязвимостей позволяет:

  • Получать данные об уязвимостях из внешних БДУ. Единая база уязвимостей дополняется записями о новых уязвимостях из разных источников. Процесс получения данных из разных источников описан в разделе Обновление единой базы уязвимостей из внешних БДУ.

  • Дедуплицировать записи об одной уязвимости, полученные из разных источников. Процесс дедупликации описан в разделе Дедупликация.

  • Сохранять историю происхождения записей.

  • Обновлять данные об уязвимостях - карточки уязвимостей в единой базе уязвимостей обновляются и дополняются.

  • Получать оригинальные и агрегированные записи об уязвимостях.

Обновление единой базы уязвимостей из внешних БДУ#

Для поддержания единой базы уязвимостей в актуальном состоянии, реализован механизм загрузки обновлений посредством выполнения запроса через защищенную точку подключения. Для выполнения запроса используется API конкретной БДУ.

Процесс загрузки уязвимостей из внешних источников (БДУ) осуществляется с заданной периодичностью, настраиваемой в файле конфигурации application.yaml (пример ниже в поле cron).

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

Параметр

Описание

Пример заполнения

name

Название источника

NVD

enabled

Флаг включения/выключения загрузчика из выбранного источника. Доступные значения true/false

true

cron

Расписание запуска загрузки уязвимостей в формате cron (минута час ДД ММ ДН)

00 10 01 01 2025

url

URL БДУ

https://services.nvd.nist.gov/rest/json/cves/2.0

apiKey

Токен для доступа к БДУ выдается на сайте БДУ

2f101f6d-dc26-4dac-9d2e-da715da6423e

resultsPerPage

Количество результатов получаемых из БДУ за один запрос

2000

start-date

Начальная дата загрузки уязвимостей из БДУ. Используется при первом запуске для загрузки всех уязвимостей с указанной даты. Значение по умолчанию 01.01.1988

1988-01-01T00:00:00

retry-attempts

Максимальное количество повторных попыток выполнения запроса к API БДУ в случае ошибки

3

initial-delay

Задержка между повторными запросами к API БДУ (в миллисекундах)

2000

concurrency

Количество параллельных потоков, используемых для загрузки уязвимостей из NVD

5

day-range

Максимальный диапазон дней, за который можно запрашивать данные из NVD за один запрос (ограничение API БДУ)

120

core-pool-size

Минимальное количество потоков в пуле потоков (остаются активными, даже если простаивают)

4

max-pool-size

Максимальное количество потоков в пуле потоков (дополнительные потоки создаются при перегрузке)

8

queue-capacity

Максимальное количество задач, которые могут ожидать в очереди, пока потоки будут доступны

5000

start-date

Начальная дата загрузки уязвимостей из БДУ GitHub Advisory. Используется при первом запуске

2010-01-01T00:00:00

max-retries

Максимальное количество повторных попыток выполнения запроса к API БДУ при ошибке

3

retry-delay

Задержка между повторными запросами к API БДУ (в миллисекундах)

2000

Пример заполнения параметров в application.yaml сервиса хранения единой базы уязвимостей:

   sources:                                                             #конфигурация передаваемая в класс загрузчика уязвимостей
     - name: NVD                                                        #название источника
       enabled: ${NVD_ENABLED:true}                                     #флаг включения/выключения загрузчика из выбранного источника
       cron: ${NVD_CRON:* * 10 * * *}                                   #периодичность запуска загрузки уязвимостей
       url: ${NVD_URL:https://services.nvd.nist.gov/rest/json/cves/2.0} #URL БДУ
       apiKey: ${NVD_API_KEY:2xx01xxd-dxx6-xxac-9xxe-xx71xxa6xx3x}      #токен для доступа к БДУ
       resultsPerPage: ${RESULT_PER_PAGE:2000}                          #Количество результатов получаемых из БДУ за один запрос
   nvd:
   loader:
     start-date: ${LOAD_START_DATE:1988-01-01T00:00:00}                 #начальная дата загрузки уязвимостей(используется при первом запуске для загрузки всех уязвимостей)
     retry-attempts: ${NVD_RETRY_ATTEMPT:3}                             #количество повторных попыток выполнения запросов
     initial-delay: ${NVD_INITIAL_DELAY:2000}                           #задержка между повторными запросами (миллисекунды)
     concurrency: ${NVD_CONCURRENCY:5}                                  #сколько параллельных потоков использовать для загрузки уязвимостей
     day-range: ${NVD_DAY_RANGE:120}                                    #ограничение NVD API на диапазон дат (максимум 120 дней можно запросить за раз)

   executor:                                                            #глобальные настройки пула потоков
     core-pool-size: ${CORE_POOL_SIZE:4}                                #минимальное количество потоков
     max-pool-size: ${MAX_POOL_SIZE:8}                                  #максимальное количество потоков
     queue-capacity: ${QUEUE_CAPACITY:5000}                             #очередь задач

Дедупликация#

Для исключения дублирующихся записей об уязвимостях и поддержания единой базы уязвимостей в актуальном состоянии, в Сервисе хранения единой базы уязвимостей реализован механизм регулярной дедупликации записей об одной и той же уязвимости, полученной из разных БДУ.

Процесс получения данных из внешних БДУ описан в разделе Обновление единой базы уязвимостей из внешних БДУ.

Механика дедупликации записей об уязвимостях#

Для дедупликации используется метод Ingestion deduplication/ingest-time deduplication - дедупликация в момент загрузки из внешних источников (БДУ).

  1. Запись об уязвимости попадает в единую базу уязвимостей и сохраняется в таблице raw_record:

    • Сервис хранения единой базы уязвимостей отправляет запрос во внешний источник (БДУ).

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

    • Запись сохраняется в таблице raw_record с указанием источника (source), идентификатора уязвимости (vuln_id), даты добавления (fetched_at) и сырых данных (payload).

  2. Единая база уязвимостей нормализует запись и сохраняет данные об уязвимости в таблицу normalized_raw_record:

    • Сервис хранения единой базы уязвимостей нормализует данные из таблицы raw_record.

    • Нормализованные данные сохраняются в таблицу normalized_raw_record с указанием идентификатора сырой записи (raw_id), даты создания (created), уровня серьезности (severity), базового балла CVSS (cvss_base_score), даты первой публикации (published), даты последнего обновления (updated), списка ссылок на источники (references), списка CWE-кодов (cwes), списка альтернативных идентификаторов (aliases) и оценки CVSS в виде векторной строки (cvss_vector).

  3. Сервис хранения единой базы уязвимостей проверяет наличие дубликатов:

    • Сервис сравнивает идентификатор уязвимости (vuln_id), источник (source) и значение в поле aliases с уже существующими записями в таблице normalized_raw_record.

    • Если запись уже существует, сервис определяет, что это дубликат.

  4. Если запись является дубликатом, сервис объединяет данные в агрегированную уязвимость:

    • Агрегированные данные сохраняются в таблицу cvuln с указанием заголовка уязвимости (title), полного агрегированного описания (description), агрегированного показателя CVSS (aggregated_cvss), списка затронутых пакетов (affected_packages), даты последнего обновления (last_updated) и агрегированного уровня серьезности (aggregated_severity).

  5. Запись о происхождении нормализованных данных сохраняется в таблицу provenance:

    • В таблицу provenance записывается информация о происхождении нормализованных данных, включая идентификатор агрегированной уязвимости (cvuln_id), идентификатор нормализованной записи (normalized_raw_id), этап дедупликации (merge_step), уровень уверенности алгоритма (confidence) и поля, которые данный источник внес в агрегат (fields_contributed).

  6. Прогресс загрузки данных об уязвимостях обновляется в таблице loading_track:

    • В таблицу loading_track записывается информация о прогрессе загрузки данных, включая источник уязвимостей (source_name), последнее успешно загруженное смещение (last_published_at), дату последней успешно загруженной уязвимости по дате публикации (last_start_index), дату последней успешно загруженной уязвимости по дате изменения (last_modified_at) и количество загруженных уязвимостей (count_vulnerabilities).

    @startuml
    title Дедупликация записей об уязвимостях
    
    actor "Источник данных об уязвимости" as source
    participant "Единая база уязвимостей" as db
    participant "Таблица raw_record" as raw
    participant "Таблица normalized_raw_record" as normalized
    participant "Таблица cvuln" as cvuln
    participant "Таблица provenance" as provenance
    participant "Таблица loading_track" as loading
    
    source -> db: Отправка записи об уязвимости
    db -> raw: Сохранение в raw_record
    db -> normalized: Нормализация данных
    normalized -> db: Проверка наличия дубликатов
    db -> cvuln: Объединение данных в агрегированную уязвимость
    db -> provenance: Сохранение информации о происхождении
    db -> loading: Обновление прогресса загрузки
    
    @enduml

Модель данных#

Модель данных сервиса хранения единой базы уязвимостей.

Описание таблиц модели данных единой базы уязвимостей:

  • raw_record - хранение сырых записей об уязвимости, полученных из внешнего источника;

  • normalized_raw_record - хранение нормализованных данных уязвимости, полученных из сырых записей;

  • component - хранение компонентов/пакетов программного обеспечения, для которых может существовать уязвимость;

  • vulnerable_component - хранение связей между уязвимостью и компонентом, отражающих, какие версии компонента подвержены данной уязвимости;

  • cvuln - хранение агрегированных уязвимостей, объединяющих информацию из разных источников;

  • provenance - хранение записей о происхождении нормализованных данных, вошедших в агрегированные уязвимости;

  • loading_track - хранение прогресса загрузки данных об уязвимостях из внешних источников.

raw_record#

Хранение сырых записей об уязвимости, полученных из внешнего источника.

Поле в таблице

Описание

fetched_at

Дата добавления записи об уязвимости в сервис

source

Источник данных об уязвимости. Поле обязательно к заполнению. Пример заполнения: NVD, GITHUB, OSV, FSTEK

vuln_id

Идентификатор уязвимости в источнике. Соответствует полю VULNID в Dependency Track, обязательно к заполнению. Пример заполнения: CVE-2025-49719, GHSA-9g4j-v8w5-7x42

payload

Сырые данные в формате JSON, сохраненные без изменений

normalized_raw_record#

Хранение нормализованных данных уязвимости, полученных из сырых записей.

Поле в таблице

Описание

raw_id

Идентификатор сырой записи, с которой связана нормализованная запись

created

Дата создания нормализованной записи

severity

Уровень серьезности уязвимости. Соответствует полю SEVERITY в Dependency Track. Пример: HIGH, MEDIUM, LOW, CRITICAL, INFO

cvss_base_score

Базовый балл уязвимости по CVSS. CVSS - система оценки уязвимости (подробное описание системы оценки приведено в официальной спецификация CVSS (Common Vulnerability Scoring System) версии 3.1). Базовые метрики дают оценку в диапазоне от 0 до 10

published

Дата первой публикации уязвимости в источнике

updated

Дата последнего обновления данных

references

Список ссылок на источники

cwes

Список CWE-кодов, связанных с уязвимостью

aliases

Список альтернативных идентификаторов уязвимости (например, GHSA-vwq2-jx9q-9h9f)

cvss_vector

Оценка CVSS в виде векторной строки — сжатого текстового представления значений, используемых для ее получения. Пример: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

component#

Хранение компонентов/пакетов программного обеспечения, для которых может существовать уязвимость.

Поле в таблице

Описание

purl

Package URL - cтандартизированный и универсальный способ идентификации пакетов и компонентов программного обеспечения. Пример: pkg:maven/org.apache.logging.log4j/log4j-core@2.17.1 (Maven-пакет log4j-core версии 2.17.1 из группы org.apache.logging.log4j)

cpe

Уникальный идентификатор платформы

ecosystem

Тип экосистемы, к которой принадлежит пакет (например, go)

package_name

Название уязвимого пакета

vendor

Производитель продукта

product

Продукт или библиотека

vulnerable_component#

Хранение связей между уязвимостью и компонентом, отражающих, какие версии компонента подвержены данной уязвимости.

Поле в таблице

Описание

normalized_raw_id

Идентификатор уязвимости в таблице normalized_raw_record

component_id

Идентификатор компонента в таблице component

version

Конкретная уязвимая версия

version_start_including

Указывает первую версию, которая включает данный уязвимый компонент. Эта версия является нижней границей диапазона то есть минимальная версия, включенная в диапазон. Например, когда с GitHub приходит поле {"vulnerable_version_range": " >=4.5.6"}, соответственно версия 4.5.6 включена в диапазон и является минимальной

version_start_excluding

Указывает нижнюю границу диапазона версий, которые подвержены уязвимости. Эта версия исключается из диапазона, что означает, что компоненты с этой версией и ниже не подвержены уязвимости. Например, когда с GitHub приходит поле {"vulnerable_version_range": "> 2.4.0-rc1.1, <= 2.11.2"}, соответственно версия 2.4.0-rc1.1 исключена из диапазона

version_end_including

Максимальная версия, включенная в диапазон. Например, когда с GitHub приходит поле {"vulnerable_version_range": "<=0.9.6"}, соответственно версия 0.9.6 включена в диапазон и является максимальной

version_end_excluding

Максимальная версия, исключенная из диапазона

vulnerable

Указывает, что данное программное обеспечение подвержено указанной уязвимости. Если это значение true, значит, версии, соответствующие критериям, имеют уязвимость

cvuln#

Хранение агрегированных уязвимостей, объединяющих информацию из разных источников.

Поле в таблице

Описание

title

Заголовок уязвимости

description

Полное агрегированное описание уязвимости

aggregated_cvss

Агрегированный показатель CVSS

affected_packages

Список затронутых пакетов

last_updated

Дата последнего обновления агрегированной уязвимости

aggregated_severity

Агрегированный уровень серьезности

provenance#

Хранение записей о происхождении нормализованных данных, вошедших в агрегированные уязвимости.

Поле в таблице

Описание

cvuln_id

Агрегированная уязвимость, в которую включена нормализованная запись

normalized_raw_id

Исходная нормализованная запись

merge_step

Этап дедупликации

confidence

Уровень уверенности алгоритма

fields_contributed

Поля, которые данный источник внес в агрегат

loading_track#

Хранение прогресса загрузки данных об уязвимостях из внешних источников.

Поле в таблице

Описание

source_name

Источник уязвимостей

last_published_at

Последнее успешно загруженное смещение (startIndex) из источника

last_start_index

Дата последней успешно загруженной уязвимости по дате публикации

last_modified_at

Дата последней успешно загруженной уязвимости по дате изменения

count_vulnerabilities

Количество загруженных уязвимостей

Интеграция с Dependency track#

Для поддержания внутренней базы Dependency track в актуальном состоянии, в Сервисе хранения единой базы уязвимостей реализована интеграция с Dependency track посредством API взаимодействия.

Диаграмма взаимодействия Dependency track с Cервисом хранения единой базы уязвимостей.

@startuml

skinparam BoxPadding 20
skinparam BoxMargin 2

box Источники данных #23A2D9
  database "NVD" as NVD
  database "OSV" as OSV
  database "GitHub Advisory" as GitHub
  database "FSTEK" as FSTEK
end box
box #LightBlue
  participant "Vulnerability Database Service" as VDS
  database "Database " as DB
end box

box #FFE4C4
  participant "Dependency-Track" as DT
  database "Database" as DTDB
end box

== Загрузка данных об уязвимостях ==

VDS -> NVD: GET https://services.nvd.nist.gov/rest/json/cves/2.0
NVD --> VDS: JSON-данные
VDS -> OSV: GET https://osv-vulnerabilities.storage.googleapis.com
OSV --> VDS: JSON-данные
VDS -> GitHub: POST https://api.github.com/graphql
GitHub --> VDS: GraphQL-ответ
VDS -> FSTEK: GET https://fstec.ru/upload/catalogs/vuln/xml.php?v=current
FSTEK --> VDS: XML-документ

group Обработка данных
  VDS -> VDS: Парсинг
  VDS -> VDS: Нормализация:\n- Пакеты → PURL\n- Версии → Semver
  VDS -> VDS: Агрегирование данных(дедупликация)
  VDS -> DB: Сохранение
end

loop
  DT -> DT: Запуск task для получения уязвимостей/обновлений \nс заданной периодичностью (каждые 24 часа)
  DT -> VDS: GET /v1/normalized-vulnerabilities?lastSync=2025-01-10T10:00:00\n&id=0xxc975a-exx6-4xxc-axx6-8xxcxxe2xx2a&size=2000
  VDS -> DB: Поиск уязвимостей
  VDS --> DT: JSON с уязвимостями
  
  group Обработка ответа
    DT -> DT: Обработка полученных данных
    DT -> DTDB: Сохранение уязвимостей
  end
end

@enduml