Конкурс: Встречаем 2020 статьями по инфобезу
Тысяча и одна уязвимость. Проводим аудит безопасности GNU/Linux «на лету»
Всем привет!
Не так давно по долгу службы я столкнулся с необходимостью проведения «моментальных» аудитов безопасности машин, работающих на операционных системах Debian-based Linux. Целью таких процедур, которые должны были проводиться регулярно на разных хостах (не обязательно объединенных в одну локальную сеть), было выявление уязвимых версий установленных в системе пакетов по открытым базам данных. В силу определенных обстоятельств некоторая часть ПО, крутящегося в системах, не всегда могла быть обновлена достаточно оперативно, поэтому основным назначением аудита должен был стать своеобразный «алерт» о нависшей угрозе, что делать с которой уже решали специально обученные люди.
Сообщество знает целую галактику способов проведения подобных чек-ап'ов, однако бо́льшая часть из них предполагает развертывание громоздких программных комплексов, которые постоянно мониторят текущую обстановку. Чаще всего это связано с тем фактом, что там, где такие автоматизированные аудиты безопасности в принципе нужны, они нужны на постоянной основе в режиме реалтайма. Напротив, если речь заходит о более «портативных» сканерах уязвимостей, то в этой ситуации спектр существующих решений заметно сужается: основная их часть представляет из себя самописные (на коленке) скрипты, ориентированные на какую-то одну базу данных (чаще всего
Немного погуляв по сети в надежде отыскать что-то достойное моих самодурских прихотей и не найдя ничего, что удовлетворило бы меня полностью, я не придумал ничего лучше, чем пополнить этот список любительских скриптов своим творением. О том, как я написал простой и удобный враппер для набирающего популярность агрегатора ИБ-контента
Vulners — база данных уязвимостей
Основой для будущего сканера было решено выбрать крупную базу данных уязвимостей
Более подробно о том, почему это так круто, можно прочитать на
«То что нужно!» — в итоге воскликнул я и закопался в изучение существующих инструментов, использующих Vulners в качестве своей базы знаний.
Далеко ходить не потребовалось — сам агрегатор предлагает ряд программных продуктов для упрощения работы со своей БД, в том числе:
По всему вышеперечисленному я набросал свой скрипт, которым поделюсь с вами в следующем параграфе.
vul5can.py [vulskΛn]
Итак, для начала синопсис в виде help'а, и тезисный список того, чем отличается (помимо ума и сообразительности) мой сканер.
Отличительные особенности:
Пример 1.
Сперва «чистый» запуск (по умолчанию, без дополнительных опций).
Визуально вывод можно разделить на 3 части:
Данные об установленных в системе пакетах передаются от утилиты
Формат, требуемый API Vulners (и часть вывода
Идем дальше.
С помощью флагов
Здесь я добавил флаг
Пример 2. Удаленный репозиторий
С помощью флага
Флаг
Я добавил флаг
В этом же примере посмотрим, что из себя представляют более расширенные результаты сканирования.
Если я повторю предыдущую команду с флагом
Двойной флаг
Также можно посмотреть, какие конкретно веб-запросы делает сканер через Burp, если потребуется отладить скрипт. Для этого установи две переменные окружения (
Однако следует помнить, что в этом случае vul5can слепо доверяет SSL-сертификату, так как конечная точка API живет на HTTPS, и Burp, как человек-по-середине, вынужден вклиниться со своим незвестным никому (особенно питоновскому интерпретатору) сертификатом (ох уж этот Burp!).
Пример 3. Удаленный файл
Если значение аргумента для параметра
Аналогично, если я предварительно скачаю этот архив на свою машину, то я просто смогу указать путь до него в
Пример 4. Stealth-режим
В случае, когда нежелательно оставлять какие-либо следы своего присутствия на просканированной машине, удобно использовать опцию
Тогда файл с настройками не будет создан, а API-ключ будет спрашиваться в интерактивном режиме каждый раз при запуске сканера. В этом же примере я использовал флаг
Если ты работаешь не в stealth-режиме, и тебе хотелось бы изменить дефолтное расположение файла конфигураций и логов (по умолчанию —
Этим действием я инициировал запись
Пример 5. Бесконтактная доставка
В завершающем примере посмотрим, почему для меня было важным уместить весь код в один исходник. Все просто: при таком раскладе я могу загружать скрипт с удаленного сервера и выполнять его без сохранения на жесткий диск сканируемого хоста.
Предположим, что исходник сканера доступен мне по адресу
Только тс-с-с-с, нас здесь не было... Кстати, то же самое можно сделать с помощью
В заключение
Вот такая игрушка получилась, надеюсь читать было интересно. Разумеется, самый главный минус такого подхода к аудиту безопасности в том, что информация об установленных в системе пакетах ходит в интернеты (в своем профиле на Vulners можно даже
Сам скрипт находится
Take care!
Тысяча и одна уязвимость. Проводим аудит безопасности GNU/Linux «на лету»
Всем привет!
Не так давно по долгу службы я столкнулся с необходимостью проведения «моментальных» аудитов безопасности машин, работающих на операционных системах Debian-based Linux. Целью таких процедур, которые должны были проводиться регулярно на разных хостах (не обязательно объединенных в одну локальную сеть), было выявление уязвимых версий установленных в системе пакетов по открытым базам данных. В силу определенных обстоятельств некоторая часть ПО, крутящегося в системах, не всегда могла быть обновлена достаточно оперативно, поэтому основным назначением аудита должен был стать своеобразный «алерт» о нависшей угрозе, что делать с которой уже решали специально обученные люди.
Сообщество знает целую галактику способов проведения подобных чек-ап'ов, однако бо́льшая часть из них предполагает развертывание громоздких программных комплексов, которые постоянно мониторят текущую обстановку. Чаще всего это связано с тем фактом, что там, где такие автоматизированные аудиты безопасности в принципе нужны, они нужны на постоянной основе в режиме реалтайма. Напротив, если речь заходит о более «портативных» сканерах уязвимостей, то в этой ситуации спектр существующих решений заметно сужается: основная их часть представляет из себя самописные (на коленке) скрипты, ориентированные на какую-то одну базу данных (чаще всего
Ссылка скрыта от гостей
нацеленная на эксплуатацию найденных брешей).Немного погуляв по сети в надежде отыскать что-то достойное моих самодурских прихотей и не найдя ничего, что удовлетворило бы меня полностью, я не придумал ничего лучше, чем пополнить этот список любительских скриптов своим творением. О том, как я написал простой и удобный враппер для набирающего популярность агрегатора ИБ-контента
Ссылка скрыта от гостей
, я расскажу далее.Vulners — база данных уязвимостей
Основой для будущего сканера было решено выбрать крупную базу данных уязвимостей
Ссылка скрыта от гостей
от российских разработчиков. Этот проект включает в себя обширную коллекцию сведений об уязвимостях систем на базе Linux и предлагает RESTful API для удобного взаимодействия с последней. Одной из ключевых особенностей проекта является возможность проведения «удаленного» аудита безопасности Linux-хоста.Более подробно о том, почему это так круто, можно прочитать на
Ссылка скрыта от гостей
, а мы вернемся к моей истории.«То что нужно!» — в итоге воскликнул я и закопался в изучение существующих инструментов, использующих Vulners в качестве своей базы знаний.
Далеко ходить не потребовалось — сам агрегатор предлагает ряд программных продуктов для упрощения работы со своей БД, в том числе:
- vulners-scanner – Proof-of-Concept аудита безопасности Linux, демонстрирующий возможности API Vulners.com;
- vulners-agent – агент для Linux-сервера, позволяющий проводить сканирование по планировщику cron;
- nmap-vulners – NSE-скрипт для Nmap, позволяющий выявить угрозы безопасности, исходя из информации, полученной от сервисов, которые запущенны на открытых портах исследуемого хоста;
- api – средство разработчика, представляющее из себя враппер веб-API Vulners.com в виде подключаемого модуля для Python (доступен для установки через PyPI).
- Первый сканер, как я понимаю, является форком Python-приложения от стороннего разработчика (репозиторий, к слову, на данный момент находится в архиве, и более не поддерживется автором), которое попросту отказалось заводиться, когда я в первый раз решил посмотреть, что оно умеет. Немного повозившись, я решил траблы с запуском, но мне категорически не понравился вывод скрипта. В довесок ко всему прочему проект состоит из нескольких исходников, что, разумеется, улучшает структуру кода, но идет в разрез с моим представлением об идеальной портативности: я хотел иметь возможность использовать скрипт также и для редтим-мероприятий, где лучшим вариантом является отказ от сохранения наступательного кода на жесткий диск (бесконтактная доставка боевой нагрузки, об этом далее).
- Агент для сервера выглядит очень интересно, но тащит за собой тонну зависимостей, поэтому сразу нет — мне не хотелось выходить за рамки стандартной библиотеки Python.
- По этой же причине, к сожалению, пришлось отказаться от готового питоновского API для Vulners. Мне была нужна всего пара POST-запросов, и тянуть ради этого целый
requests
(который требует API), я посчитал кощунством.
По всему вышеперечисленному я набросал свой скрипт, которым поделюсь с вами в следующем параграфе.
vul5can.py [vulskΛn]
Итак, для начала синопсис в виде help'а, и тезисный список того, чем отличается (помимо ума и сообразительности) мой сканер.
Код:
usage: vul5can.py [-h] [--os OS] [--os-version OS_VERSION] [-j] [-a] [-q]
[-s SOURCE] [--arch ARCH] [--config-path CONFIG_PATH]
[--log-path LOG_PATH] [--stealth] [--valid-api-key]
[-v | -r]
optional arguments:
-h, --help show this help message and exit
--os OS OS type
--os-version OS_VERSION
OS version
-j, --json return output as JSON
-a, --all also include vulnerable packages associated only with
DSA (and not with CVE)
-q, --quiet supress progress messages
-s SOURCE, --source SOURCE
remote repository, URI or a local file containing
repository packages
--arch ARCH "amd64" | "i386" (default: "amd64")
--config-path CONFIG_PATH
path to the directory where you would like vul5can.py
to save configuration file
--log-path LOG_PATH path to the directory where you would like vul5can.py
to save log files
--stealth do not save configuration and log files to disk
--valid-api-key validate Vulners.com API key before calling audit
endpoint
-v, --verbose increase verbosity level (use -vv or more for greater
effect)
-r, --raw return raw API output
- Как все уже поняли, сканер написан на Питоне и требует интерпретатор версии >= 3.5. Я специально не стал использовать «f-строки», поддержка которых появилась только в Python 3.6 (хотя в некоторых местах их применение сделало бы код весьма более лаконичным). Внешние зависимости не требуются, только стандартная библиотека.
- Софтина умещается в один файл исходного кода, что позволяет не тревожить жесткий диск подопытного хоста, и запускать проверку «на лету» (если есть такая необходимость), используя редирект результата загрузки через пайп прямо в bash.
- Сканер умеет вести логи, а свои настройки (включая чувствительную информацию в виде API-ключа Vulners) хранит в отельном файле. Это может быть удобным для планирования сканирования по cron.
- Поддерживается stealth-режим, когда никаких следов (логи, файл конфигурации) на машине не остается.
- В качестве входных данных могут использоваться, как простые текстовые файлы (локальные / на удаленных ресурсах; сжатые с помощью
gzip
), так и вывод команды dpkg-query, если скрипт запускается прямо на сканируемом хосте.
Пример 1.
dpkg-query
Сперва «чистый» запуск (по умолчанию, без дополнительных опций).
Код:
$ ./vul5can.py
Визуально вывод можно разделить на 3 части:
- баннер и служебная информация;
- информационные сообщения о статусе проводимого сканирования;
- результат сканирования.
Ссылка скрыта от гостей
) среди всех идентификаторов
Ссылка скрыта от гостей
, которые ассоциированы с данной уязвимостью. Информативность вывода можно расширить verbosity-флагами -v/-vv
, что я покажу чуть позже.Данные об установленных в системе пакетах передаются от утилиты
dpkg-query
таким запросом.
Код:
$ dpkg-query -W -f='${Status} ${Package} ${Version} ${Architecture}\n'|awk '($1 == "install") && ($2 == "ok") {print $4" "$5" "$6}'
dpkg-query
по совместительству) представлен ниже.
Код:
acl 2.2.53-5 amd64
adduser 3.118 all
adwaita-icon-theme 3.34.0-2 all
aircrack-ng 1:1.5.2-3+b1 amd64
alsa-tools 1.1.7-1 amd64
amass 3.3.1-0kali1 amd64
amass-common 3.3.1-0kali1 all
amd64-microcode 3.20191021.1 amd64
apache2 2.4.41-1 amd64
apache2-bin 2.4.41-1 amd64
apache2-data 2.4.41-1 all
apache2-utils 2.4.41-1 amd64
apparmor 2.13.3-7 amd64
apt 1.8.4 amd64
...
Код:
$ ./vul5can.py --os-version 10 -jq
С помощью флагов
-j
(--json
) и -q
(-quiet
) соответственно можно сгенерировать output в формате JSON и подавить весь остальной вывод на экран, чтобы перенаправить результат сканирования в файл или через пайп другой утилите (к примеру, JSON-процессору
Ссылка скрыта от гостей
, что продемонстрировано ниже). Флаг --os-version
отвечает за версию сканируемого дистрибутива, который можно выбрать опцией --os
(по умолчанию debian
).
Код:
$ ./vul5can.py --os-version 10 -qaj | jq
Здесь я добавил флаг
-a
(--all
), чтобы расширить результат сканирования пакетами, для которых не существует номеров CVE (только бюллетени Debian), и перенаправил JSON-вывод jq
.Пример 2. Удаленный репозиторий
С помощью флага
-s
(--source
) можно задать источник получения входных данных. Так как API требует всего лишь список пакетов в текстовом виде, вовсе не обязательно запускать сканер «изнутри» сканируемого хоста. К тому же, иногда это попросту неудобно.Флаг
-s
понимает 3 вида аргументов:- Удаленный (http, https, ftp) deb-репозиторий.
Ссылка скрыта от гостейтакой же, как в файле
/etc/apt/sources.list
на твоей машине — начинается со словаdeb
, дальше URI, потом название дистрибутива и список компонентов (через пробел) в конце. - Удаленный (http, https, ftp) файл, содержащий список установленных пакетов в нужном формате. Можно использовать как обычный текстовый файл, так и gz-архив.
- Локальный файл, содержащий список установленных пакетов в нужно формате. Можно использовать как обычный текстовый файл, так и gz-архив.
Код:
$ ./vul5can.py --os ubuntu --os-version 18.04 -s "deb http://ru.archive.ubuntu.com/ubuntu/ bionic main restricted" --arch i386
Я добавил флаг
--arch
, чтобы выбрать 32-битную архитектуру (по дефолту — amd64
). Красным выделен список файлов, которые скрипт забирает для сканирования.В этом же примере посмотрим, что из себя представляют более расширенные результаты сканирования.
Код:
$ ./vul5can.py --os ubuntu --os-version 18.04 -s "deb http://ru.archive.ubuntu.com/ubuntu/ bionic main restricted" --arch i386 -v
Если я повторю предыдущую команду с флагом
-v
(--verbose
), то для каждого уязвимого пакета будет отображаться список идентификаторов CVE, которые тем или иным образом относятся к его «слабости».
Код:
$ ./vul5can.py --os ubuntu --os-version 18.04 -s "deb http://ru.archive.ubuntu.com/ubuntu/ bionic main restricted" --arch i386 -vv
Двойной флаг
-vv
еще больше расширит вывод, включив в него информацию о бюллетенях безопасности Debian.Также можно посмотреть, какие конкретно веб-запросы делает сканер через Burp, если потребуется отладить скрипт. Для этого установи две переменные окружения (
HTTP_PROXY
и HTTPS_PROXY
), равными адресу локального прокси-сервера and you're good to go!Однако следует помнить, что в этом случае vul5can слепо доверяет SSL-сертификату, так как конечная точка API живет на HTTPS, и Burp, как человек-по-середине, вынужден вклиниться со своим незвестным никому (особенно питоновскому интерпретатору) сертификатом (ох уж этот Burp!).
Пример 3. Удаленный файл
Если значение аргумента для параметра
-s
начинается с названия протокольной схемы (http, https, ftp), то сканер может дергать отдельные удаленные файлы. Покажем это на примере сканирования списка пакетов, устанавливаемых в анонимной ОС Tails v3.14.2.
Код:
$ ./vul5can.py -s "https://deb.tails.boum.org/dists/3.14.2/main/binary-amd64/Packages.gz"
Аналогично, если я предварительно скачаю этот архив на свою машину, то я просто смогу указать путь до него в
-s
и сканер прочитает локальный файл.
Код:
$ wget https://deb.tails.boum.org/dists/3.14.2/main/binary-amd64/Packages.gz
$ ./vul5can.py -s Packages.gz
Пример 4. Stealth-режим
В случае, когда нежелательно оставлять какие-либо следы своего присутствия на просканированной машине, удобно использовать опцию
--stealth
.
Код:
$ ./vul5can.py --stealth --valid-api-key
Тогда файл с настройками не будет создан, а API-ключ будет спрашиваться в интерактивном режиме каждый раз при запуске сканера. В этом же примере я использовал флаг
--valid-api-key
для валидации API-ключа на Vulners (выполняется дополнительный POST-запрос).Если ты работаешь не в stealth-режиме, и тебе хотелось бы изменить дефолтное расположение файла конфигураций и логов (по умолчанию —
~/.config/vul5can/
), пользуйся --config-path
и --log-path
.
Код:
$ ./vul5can.py --quiet --config-path . --log-path .
Этим действием я инициировал запись
vul5can.ini
в текущий каталог, а значение настройки path_to_log
внутри этого файла поменялась с дефолтной (~/.config/vul5can/log/
) на CWD.Пример 5. Бесконтактная доставка
В завершающем примере посмотрим, почему для меня было важным уместить весь код в один исходник. Все просто: при таком раскладе я могу загружать скрипт с удаленного сервера и выполнять его без сохранения на жесткий диск сканируемого хоста.
Предположим, что исходник сканера доступен мне по адресу
127.0.0.1:31337/vul5can.py
. Тогда с помощью curl
(или wget
) я могу сделать следующее.
Код:
$ curl -s 127.0.0.1:31337/vul5can.py | python3 - -avv --stealth --valid-api-key
Только тс-с-с-с, нас здесь не было... Кстати, то же самое можно сделать с помощью
wget
.
Код:
$ wget -qO- 127.0.0.1:31337/vul5can.py | python3 - -avv --stealth --valid-api-key
Вот такая игрушка получилась, надеюсь читать было интересно. Разумеется, самый главный минус такого подхода к аудиту безопасности в том, что информация об установленных в системе пакетах ходит в интернеты (в своем профиле на Vulners можно даже
Ссылка скрыта от гостей
статистику сканирования). Для тех, кому такой вариант по каким-либо причинам не подходит, Vulners позволяет аккумулировать собственную БД, загружая информацию о публичных CVE локально. Поэтому, думаю, что и в этом случае можно выкрутиться.Сам скрипт находится
Ссылка скрыта от гостей
.Take care!