Как своевременно обнаружить уязвимости?

Итак, вы создали Dockerfile, протестировали контейнер на рабочей станции разработки и ждете, когда он подцепится в CI/CD. Через какое-то количество времени промежуточная среда обновляется, интеграционные тесты успешно проходятся, а функциональные тестировщики дают добро на дальнейшие действия. Неужели настало время перейти в рабочую среду? Не спешите.

Наследование слоев Docker-образов

Каждый пакет файлов, добавленный в образ, создает свой слой, который также добавляется в образ. Сам же этот образ представляет собой объединение всех слоев в хронологическом порядке.

Тот же принцип действует и тогда, когда вы создаете образ, наследующий родительский образ, через директиву FROM в Dockerfile. В конечный образ попадают все слои из родительского образа, дополненные слоями, которые создавались непосредственно вами.

Но что, если ваш родительский образ и сам пользуется другим родительским образом, который, в свою очередь, наследуется от другого… и эта цепочка тянется вплоть до базового образа по типу Ubuntu или Alpine? Могу поспорить, вы и сами поняли, что к чему: конечный образ наследует множество слоев, файлов и исполняемых модулей, из родительских образов. Но вы про них ничего не знаете и никак ими не управляете.

Визуализация Docker-образа через Dive

Но вдруг в каком-то из этих слоев затесалась уязвимость по части безопасности? Мы еще поговорим об их выявлении, а пока давайте разберемся в том, что такое уязвимость безопасности.

Уязвимости безопасности

В левой верхней части рисунка вы видите несколько слоев. В правой части перечислены файлы, из которых состоит образ. Визуализация делалась в Dive. Многие из этих файлов являются исполняемыми. Поэтому, как и любой написанный код, такие файлы подвержены проблемам с безопасностью и уязвимостям.

Если бы это были файлы из вашей локальной файловой системы, то периодическая антивирусная проверка решила бы все проблемы. В некотором роде сам вирус можно рассматривать как уязвимость безопасности. Компьютерный вирус — это тип программы, которая при своем запуске реплицируется за счет изменения других программ и добавления собственного кода. Если репликация прошла успешно, то затронутые области считаются зараженными вирусом.

Но уязвимости безопасности  —  это не вирусы.

Зачастую такие уязвимости прячутся в хорошо написанном исходном коде с каким-то логическим или техническим изъяном, который ослабляет систему и использует ее для взлома. Такие уязвимости могут незаметно существовать годами, а затем обнаружиться в результате нацеленного поиска либо по счастливой случайности.

Базы данных уязвимостей

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

Существует множество хорошо зарекомендовавших себя баз данных уязвимостей, на которых можно открыто размещать информацию. Например, CVE, NVD и VULDB.

Статический анализ Docker-уязвимостей

Давайте вспомним следующее:

  • Docker-образ состоит из слоев с файлами и исполняемыми файлами.
  • Уязвимости EXE-файлов (или библиотек) в исходном коде публикуются в базах данных онлайн.

Что же мы получим, соединив эти знания? Сможем ли мы как-то сравнить исполняемые файлы наших слоев с перечнем уязвимостей из базы данных и понять, подвержен ли наш Docker-образ каким-либо из уже известных угроз? Давайте попробуем.

Anchore Engine

Существуют разные инструменты (платные и open-source) для проверки образов на известные уязвимости. Вы можете запускать эти инструменты как часть CI/CD (непрерывной интеграции и развертывания) либо подключать их к регистру образов и проверять новые образы по мере появления. Пример сканеров на уязвимости: Clair, Dadga, Nexus Repository Pro, Black Duck, Qualys, Harbor и Twistlock.

Для простоты и наглядности я покажу, как пользоваться Anchore. У Anchore есть платное (Anchore Enterprise) и бесплатное издание (Anchor Engine).

Anchore Engine: 1. Отправка нового образа -> CI/CD. Сборка образа контейнера -> Сертификация Anchore-контейнера (инспекция и анализ образа контейнера, оценка методов) -> Сертификация: пройдена/не пройдена -> Диспетчер контейнеров -> Оркестрация

Anchor имеет впечатляющую клиентскую базу, включающую в себя такие компании, как Cisco, eBay, Atlassian, Nvidia и RedHat. В платной версии предлагается дополнительный UI, RBAC и расширенная поддержка. Тем не менее эта версия базируется на бесплатном open-source издании Anchor Engine. Им мы и воспользуемся.

Установка

Anchore Engine поставляется в виде набора Docker-образов, которые можно запускать автономно либо на платформах оркестрации (Kubernetes, Docker Swarm, Rancher, Amazon ECS и т.д.). Вы можете быстро загрузить локальную версию Anchore Engine через Docker Compose и следующий однострочник:

curl https://raw.githubusercontent.com/anchore/anchore-engine/master/docker-compose.yaml | docker-compose -p anchore -f - up

Файл docker-compose.yaml создаст пять контейнеров, а затем попытается получить данные из базы уязвимостей, так что на завершение процесса может потребоваться несколько минут.

Запуск клиента

Anchor Engine доступен через консольного клиента. Для большего удобства можно запустить CLI-клиента через другой Docker-образ:

docker run --rm -e ANCHORE_CLI_URL=http://anchore_engine-api_1:8228/v1/ --network anchore_default -it anchore/engine-cli

Теперь у вас появилась оболочка для CLI-клиента Anchore. Сейчас мы выполним в ней тестовую команду, например, anchore-cli — version:

Консольный клиент в процессе работы

Проверка Docker-образа

Отчет по уязвимостям в Anchore Engine формируется в два этапа. Сначала вы добавляете образ для сканирования, а затем запрашиваете отчет по его уязвимостям, закладывая достаточное количество времени на скачивание и сканирование образа.

В примере ниже мы воспользуемся старым образом WordPress с известными уязвимостями.

Если вы решили использовать Docker на WordPress, то обязательно скачайте свежий образ.

Теперь давайте добавим наш первый Docker-образ через консольного клиента:

anchore-cli image add wordpress:4.6.0 && anchore-cli image wait wordpress:4.6.0

Этой командой мы добавляем новый образ для анализа и ждем подтверждения от Anchore о завершении сканирования.

Завершение анализа образа

Просмотр отчета по уязвимостям

Просмотреть найденные уязвимости можно по команде:

anchore-cli image vuln wordpress:4.6.0 all

В старых образах (например из примера выше) вполне может оказаться очень много уязвимостей. К слову, в 2016 году Anchore сообщило о 1420 найденных уязвимостях в нашем тестовом WordPress образе:

Anchore: отчет по уязвимостям

Как вы видите, инстанцирование Docker-контейнера из подобного образа — весьма рисковая затея. Если бы такой образ раздавался вместе с приложением, то вам пришлось бы заблокировать раздачу версии до проверки ее на уязвимости.

Заключение

Приложения (до сих пор!) пишут люди. А людям свойственно ошибаться. Пусть ваши ошибки не вредят Docker образам. Сканеры уязвимостей защитят вас от уже известных проблем с безопасностью. Сделайте сканирование на уязвимости неотъемлемой частью CI/CD и возьмите за правило блокировать раздачу версий при обнаружении проблем с безопасностью.

Читайте также:


Перевод статьи Nassos Michas: Scan Your Docker Images for Vulnerabilities

Предыдущая статьяПочему мы создаем инфраструктуру машинного обучения в Go, а не в Python
Следующая статьяУ приложений будущего может не быть бэкенда