company_banner

Системы защиты Linux

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

    Предыстория Linux Security Modules и SELinux


    Security Enhanced Linux представляет собой набор правил и механизмов доступа, основанный на моделях мандатного и ролевого доступа, для защиты систем Linux от потенциальных угроз и исправления недостатков Discretionary Access Control (DAC) — традиционной системы безопасности Unix. Проект зародился в недрах Агентства Национальной Безопасности США, непосредственно разработкой занимались, в основном, подрядчики Secure Computing Corporation и MITRE, а также ряд исследовательских лабораторий.


    Linux Security Modules

    Линус Торвальдс внес ряд замечаний о новых разработках АНБ, с тем, чтобы их можно было включить в основную ветку ядра Linux. Он описал общую среду, с набором перехватчиков для управления операциями с объектами и набором неких защитных полей в структурах данных ядра для хранения соответствующих атрибутов. Затем эта среда может использоваться загружаемыми модулями ядра для реализации любой желаемой модели безопасности. LSM полноценно вошел в ядро Linux v2.6 в 2003 году.

    Фреймворк LSM включает защитные поля в структурах данных и вызовы функций перехвата в критических точках кода ядра для управления ими и выполнения контроля доступа. Он также добавляет функции для регистрации модулей безопасности. Интерфейс /sys/kernel/security/lsm содержит список активных модулей в системе. Хуки LSM хранятся в списках, которые вызываются в порядке, указанном в CONFIG_LSM. Подробная документация по хукам включена в заголовочный файл include/linux/lsm_hooks.h.

    Подсистема LSM позволила завершить полноценную интеграцию SELinux той же версии стабильного ядра Linux v2.6. Буквально сразу же SELinux стал стандартом де-факто защищенной среды Linux и вошел в состав наиболее популярных дистрибутивов: RedHat Enterprise Linux, Fedora, Debian, Ubuntu.

    Глоссарий SELinux


    • Идентичность — Пользователь SELinux не то же самое, что и привычный Unix/Linux user id, они могут сосуществовать на одной и той же системе, но совершенно различны по сути. Каждая стандартная учетная запись Linux может соответствовать одному или нескольким в SELinux. Идентичность SELinux является составной частью общего контекста безопасности, который определяет в какие домены можно входить, а в какие — нельзя.
    • Домены — В SELinux домен является контекстом выполнения субъекта, т. е. процесса. Домен напрямую определяет доступ, который имеет процесс. Домен — это в основном список того, что могут делать процессы или какие действия процесс может выполнять с разными типами. Некоторые примеры доменов: sysadm_t для системного администрирования, и user_t, который является обычным непривилегированным доменом пользователя. Система инициализации init запускается в домене init_t, а процесс named запускается в домене named_t.
    • Роли — То, что служит посредником между доменами и пользователями SELinux. Роли определяют, в каких доменах может состоять пользователь и к каким типам объектов он сможет получить доступ. Подобный механизм разграничения доступов предотвращает угрозу осуществить атаку повышения привилегий. Роли вписаны в модель безопасности Role Based Access Control (RBAC), используемой в SELinux.
    • Типы — Атрибут списка Type Enforcement, который назначается объекту и определяет, кто получит к нему доступ. Похоже на определение домена, за исключением того, что домен применяется к процессу, а тип применяется к таким объектам, как каталоги, файлы, сокеты и т. д.
    • Субъекты и объекты — Процессы являются субъектами и запускаются в определенном контексте, или домене безопасности. Ресурсы операционной системы: файлы, директории, сокеты и пр., являются объектами, которым ставится в соответствие определенный тип, иначе говоря — уровень секретности.
    • Политики SELinux — Для защиты системы SELinux использует разнообразные политики. Политика SELinux определяет доступ пользователей к ролям, ролей — к доменам и доменов — к типам. В начале пользователь авторизуется для получения роли, далее роль авторизуется для доступа к доменам. Наконец домен может иметь доступ лишь к некоторым типам объектов.

    LSM и архитектура SELinux


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


    Стек проверок LSM

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

    SELinux перенял архитектуру безопасности Flask исследовательской операционной системы Fluke, в частности принцип наименьших привилегий. Суть этой концепции, как следует из их названия, в предоставлении пользователю или процессу лишь тех прав, которые необходимы для осуществления предполагаемых действий. Данный принцип реализован с помощью принудительной типизации доступа, таким образом контроль допусков в SELinux базируется на модели домен => тип.

    Благодаря принудительной типизации доступа SELinux имеет гораздо более значительные возможности по разграничению доступа, нежели традиционная модель DAC, используемая в ОС Unix/Linux. К примеру, можно ограничить номер сетевого порта, который будет случать ftp сервер, разрешить запись и изменения файлов в определенной папке, но не их удаление.

    Основные компоненты SELinux таковы:

    • Policy Enforcement Server — Основной механизм организации контроля доступа.
    • БД политик безопасности системы.
    • Взаимодействие с перехватчиком событий LSM.
    • Selinuxfs — Псевдо-ФС, такая же, как /proc и примонтированная в /sys/fs/selinux. Динамически заполняется ядром Linux во время выполнения и содержит файлы, содержащие сведения о статусе SELinux.
    • Access Vector Cache — Вспомогательный механизм повышения производительности.


    Схема работы SELinux

    Все это работает следующим образом.

    1. Некий субъект, в терминах SELinux, выполняет над объектом разрешенное действие после DAC проверки, как показано не верхней картинке. Этот запрос на выполнение операции попадает к перехватчику событий LSM.
    2. Оттуда запрос вместе с контекстом безопасности субъекта и объекта передается на модуль SELinux Abstraction and Hook Logic, ответственный за взаимодействие с LSM.
    3. Инстанцией принятия решения о доступе субъекта к объекту является Policy Enforcement Server и к нему поступают данные от SELinux AnHL.
    4. Для принятия решения о доступе, или запрете Policy Enforcement Server обращается к подсистеме кэширования наиболее используемых правил Access Vector Cache (AVC).
    5. Если решение для соответствующего правила не найден в кэше, то запрос передается дальше в БД политик безопасности.
    6. Результат поиска из БД и AVC возвращается в Policy Enforcement Server.
    7. Если найденная политика согласуется с запрашиваемым действием, то операция разрешается. В противном случае операция запрещается.

    Управление настройками SELinux


    SELinux работает в одном из трех режимов:

    • Enforcing — Строгое соблюдение политик безопасности.
    • Permissive — Допускается нарушение ограничений, в журнале делается соответствующая пометка.
    • Disabled — Политики безопасности не действуют.

    Посмотреть в каком режиме находится SELinux можно следующей командой.

    [admin@server ~]$ getenforce
    Permissive

    Изменение режима до перезагрузки, например выставить на enforcing, или 1. Параметру permissive соответствует числовой код 0.

    [admin@server ~]$ setenforce enforcing
    [admin@server ~]$ setenforce 1 #то же самое
    

    Также изменить режим можно правкой файла:

    [admin@server ~]$ cat /etc/selinux/config

    # This file controls the state of SELinux on the system.
    # SELINUX= can take one of these three values:
    # enforcing - SELinux security policy is enforced.
    # permissive - SELinux prints warnings instead of enforcing.
    # disabled - No SELinux policy is loaded.
    SELINUX=enforcing
    # SELINUXTYPE= can take one of three values:
    # targeted - Targeted processes are protected,
    # minimum - Modification of targeted policy. Only selected processes are protected.
    # mls - Multi Level Security protection.

    SELINUXTYPE=targeted


    Разница с setenfoce в том, что при загрузке операционный системы режим SELinux будет выставлен в соответствии со значением параметра SELINUX конфигурационного файла. Помимо того, изменения enforcing <=> disabled вступают в силу только через правку файла /etc/selinux/config и после перезагрузки.

    Просмотреть краткий статусный отчет:

    [admin@server ~]$ sestatus

    SELinux status: enabled
    SELinuxfs mount: /sys/fs/selinux
    SELinux root directory: /etc/selinux
    Loaded policy name: targeted
    Current mode: permissive
    Mode from config file: enforcing
    Policy MLS status: enabled
    Policy deny_unknown status: allowed
    Max kernel policy version: 31

    Для просмотра атрибутов SELinux некоторые штатные утилиты используют параметр -Z.

    [admin@server ~]$ ls -lZ /var/log/httpd/
    -rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log
    -rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20200920
    -rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20200927
    -rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20201004
    -rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20201011
    [admin@server ~]$ ps -u apache -Z
    LABEL                             PID TTY          TIME CMD
    system_u:system_r:httpd_t:s0     2914 ?        00:00:04 httpd
    system_u:system_r:httpd_t:s0     2915 ?        00:00:00 httpd
    system_u:system_r:httpd_t:s0     2916 ?        00:00:00 httpd
    system_u:system_r:httpd_t:s0     2917 ?        00:00:00 httpd
    ...
    system_u:system_r:httpd_t:s0     2918 ?        00:00:00 httpd

    По сравнению с обычным выводом ls -l тут есть несколько дополнительных полей следующего формата:

    <user>:<role>:<type>:<level>

    Последнее поле обозначает нечто вроде грифа секретности и состоит из комбинации двух элементов:

    • s0 — значимость, также записывают интервалом lowlevel-highlevel
    • c0, c1… c1023 — категория.

    Изменение конфигурации доступов


    Используйте semodule, чтобы загружать модули SELinux, добавлять и удалять их.

    [admin@server ~]$ semodule -l |wc -l #список всех модулей
    408
    [admin@server ~]$ semodule -e abrt #enable - активировать модуль
    [admin@server ~]$ semodule -d accountsd #disable - отключить модуль
    [admin@server ~]$ semodule -r avahi #remove - удалить модуль

    Первая команда semanage login связывает пользователя SELinux с пользователем операционной системы, вторая выводит список. Наконец последняя команда с ключом -r удаляет связку отображение пользователей SELinux на учетные записи ОС. Объяснение синтаксиса значений MLS/MCS Range находится в предыдущем разделе.

    [admin@server ~]$ semanage login -a -s user_u karol
    [admin@server ~]$ semanage login -l

    Login Name SELinux User MLS/MCS Range Service
    __default__ unconfined_u s0-s0:c0.c1023 *
    root unconfined_u s0-s0:c0.c1023 *
    system_u system_u s0-s0:c0.c1023 *
    [admin@server ~]$ semanage login -d karol

    Команда semanage user используется для управления отображений между пользователями и ролями SELinux.

    [admin@server ~]$ semanage user -l
                    Labeling   MLS/       MLS/                          
    SELinux User    Prefix     MCS Level  MCS Range             SELinux Roles
    guest_u         user       s0         s0                    guest_r
    staff_u         staff      s0         s0-s0:c0.c1023        staff_r sysadm_r
    ...
    user_u          user       s0         s0                    user_r
    xguest_u        user       s0         s0                    xguest_r
    [admin@server ~]$ semanage user -a -R 'staff_r user_r'
    [admin@server ~]$ semanage user -d test_u

    Параметры команды:

    • -a добавить пользовательскую запись соответствия ролей;
    • -l список соответствия пользователей и ролей;
    • -d удалить пользовательскую запись соответствия ролей;
    • -R список ролей, прикрепленных к пользователю;

    Файлы, порты и булевы значения


    Каждый модуль SELinux предоставляет набор правил маркировки файлов, но также можно добавить собственные правила для в случае необходимости. Например мы желаем дать веб серверу права доступа к папке /srv/www.

    [admin@server ~]$ semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
    [admin@server ~]$ restorecon -R /srv/www/

    Первая команда регистрирует новые правила маркировки, а вторая сбрасывает, вернее выставляет, типы файлов в соответствии с текущими правилами.

    Аналогично, TCP/UDP порты отмечены таким образом, что лишь соответствующие сервисы могут их прослушивать. Например, для того, чтобы веб-сервер мог прослушивать порт 8080, нужно выполнить команду.

    [admin@server ~]$ semanage port -m -t http_port_t -p tcp 8080

    Значительное число модулей SELinux имеют параметры, которые могут принимать булевы значения. Весь список таких параметров можно увидеть с помощью getsebool -a. Изменять булевы значения можно с помощью setsebool.

    [admin@server ~]$ getsebool httpd_enable_cgi
    httpd_enable_cgi --> on
    [admin@server ~]$ setsebool -P httpd_enable_cgi off
    [admin@server ~]$ getsebool httpd_enable_cgi
    httpd_enable_homedirs --> off
    

    Практикум, получить доступ к интерфейсу Pgadmin-web


    Рассмотрим пример из практики, мы установили на RHEL 7.6 pgadmin4-web для администрирования БД PostgreSQL. Мы прошли небольшой квест с настройкой pg_hba.conf, postgresql.conf и config_local.py, выставили права на папки, установили из pip недостающие модули Python. Все готово, запускаем и получаем 500 Internal Server error.



    Начинаем с типичных подозреваемых, проверяем /var/log/httpd/error_log. Там есть некоторые интересные записи.

    [timestamp] [core:notice] [pid 23689] SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
    ...
    [timestamp] [wsgi:error] [pid 23690] [Errno 13] Permission denied: '/var/lib/pgadmin'
    [timestamp] [wsgi:error] [pid 23690]
    [timestamp] [wsgi:error] [pid 23690] HINT : You may need to manually set the permissions on
    [timestamp] [wsgi:error] [pid 23690] /var/lib/pgadmin to allow apache to write to it.


    На этом месте у большинства администраторов Linux возникнет стойкое искушение запустить setenforce 0, да и дело с концом. Признаться, в первый раз я так и сделал. Это конечно тоже выход, но далеко не самый лучший.

    Несмотря на громоздкость конструкций SELinux может быть дружественным к пользователю. Достаточно установить пакет setroubleshoot и просмотреть системный журнал.

    [admin@server ~]$ yum install setroubleshoot
    [admin@server ~]$ journalctl -b -0
    [admin@server ~]$ service restart auditd


    Обратите внимание на то, что сервис auditd необходимо перезапускать именно так, а не с помощью systemctl, несмотря на наличие systemd в ОС. В системном журнале будет указан не только факт блокировки, но также причина и способ преодоления запрета.



    Выполняем эти команды:

    [admin@server ~]$ setsebool -P httpd_can_network_connect 1
    [admin@server ~]$ setsebool -P httpd_can_network_connect_db 1


    Проверяем доступ на веб страницу pgadmin4-web, всё работает.



    RUVDS.com
    VDS/VPS-хостинг. Скидка 10% по коду HABR

    Комментарии 8

      +10

      SELinux — это позорное пятно в безопасности Linux. Стоит хотя бы упомянуть, что реализация большинства инструментов в SELinux — это хромые поделия, в которых даже сами мантейнеры SELinux с трудом разбираются (зайдите, к примеру, на их github и посмотрите код mcstransd). Кроме этого, в SELinux есть два параллельных языка для написания политик безопасности, при этом в некоторых местах у них конфликтуют даже ключевые слова (то, что в одном называется typeattribute в другом записывается typeattributeset или как-то так). Систему категорий, кстати, практически забросили и пользуются ей только для разграничения виртуальных машин, хотя потенциал был (и есть) гигантский. Добавьте к этому, что в пользовательских дистрибутивах пользователи толком не могут защититься с помощью SELinux (адекватного UI и адекватной политики до сих пор нет, большая часть бинарников имеет одинаковый контекст безопасности), то Linux уже и не кажется правильным решениям для защищенного пользовательского десктопа.

        +1

        И что Вы порекомендуете для RBAC как альтернативу? Мне вот нравился вариант из GrSecurity, но он теперь для простых смертных недоступен.

          +2

          Вот мне бы тоже было бы интересно про альтернативы. AppArmor думаю не подходит, SMACK заброшен (слабо развивается в рамках Tizen и Automotive Linux), ещё знаю, что в российских дистрибутивах есть какие-то свои разработки, но там не совсем про контроль доступа, либо тот же MAC.

            +4

            А что конкретно не так с AppArmor? Я просто так и не нашёл пока время его поковырять, так что вопрос без подвоха, просто любопытно.

              0

              Правила для довольно просто пишутся, кстати. Во всяком случае, лет восемь назад это было так.

              0
              Интересно, какой RBAC они:
              github.com/anthraxx/linux-hardened
              docs.clip-os.org/clipos/kernel.html#configuration
              применяют?

              Насколько я понял такое же anthraxx ядро используется и в Whonix, это уже почти Debian, т.е. теоретически наверно даже можно перетащить такое в Devuan без systemD:
              phabricator.whonix.org/T998
              ?
          +4
          В заголовке «системы» во множественном числе, но рассматривается только SELinux
            +2
            SELinux неудобный. Эта технология не оптимизирована и морально устаревшая, чтобы заниматься без «напрягов» обеспечением безопасности. К тому же примеры привел бы какие-нибудь дельные. Как модуль безопасности написать для своего софта, а не просто копировать то, что валяется на просторах интернета ~10 лет.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое