Книга «Безопасность контейнеров. Фундаментальный подход к защите контейнеризированных приложений»

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

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

В основном в этой книге обсуждаются контейнеры приложений, которые в настоящее время используют многие организации, чтобы запускать свои приложения в таких системах, как Kubernetes и Docker, а не контейнеры для систем наподобие LXC и LXD из проекта Linux Containers Project (https://linuxcontainers.org/). В контейнере приложений можно запускать неизменяемые контейнеры с помощью кода объемом не больше, чем требуется для запуска приложения. Наряду с этим в среде системного контейнера выполняется полный дистрибутив Linux, и работают с ним скорее как с виртуальной машиной. Вполне допустимо подключаться к системному контейнеру по SSH. Если же вы захотите подключиться по SSH к контейнеру приложений, то специалисты по их безопасности посмотрят на вас косо (по причинам, изложенным далее в этой книге). Впрочем, основные механизмы создания контейнеров для систем и приложений совпадают: контрольные группы, пространства имен и изменение корневого каталога. Так что фундамент, заложенный в данной книге, позволит вам и далее изучать разницу в подходах, которые используются в различных проектах контейнеров.

Угрозы безопасности контейнеров

За последние несколько лет масштабы применения контейнеров резко возросли. Соответствующие концепции контейнеров существовали еще за несколько лет до Docker. Но большинство наблюдателей сходятся во мнении, что именно появление в 2013 году Docker с его удобными в использовании утилитами командной строки дало толчок популярности контейнеров среди сообщества разработчиков.

У контейнеров есть множество достоинств. Как гласит рекламный слоган Docker, с их помощью можно «создать один раз, выполнять где угодно» — благодаря объединению в пакет приложения и всех его зависимостей и изоляции приложения от остальной части машины, на которой оно работает. У контейнеризованного приложения есть все необходимое, его легко можно упаковать в образ контейнера, который будет работать одинаково на моем/вашем ноутбуке и на сервере в центре обработки данных (ЦОД).

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

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

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

Риски, угрозы и уменьшение их последствий

Риск (risk) — это потенциальная проблема, а также ее возможные последствия.

Угроза (threat) — путь реализации этого риска.

Уменьшение их последствий (mitigation) — контрмеры, с помощью которых можно предотвратить угрозу или по крайней мере уменьшить вероятность ее успешной реализации.

Скажем, существует риск, что какой-нибудь злоумышленник украдет из вашего дома ключи от вашей же машины и уедет на ней. Угрозы в данном случае — это различные способы кражи ключей: разбить окно, запустить руку и схватить ключи; просунуть удочку через щель для почты; постучать в дверь и отвлечь вас, пока сообщник быстро проскользнет внутрь и схватит ключи. Чтобы уменьшить последствия всех этих угроз, можно, например, убрать ключи от машины с видного места.

Риски очень различаются в разных организациях. Основной риск для банка, хранящего клиентские деньги, — их кража. Для интернет-магазина основная головная боль — мошеннические транзакции. Ведущий личный блог пользователь может бояться, например, что кто-то взломает его учетную запись, выдаст себя за него и начнет публиковать непристойные комментарии. В разных странах законодательство о защите персональной информации имеет свои особенности, поэтому различается и риск утечки личных данных пользователей — во многих странах риски «лишь» репутационные, в то время как в Европе Общий регламент защиты персональных данных (General Data Protection Regulation, GDPR) допускает штрафы до 4 % общего дохода компании (https://oreil.ly/guQg3).

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

Моделирование угроз (threat modeling) — процесс распознавания и перечисления возможных угроз системе. За счет планомерного анализа ее компонентов и вероятных векторов атаки модель угроз помогает определить места системы, наиболее уязвимые для атак.

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

Модель угроз для контейнеров

В частности, модель угроз можно рассматривать с точки зрения ее участников, в число которых могут входить:

  • внешние нарушители (external attackers), пытающиеся извне получить доступ к развернутой системе;
  • внутренние нарушители (internal attackers), сумевшие получить доступ к некой части развернутой системы;
  • внутренние действующие лица-злоумышленники (malicious internal actors), например, разработчики и администраторы с определенным уровнем полномочий доступа к развернутой системе;
  • небрежные внутренние действующие лица (inadvertent internal actors), которые могут неумышленно вызывать проблемы;
  • процессы приложений (application processes) — не люди-злоумышленники, тем не менее имеющие определенный программный доступ к системе.
  • Необходимо учитывать набор прав доступа каждого из действующих лиц.

  • Какой доступ к системе есть у этого лица в соответствии с его учетными данными? Например, есть ли у него доступ к пользовательским учетным записям на машинах хостов, где работает развернутая система?
  • Какие права доступа оно имеет в системе? В Kubernetes этот пункт относится к настройкам управления доступом для всех пользователей, в том числе анонимных, на основе ролей.
  • Какие права доступа к сети есть у этого лица? Например, какие части системы включены в виртуальное частное облако (virtual private cloud, VPC)?
  • Существует несколько возможных путей атаки на развернутую контейнеризованную систему, и чтобы их систематизировать, можно, например, проанализировать потенциальные векторы атак на каждом из этапов жизненного цикла контейнера (рис. 1.1).

    Рассмотрим эти векторы более подробно.

  • Уязвимый код. Жизненный цикл приложения начинается с написания разработчиком его кода. Он, равно как и его зависимости, может содержать изъяны (уязвимости). Существуют списки из тысяч известных уязвимостей, которыми (если они есть в приложении) могут воспользоваться злоумышленники. Образы необходимо анализировать, как вы увидите в главе 7, чтобы не применять контейнеры с известными уязвимостями. Причем делать это нужно регулярно, поскольку уязвимости обнаруживаются в уже существующем коде постоянно. В процессе анализа должны также выявляться контейнеры с устаревшим ПО, которое необходимо обновить, установив исправления безопасности. Кроме того, есть анализаторы, способные выявлять встроенное в образы вредоносное программное обеспечение.
  • Плохо настроенные образы контейнеров. Написанный код встраивается в образ контейнера. В ходе конфигурации сборки образа контейнера возникает множество возможностей создать уязвимости, которые открывают дорогу для дальнейших атак на работающий контейнер. В их число входит выполнение контейнера от имени суперпользователя, в результате чего у него оказывается больше полномочий, чем нужно. Больше информации об этом — в главе 6.
  • Атаки на систему сборки. Если злоумышленник может изменить сборку образа контейнера или как-то повлиять на нее, то сможет вставить вредоносный код, который потом будет запущен в среде промышленной эксплуатации. Кроме того, возможность закрепиться внутри среды сборки — плацдарм для злоумышленника, позволяющий в дальнейшем проникать в среду промышленной эксплуатации. Этот вопрос также обсуждается в главе 6.
  • Атаки на цепь поставок. Собранный образ контейнера сохраняется в реестре, откуда извлекается перед запуском. Как гарантировать соответствие извлекаемого образа тому, который был ранее помещен в реестр? Не могли ли злоумышленники внести в него изменения? Любой, кто может заменить образ или модифицировать его в промежутке между сборкой и развертыванием, сможет выполнить любой код в развернутой системе.
  • Плохо настроенные контейнеры. Как мы обсудим в главе 9, контейнер можно запустить с настройками, в результате которых у них появляются ненужные, а порой и незапланированные полномочия. Скачивая файлы конфигурации YAML из Интернета, пожалуйста, не запускайте их, не убедившись в отсутствии в них небезопасных настроек!
  • Уязвимые хосты. Контейнеры выполняются на хост-компьютерах, поэтому нужно проверять работающий на них код на наличие уязвимостей (например, отслеживать старые версии компонентов механизма координации, с известными уязвимостями). Имеет смысл уменьшить до минимума объем запущенного на каждом хосте программного обеспечения, чтобы сократить поверхность атаки. Кроме того, необходимо задать правильную конфигурацию хостов в соответствии с практическими рекомендациями по обеспечению безопасности. Все это обсуждается в главе 4.
  • Общедоступные секретные данные. Чтобы взаимодействовать с другими компонентами системы, код приложения часто требует учетные данные, токены или пароли. При развертывании в контейнере эти секретные значения необходимо передавать в контейнеризованный код. Как вы увидите в главе 12, существует несколько различных вариантов решения этой задачи, имеющих разную степень безопасности.
  • Незащищенная сеть. Контейнерам обычно требуется взаимодействовать друг с другом или с окружающим миром. В главе 10 обсуждается передача данных по сети в контейнерах, а в главе 11 — установление защищенных соединений между компонентами.
  • Уязвимости выхода за рамки контейнера. Широко используемые среды выполнения контейнеров, включая containerd и CRI-O, уже хорошо проверены в деле, однако не исключено, что в них все же остаются программные ошибки, вследствие которых вредоносный код, работающий внутри контейнера, может просочиться за пределы контейнера, в хост. Одна из таких проблем — Runcescape (https://oreil.ly/cFSaJ) — обнаружилась в 2019 году. В главе 4 можно прочитать об изоляции, предназначенной для ограничения кода приложения рамками контейнера. Ущерб от выхода за рамки контейнера для ряда приложений может быть столь велик, что имеет смысл задуматься о применении более эффективных механизмов изоляции, таких как те, которые обсуждаются в главе 8.
  • Некоторые векторы атак выходят за рамки данной книги.

  • Исходный код обычно хранится в репозиториях, потенциально доступных для атак, цель которых — взлом приложения. Необходимо обеспечить должный контроль доступа пользователя к репозиторию.
  • Хост-компьютеры связываются между собой сетью, обычно подключенной к Интернету, причем в целях безопасности при этом часто применяется VPC. Как и при обычном развертывании, необходимо защитить хост-компьютеры (или виртуальные машины) от доступа злоумышленников. Безопасные настройки сети, использование брандмауэра, а также управление идентификацией и доступом для нативного облачного развертывания ничуть не менее релевантны, чем для обычного.
  • Контейнеры обычно работают под управлением механизма координации — в современных развертываниях его роль обычно играет Kubernetes, хотя есть и другие варианты, например Docker Swarm и Hashicorp Nomad. Недостаточная безопасность настроек средства координации или отсутствие должного контроля над доступом с правами администратора открывают злоумышленникам дополнительные векторы атак.
  • Больше информации о моделях угроз при развертываниях на основе Kubernetes можно найти в отчете «Модель угроз Kubernetes» (Kubernetes Threat Model) (https://bit.ly/3sg7aBn), заказанном CNCF.

    Кроме того, команда Financial User Group проекта CNCF опубликовала дерево атак Kubernetes (Kubernetes Attack Tree) (https://bit.ly/3mPGZR2), созданное на основе методологии STRIDE (https://oreil.ly/rNmPN).

    С полным содержанием статьи можно ознакомиться на сайте “Хабрахабр”:

    https://habr.com/ru/company/piter/blog/560602/

    Источник



    Leave A Reply

    Your email address will not be published.