Черная метка – как OpenShift защищает от уязвимости контейнеров с помощью SELinux

Бывало ли, что вы выполняли для блага общества непростую работу, а ваших усилий не замечали, потому что вы приносили пользу так долго, что все давно привыкли? Именно такую работу для вас совершают все участники сообщества SELinux.

lfxp34f04xcciggvd-ld8o8j7ac.png

И вот 18 февраля этого года, во многом благодаря их работе, мир был спасен от опасной поражающей контейнеры уязвимости CVE-2019–5736.
Хотя существуют и другие операционные системы, и другие проекты с открытым кодом, в которых применяется контроль по типам и категориям, редко бывает, когда все компоненты, настроенные с SELinux, включены «из коробки», по умолчанию и готовы к работе. Еще реже эта конфигурация охватывает все уровни, вплоть до решения для оркестрации контейнеров, на основе которого работает публичное облако.

В Red Hat OpenShift уже восемь лет используются такие механизмы принудительного контроля доступа Linux, как контроль по типам (type enforcement, TE) и мультикатегорийная безопасность (multi-category security, MCS). SELinux применяется в OpenShift с 2011 года. В Red Hat OpenShift Online — общедоступном хостинговом сервисе, где тысячи разработчиков ежедневно запускают код в виде контейнеров, — SELinux используется с самого начала. А что как насчет версии OpenShift, который используется, например в ЦОДе вашего любимого сотового оператора? На самом деле, модуль безопасности SELinux включен в Red Hat OpenShift Container Platform по умолчанию, бай дефолт! Причем не просто включен, а полностью настроен и готов защищать от реальных угроз.

В отличие от других дистрибутивов Kubernetes, Red Hat закрывает брешь между Linux и установленной поверх платформой оркестрации контейнеров. То есть Red Hat OpenShift отслеживает и устраняет угрозы безопасности по всему стеку, а не только в одном слое. И это делается по умолчанию — с первого дня работы.

OpenShift по умолчанию использует эту конфигурацию в Red Hat Enterprise Linux (вам даже необязательно знать что она там есть). Дело не ограничивается тем, чтобы запустить на ноутбуке setenforce 1. Правила контроля доступа по типам и категориям, которые арендатор применяет для работы с контейнерами на одном кластере Kubernetes, можно распространить на сотни узлов, которыми могут пользоваться тысячи других арендаторов.

Задумайтесь, как будет выглядеть конфигурация SELinux с MCS через несколько лет использования в крупной компании, которая раздает учетные данные OpenShift направо и налево. Теперь представьте, что вы предоставляете свои учетные данные для входа в ваш кластер OpenShift, как мы делаем это на openshift.com. Преданность SELinux часто не получает признания за все, что делает в решении OpenShift. Если вам кажется, что в наши дни операционная система уже не так важна, подумайте, а были ли вы защищены от уязвимости CVE-2019–5736 до этого февраля. В OpenShift защита от уязвимости CVE-2019–5736 применяется с самого начала и на это решение можно перейти уже сейчас.

SELinux ставит отметки


Одной из наиболее эффективных функций безопасности по умолчанию, реализованных в Red Hat OpenShift, является Security-Enhanced Linux (SELinux). SELinux — это модуль безопасности ядра Linux, обеспечивающий механизм принудительного контроля доступа на основе политик безопасности. Способ работы SELinux заключается в том, чтобы присваивать метки (имена) всем процессам и объектам операционной системы. Таким образом, каждый элемент, задействованный в операциях ядра, помечается и классифицируется, а затем ему предоставляется доступ на основе имеющегося набора правил.

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

Представим систему, в которой нужно определить типы для таких объектов, как кошки и собаки. Кошка и собака — это типы процессов.

p6fwedxevpd4bt1tplgm7_-stgo.png


* Автор всех рисунков — Майрин Даффи (Máirín Duffy)

Класс объектов, с которыми будут взаимодействовать процессы, — корм. Добавим типы корма: cat_chow и dog_chow (Ом-ном-ном).

ceyb-ioj32dnqpl62umrtylsoyg.png


Зададим для собаки разрешение есть собачий корм (dog_chow), а для кошки — кошачий (cat_chow). Запишем эти разрешения в виде правила политики SELinux:

allow cat cat_chow:food eat;
allow dog dog_chow:food eat;


_jrahfdtxvyx-ctmut1ta2nd2rk.png


По этим правилам процессу «кошка» будет на уровне ядра разрешено есть корм с меткой cat_chow, а собаке — корм с меткой dog_chow.

mv6dnihkvgs96hr9d_-ldnz7qom.png


Но мы помним, что в системе SELinux по умолчанию все запрещено. Поэтому если собака попытается съесть корм cat_chow, ядро не позволит этого сделать.

65zb6si0w3_eladgxlyqov5ne7w.png


Это и есть контроль по типам, который играет главную роль в защите хост-системы от контейнерных процессов. Контейнерные процессы могут читать и запускать только файлы из каталога /usr и записывать данные только в контейнерные файлы. Это ограничение надежно защищает хост от контейнеров, но не обеспечивает защиту одних контейнеров от других, ведь все они помечены одним типом. Чтобы защитить контейнеры друг от друга, потребуется внедрить контроль по меткам MCS.

MCS не тянет кота за хвост


Применение MCS не связано напрямую с защитой OpenShift от уязвимости CVE-2019–5736, но с этой темой полезно ознакомиться, чтобы лучше понимать принципы использования SELinux в OpenShift. Присвоение меток MCS с точки зрения пользователя или системного администратора происходит достаточно просто. Нужно всего лишь настроить набор категорий, представляющих собой простые текстовые метки (например, Fido или Spot), и добавить в них пользователей. Системный администратор сначала настраивает категории, а затем добавляет в них пользователей, после чего пользователи могут применять эти метки по своему усмотрению. Это удобно, так как MCS позволяет использовать стандартные метки SELinux для управления объектами. Снова обратимся к воображаемой системе из примера выше.

Добавим еще одну часть метки, которая будет применяться к процессу «собака» и корму dog_chow. Присвоим процессу «собака» метки dog: random1 (Fido) и dog: random2 (Spot).

twyq_lsws3els9cswdrlt8utnuc.png


Корму для собак присвоим метки dog_chow: random1 (Fido) и dog_chow: random2 (Spot).

jbgx7ujlwy2svpihnxbpygu4qsa.png


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

Попытки Fido (dog: random1) съесть корм cat_chow: food будут отклонены благодаря принудительному контролю по типу.

ztjwru8zama7leaffnnru7kuooy.png


Глубоко эшелонированная защита


Модуль безопасности SELinux, который применяется в OpenShift по умолчанию, — яркий пример глубоко эшелонированной защиты. В OpenShift, как и во многих других платформах на базе Kubernetes, используются политики SCC/PSP, запрещающие запускать контейнеры с правами root-пользователя. Это ограничение также защищает от уязвимости CVE-2019–5736. В OpenShift по умолчанию блокируются контейнеры, владельцем которых является root-пользователь, но этот параметр можно изменить. Даже если разрешить запускать контейнеры от имени root-пользователя, стандартная конфигурация SELinux в OpenShift все равно защищает от уязвимости CVE-2019–5736. Это еще один уровень защиты, который действительно оправдывает себя в данной ситуации и он в OpenShift далеко не единственный. Дополнительную информацию можно найти в документе 10 уровней контейнерной безопасности.

Дополнительную информацию об уязвимости CVE-2019–5736, в том числе о патче Red Hat Enterprise Linux для среды выполнения контейнеров, можно найти в отзыве Red Hat на уязвимость.

© Habrahabr.ru