
Приоритизация уязвимостей является важным этапом, входе которого необходимо оценить риск и последовательность устранения уязвимостей в приоритете - от самого критического до самого низкого риска.
В предыдущей статье я описывал визуализацию уязвимостей с помощью Budibase, в этой статье я опишу собственную реализацию оценки приоритетности устранения уязвимостей и добавлю функционал на Budibase платформу.
При устранении уязвимостей существуют несколько проблем:
Большое количество уязвимостей разного риска на разных активах.
Отсутствие единого способа понять, что приоритетно, так как опираться только на риск по CVSS не всегда является правильным решением и пентесты это доказывают.
Невозможность оперативно устранить уязвимость, ввиду непродуманных процессов разработки приложения или, в принципе отсутствие поддержки вендора в данном вопросе.
Теория и метрики приоритета
После сканирования на уязвимости необходимо проанализировать результат и задать приоритет устранения уязвимостей. На самом деле если обновления проводятся постоянно, то большинство уязвимостей будет устранено без особых усилий.
Но бывают ситуации, когда необходимо посмотреть конкретные уязвимости и оценить риск. В случае невозможности оперативного устранения, подумать о компенсирующих мерах. Например, в случае SQL инъекции в веб приложении, которое невозможно обновить оперативным образом, следует рассмотреть вариант использования WAF как компенсирующей меры, проверив наличие сигнатуры под данную уязвимость.
Для оценки я сделал интерфейс в Budibase который позволяет оценить приоритетные уязвимости в количественном масштабе и выгрузить для коллег список в .csv формате.


Приведу основные метрики по которым создавал фильтры:
Время публикации уязвимости - чем дольше живает уязвимость, тем больше вероятность появления эксплойта и эксплуатации в будущем, с другой стороны больше компенсирующих мер и патчей. А если уязвимость появилась вчера, то не стоит ожидать, что коллеги ее тоже устранят "вчера". Я сделал фильтр, отсеивать уязвимости младше X дней.
Значимость актива - насколько актив значим, если к нему получат доступ.
Расположение актива - позволит оценить простоту эксплуатации из неконтролируемых сетей, а так же возможности компенсирующих мер с учетом расположения средств защиты. Эту метрику я объединил со значимостью выше, и все активы на периметре помечал как важные.
Трендовость уязвимости - означает эксплуатируется ли данная уязвимость активно в данный момент. Если имеется информация с оценкой от вендора сканера уязвимостей или оценка от threat intelligence, то можно задать такой параметр.
Вектор эксплуатации - это метрики CVSS(локально/удаленно).
Наличие эксплойта - имеется готовый эксплойт под уязвимость.
Критичность уязвимости - оценка того насколько уязвимость критична согласно базовым метрикам CVSS.
Наличие исправления - наличие обновлений от вендора, устраняющих уязвимость.
Реализация фильтров приоритезации в Budibase
Основная идея заключалась в том, что бы при изменении любого из параметров фильтра, автоматически обновлялись дашборды и данные, которые позже смогут выгрузить коллеги, ответственные за обновления.
В Budibase фильтрация происходит через фильтр, значение которого с помощью привязки(binding) в качестве переменной передается в условие SQL запроса. Переменные задаются в параметрах элемента графика. А вот так например выглядят сами bindings на изображении в центре.

В запросе SQL они фиксируются между двумя скобками {{ var }}
в нужном месте. Таким образом получается полноценный SQL запрос.

Сам SQL-запрос создаётся во вкладке Data, внутри раздела подключения к СУБД.

Там же задаются bindings для SQL-запроса и значения по умолчанию - на случай, если фильтр пуст или ничего не выбрано. Эти условия также должна учитывать логика самого SQL-запроса.

Примеры SQL запросов с приоритизацией для построения дашбордов
Приведу несколько примеров SQL-запросов для построения дашбордов с учётом фильтров приоритизации.
Дашборд 1 - Топ 10 уязвимых активов
SELECT
COUNT(hostname) AS total, hostname
FROM mat_allassets
WHERE osname ILIKE '%windows 20%' AND status = 'new' AND VulnerabilityIssueTime < CURRENT_DATE - {{days}}::interval AND (
CASE
WHEN {{ sev }}::text IS NULL THEN TRUE
ELSE severity = {{ sev }}::text
END ) AND (
CASE
WHEN {{expltbl}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text
END ) AND (
CASE
WHEN {{netvector}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text
END ) AND (
CASE
WHEN {{remedy}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text
END ) AND (
CASE
WHEN {{vulntrend}}::bool IS NULL THEN TRUE
ELSE VulnerIsTrend = '{{vulntrend}}'::text
END ) AND (
CASE
WHEN {{hostimport}}::text IS NULL THEN TRUE
ELSE HostImportance = '{{hostimport}}'::text
END )
GROUP BY hostname
ORDER BY total DESC
LIMIT 10;
Дашборд 2 - Топ 10 уязвимых сервисов
SELECT
COUNT(hostname) AS total, VulnerableEntity || ' ' || VulnerableEntityVersion AS VulnerableObject
FROM mat_allassets
WHERE osname ILIKE '%windows 20%' AND VulnerableEntity IS NOT NULL AND status = 'new' AND VulnerabilityIssueTime < CURRENT_DATE - {{days}}::interval AND (
CASE
WHEN {{ sev }}::text IS NULL THEN TRUE
ELSE severity = {{ sev }}::text
END ) AND (
CASE
WHEN {{expltbl}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text
END ) AND (
CASE
WHEN {{expltbl}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text
END ) AND (
CASE
WHEN {{netvector}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text
END ) AND (
CASE
WHEN {{remedy}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text
END ) AND (
CASE
WHEN {{vulntrend}}::bool IS NULL THEN TRUE
ELSE VulnerIsTrend = '{{vulntrend}}'::text
END ) AND (
CASE
WHEN {{hostimport}}::text IS NULL THEN TRUE
ELSE HostImportance = '{{hostimport}}'::text
END )
GROUP BY VulnerableObject
ORDER BY total DESC
LIMIT 10;
Дашборд 3 - Топ 10 активных CVE
SELECT
COUNT(DISTINCT hostname) AS total, cve
FROM mat_allassets
WHERE osname ILIKE '%windows 20%' AND status = 'new' AND cve IS NOT NULL AND VulnerabilityIssueTime < CURRENT_DATE - {{ days }}::interval AND (
CASE
WHEN {{ sev }}::text IS NULL THEN TRUE
ELSE severity = {{ sev }}::text
END ) AND (
CASE
WHEN {{expltbl}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE 'Exploitable: {{expltbl}}%'::text
END ) AND (
CASE
WHEN {{netvector}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE '%HasNetworkAttackVector: {{netvector}}%'::text
END ) AND (
CASE
WHEN {{remedy}}::bool IS NULL THEN TRUE
ELSE metrics ILIKE '%HasFix: {{remedy}}%'::text
END ) AND (
CASE
WHEN {{vulntrend}}::bool IS NULL THEN TRUE
ELSE VulnerIsTrend = '{{vulntrend}}'::text
END ) AND (
CASE
WHEN {{hostimport}}::text IS NULL THEN TRUE
ELSE HostImportance = '{{hostimport}}'::text
END )
GROUP BY cve
ORDER BY total DESC
LIMIT 10;
Что в итоге получилось
В итоге получился достаточно простой, но эффективный инструмент, позволяющий подсветить наиболее проблемные активы и сервисы с учётом наиболее опасных уязвимостей и выгрузить их.
Вывод: даже если у вас нет бюджета на дорогую VM-платформу, это не означает, что вы не можете приоритизировать уязвимости правильно. Более того, не все современные VM-решения позволяют настраивать приоритизацию так гибко, как того требует конкретная инфраструктура.
В следующей статье я расскажу об EPSS, покажу, как реализовать его в Budibase, и добавлю функционал для выгрузки списка приоритетных уязвимостей.
Будет интересно узнать, используете ли вы приоритизацию уязвимостей в своей работе? Как отслеживаете проблемные активы?