Введение в SELinux: модификация политики targeted для сторонних веб-приложений

    Привет, коллеги!
    Многие из нас занимаются настройкой рабочих серверов для веб-проектов. Я не буду рассказывать о том, как настроить Apache или Nginx: вы знаете об этом больше меня. Но один важный аспект создания frontend-серверов остается неосвещенным: это настройки подсистем безопасности. «Отключите SELinux», — вот стандартная рекомендация большинства любительских руководств. Мне кажется, что это поспешное решение, ибо процесс настройки подсистем безопасности в режиме «мягкой» политики чаще всего весьма тривиален.

    Сегодня я расскажу вам о некоторых методах настройки подсистемы безопасности SELinux, применяемой в семействе операционных систем Red Hat (CentOS). В качестве примера мы настроим связку для веб-сервера Apache + mod_wsgi + Django + ZEO на CentOS версии 5.8.



    При настройке систем безопасности Linux мы скованы рамками системы избирательного управления доступом (Discretionary Access Control, DAC). В нашем распоряжении стандартные права rwx на трех уровнях (владелец, группа-владелец и остальные) и POSIX ACL. Таким образом, приложение с правами user теоретически имеет доступ ко всем ресурсам, доступным соответствующему пользователю. В случае компрометации приложения это может привести к печальным последствиям.

    SELinux (Security-Enhanced Linux) — это подсистема безопасности, которая реализует мандатное управление доступом (Mandatory Access Control, MAC), работающее параллельно с классической дискреционной системой. Права доступа при этом определяются системой при помощи политик. В семействе операционных систем Red Hat (CentOS) вы получаете SELinux «из коробки», в качестве части ядра. Для простейшего решения поставленных задач нам потребуется политика targeted («целевая»), в рамках которой описаны правила для основной массы типовых приложений. Мы получаем базовую защиту основных сервисов без дополнительных усилий. Правила политики таковы, что все не описанные в ней приложения будут работать без ограничений со стороны SELinux в рамках DAC.

    «Но зачем, собственно, нам нужен этот SELinux?» — спросите вы. Ответ довольно прост: в ряде случаев подсистема безопасности позволит как минимум запротоколировать несанкционированный доступ, а в идеале — предотвратить его. В любом случае, нарушителю придется действовать в рамках, очерченных для конкретного процесса.



    Для добавления собственных настроек мы будем оперировать контекстами, доменами и векторами доступа. События, имеющие значение с точки зрения безопасности, перехватываются SELinux на уровне ядра. Механизмы подсистемы безопасности вступают в действие после правил DAC. SELinux предоставляет возможности RBAC (Role-Based Access Control), TE (Type Enforcement) и, опционально, MLS (Multi-Level Security). Каждый объект системы имеет определенный контекст (тип). На основе правил политики подсистема безопасности либо позволяет выполнение данной операции, либо блокирует его, — и процесс получает сообщение об ошибке. Все принятые SELinux решения кэшируются в Access Vector Cache (AVC).

    Контекст SELinux содержит информацию о пользователе, роли, типе и уровне. Мы будем оперировать типом, являющимся атрибутом Type Enforcement. Он определяетcя доменом для процессов и типом для файлов. В правилах SELinux описаны разрешенные типы взаимодействия. Доступ разрешается только в случае наличия соответствующего правила.

    Отдельно хотелось бы отметить технологию доменных переходов. В SELinux переход приложения из одного домена в другой возможен, если процесс из исходного домена выполняет приложение, которое запускается из файла с типом entrypoint нового домена.

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

    Итак, при реализации шаблонных решений отказ от использования защитного механизма SELinux по меньшей мере не обоснован. Отдельные трудности при его использовании возникают при установке дополнительного программного обеспечения. В контексте поставленной задачи таковыми являются модуль mod_wsgi и ZEO. Для сохранения работоспособности SELinux нам потребуется внести изменения в его настройки.

    В своем примере я использую CentOS 5.8 (kernel 2.6.18-308.1.1.el5) с веб-сервером Apache (httpd-2.2.3-63.el5.centos.1). На него дополнительно установлены из исходных кодов Python (2.7.2), Django (1.4), mod_wsgi (3.3) и Zope (3.4.0). (Прозаичный процесс установки данного программного обеспечения не заслуживает отдельного описания.)

    Прежде всего нам потребуется расширить политику SELinux для httpd. Настройки по умолчанию предназначены для надежной изоляции процесса в случае его компрометации. Однако для доступа httpd к вашему проекту потребуется внести некоторые изменения. Авторами политики заложена полная логика работы приложения с ограничениями по контексту. Ознакомиться с разметкой файлов в вашей системе поможет простая команда:

    semanage fcontext -l | grep httpd


    Политика регламентирует доступ к каждому из представленных типов. Ознакомиться с полным перечнем контекстов можно на соответствующей man-странице (man httpd_selinux). Нас интересует тип httpd_sys_content_t, который разрешает демону и сценариям доступ к файлам. Таким образом, помимо стандартных прав DAC необходимо задать контекст директории и файлов вашего проекта. Это можно сделать единовременно при помощи команды chcon.

    chcon -R -t "httpd_sys_content_t" /your/project


    Однако я рекомендую задать тип при помощи правила. Это обеспечит последующее автоматическое присвоение типа при добавлении новых файлов.

    semanage fcontext -a -t httpd_sys_content_t "/your/project(/.*)?"
    restorecon -R /your/project
     


    Мой демонстрационный проект использует Django с базой данных ZoDB. В качестве средства для коммуникации с БД используется ZEO. Так как это самостоятельное ПО, необходимо обеспечить его функционирование в рамках SELinux. Для обеспечения изоляции целесообразно, как я полагаю, осуществить запуск ZEO с правами пользователя apache в домене httpd_t. Для этого определим сценарий инициализации запуска в режиме демона. Я не стану приводить здесь листинг всего сценария ввиду его большого размера. Нам будет достаточно главного:

    /usr/local/bin/zeoctl -d -s /var/run/zeo/zsock -C /etc/zeo/zeoctl.conf start


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

    chcon –t "initrc_exec_t" /etc/init.d/your_init_script


    В конфигурационном файле необходимо указать необходимого пользователя.

    <runner>
    program /usr/local/bin/runzeo -a /var/run/zeo/zeo.socket -f /var/your_db_path/db.fs
    daemon True
    user  apache
    </runner>
     


    В качестве связующего звена между ZEO и Django используется сокет. Поскольку httpd работает в домене httpd_t, необходимо согласовать типы и DAC-права таким образом, чтобы приложение могло к нему подключиться. Для этого мы подготовим директорию /var/run/zeo и зададим для нее необходимый контекст. Мы используем ключ -f -s, для того чтобы ограничить автоматическое присвоение контекста только сокетами, а также -f -d — чтобы контекст установился на директорию.

    semanage fcontext -a -f -d -t 'httpd_sys_script_rw_t' '/var/run/zeo(/.*)?'
    semanage fcontext -a -f -s -t 'httpd_sys_script_rw_t' '/var/run/zeo(/.*)?'
    restorecon –R /var/run


    В конфигурационном файле ZEO необходимо указать принудительное расположение коммуникационного сокета.

    <zeo>
    address /var/run/zeo/zeo.socket
    </zeo>


    Поскольку мы планируем запуск приложения от имени пользователя apache, необходимо учесть транзитивность типов. Нам нужно, чтобы запущенный процесс получил тип httpd_t. По умолчанию файлы /usr/local/bin/zeoctl и /usr/local/bin/runzeo будут иметь контекст bin_t. Поскольку они будут вызываться из домена unconfined_t, то необходимо проследить цепочку переходов контекстов. Прежде всего будет вызван сценарий из /etc/init.d/, которому мы присвоили тип initrc_exec_t. Найдем цепочку переходов для этой ситуации.

    sesearch -T -s unconfined_t -t initrc_exec_t | grep " initrc_exec_t"


    Найденная цепочка перехода выглядит как unconfined_t initrc_exec_t: process initrc_t. Мы видим, что процесс получит контекст initrc_t. Соответственно, теперь нам нужно обнаружить цепочку переходов, которая приведет нас к необходимому типу httpd_t.

    sesearch -T -s initrc_t | grep "process httpd_t"


    Результатом поиска будет связь initrc_t httpd_exec_t: process httpd_t. Для того чтобы произошел данный переход, нам следует установить контекст httpd_exec_t на исполняемые файлы.

    semanage fcontext -a -t httpd_exec_t "/usr/local/bin/zeoctl"
    semanage fcontext -a -t httpd_exec_t "/usr/local/bin/runzeo"
    restorecon -R /usr/local/bin


    Теперь нам нужно добавить в политику SELinux разрешения на подключение к сокету для httpd. Это можно сделать несколькими способами. Самый простой с точки зрения пользователя — это утилита audit2allow, позволяющая формировать модули для политики на основе AVC-сообщений из системных журналов. Пользоваться утилитой следует осторожно, поскольку она лишь создает разрешения для определенных действий — но не более того (подробное руководство представлено на сайте разработчиков).

    Вторым путем будет создание модуля вручную, его компиляция и установка в текущую политику. Поскольку данный способ дает лучшую визуализацию процесса, мы изготовим модули для ZEO именно так. Предоставим httpd_t права на создание и работу с сокетом, имеющим тип httpd_sys_script_rw_t. Для этого создадим файл /tmp/httpdAllowDjangoZEO.te со следующим содержанием:

    module httpdAllowDjangoZEO 1.0;
     
    require {
            type httpd_t;
            type httpd_sys_script_rw_t;
            class sock_file link;
            class sock_file setattr;
            class sock_file create;
            class sock_file unlink;
            class sock_file write;
    }
    #============= httpd_t ==============
    allow httpd_t httpd_sys_script_rw_t:sock_file link;
    allow httpd_t httpd_sys_script_rw_t:sock_file setattr;
    allow httpd_t httpd_sys_script_rw_t:sock_file create;
    allow httpd_t httpd_sys_script_rw_t:sock_file unlink;
    allow httpd_t httpd_sys_script_rw_t:sock_file write;


    Далее нам необходимо создать и скомпилировать модуль. Для этого воспользуемся командами checkmodule и semodule_package. Для инсталляции модуля в текущую политику нам потребуется утилита semodule.

    checkmodule -M -m -o /tmp/httpdAllowDjangoZEO.mod /tmp/httpdAllowDjangoZEO.te
    semodule_package --outfile /tmp/httpdAllowDjangoZEO.pp --module /tmp/httpdAllowDjangoZEO.mod
    semodule -i httpdAllowDjangoZEO.pp
     


    Финальным действием будет настройка контекстов места хранения базы данных ZoDB и конфигурационного файла ZEO. Нам в процессе работы потребуется создавать технические файлы .lock. Следовательно, место хранения БД необходимо разметить соответствующим контекстом, который будет позволять создание файлов. Для этого хорошо подойдет «httpd_sys_script_rw_t».

    semanage fcontext –a –t «httpd_sys_script_rw_t» “/var/your_db_path(/.*)?”


    Для конфигурационных файлов существует специализированный тип «httpd_config_t».

    semanage fcontext –a –t « httpd_config_t» “/etc/zeo(/.*)?”


    Теперь достаточно перезапустить сервисы для окончания процесса настройки.

    Написанные нами правила позволят всей связке работать без проблем. При этом мы обеспечиваем сервер и его службы дополнительной защитой SELinux. В случае компрометации какого-либо из компонентов Django или ZEO злоумышленник будет ограничен и не сможет добраться до системы, поскольку будет действовать в рамках домена httpd_t.

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

    Для более целостного понимания технологии SELinux я рекомендую вам ознакомиться с русскоязычным описанием SELinux для Fedora 13.
    Positive Technologies
    213.64
    Company
    Share post

    Comments 32

      0
      При чем тут лейбл Oracle Enterprise Linux?
      P.S. за статью спасибо, почитаем.
        0
        Ох, прошу простить. Ипользовал его только для визуализации «защищенности» линукса.
        Мне показалась уместным такая картинка.
          +2
          Вот исторический лейбл SELinux.
          Если серьезно, то в основном (только?) им занимается именно компания RedHat.
            +1
            Я не рискнул его вешать. Боялся быть непонятым.
            Вообще, SELinux доступен и для других систем.
            Насколько я помню, его успешно интегрируют в Gentoo.
              0
              По-моему, он так же успешно используется в OpenSUSE.
                0
                По умолчанию Novell используют AppArmor, но уже появились альтернативные версии с SELinux.
            0
            Вы слишком вольно относитесь к визуализаци. Например, это касается и вашей аватарки. Насколько я понимаю, вы никакого отношения к RH не имеете. Вести корпоративный блог, используя на аватаре чужую торговую марку несколько… не красиво.
          +4
          процесс настройки подсистем безопасности в режиме «мягкой» политики чаще всего весьма тривиален

          Пробежав взглядом статью и отложив его в favorites всё-таки не могу согласиться, что описанное выше является «весьма тривиальным».
            +2
            Каждый раз когда читаю в доках «Отключите SELinux» мне хочется стукнуть по голове чем-нибудь больным, чтоб у человека появилось желание разбираться, а не бездумно отрубать всё незнакомое.
              0
              Типичный подход. Имеет некий аналог и на другой известной платформе.
                0
                Получилось несколько двусмыслено. Я скорее осуждаю такой подход неосилятора.
                +1
                появилось желание разбираться

                Боюсь, что когда он начнет разбираться с SELinux, то в итоге стукнет себя чем-нибудь по голове сам :)

                P.S. Я SELinux не отключаю если что :)
                +2
                Спасибо за хорошую статью, надеюсь пригодится в жизни.
                  +2
                  Спасибо. Очень хорошая статья.
                  Про AppArmor будете писать?
                  Я, помнится, именно AppArmor юзал для защиты веб. Результат был отличным 8)
                  Не претендую на достоверность, но по моему аппармор для тех же задач настраивается проще/удобнее.
                  + там есть «обучалка». Про SELinux не знаю. Было бы интересно сравнить их…
                    +1
                    Спасибо.
                    Не планировал, но если наберется достаточно запросов, то могу.
                    Задача сравнения довольно трудоемкая, но реализуемая.
                      0
                      Очень бы хотелось. Но похоже мало нас :(
                        0
                        Действительно мало. Я о него споткнулся когда у меня самба отказалась работать на сусе, долго не мог понять почему для рута permission denied (в логах). Но потом проникся идеей использования :)
                        По мне, так в apparmor можно разобраться практически интуитивно, чего не скажешь про selinux прочитав статью :)
                      0
                      audit2allow и есть «обучалка». Она генерирует разрешающий конфиг по отлупам в логе аудита.
                        0
                        Ах, если Вы это имели ввиду, то да.
                        Но я бы рекомендовал научиться писать модули политики самостоятельно.
                        Для понимания, что же происходит.
                          0
                          Гм, она скорее нужна для того, что бы быстро понять что «тянет и дергает» процесс, типа что ему нужно для счастья.
                            +1
                            Тогда, для Red Hat более верное решение это setroubleshoot [доступен через стандартный yum].
                            Это приложение, позволяющее анализировать AVC сообщения.
                            Оно выдает развернутый human-readable отчет, по какой причине высветилась ошибка.
                            Так же в отчете будет представлена команда, разрешающая данное взаимодействие.

                            audit2allow же, в свою очередь, позволяет создавать модули для политики на основе тех же AVC. Но довольно часто это не требуется.

                            Типовая проблема проблема при работе с SELinux это несоответствие контекстов.

                            Как и говорил ранее, я тем не менее рекомендую вникать в проблему и стараться разрешить ее наиболее корректными с точки зрения концепции методами.
                              0
                              Конечно надо вникать, я с вами не спорю. Это вообще святое правило =) Так то и strace можно юзать 8)

                              P.S.
                              AppArmor после обучения выдает человеко-читаемые конфиги. В чем собственно мой поинт и был, что он поудобнее по настройке (на мой взгляд)… просто я с SLES работал, мне было удобно юзать то что дали =) С Ред Хатом не работал в этом направлении, так что не знаю… может я не прав.
                          0
                          audit2allow — это жуткий костыль. Вместо введения нового домена предлагается напихать allow в существующие. Применять его конечно можно, но если уж так, то лучше, пожалуй, начать свой путь с dummy policy, в обратном порядке (%
                        0
                        image
                          –1
                          SELinux — как safe_mode в php. Никто его не любит, все его отключают, половина софта не работает из коробки, архитектурно выглядит, как неустойчивая дырявая куча if-ов, распиханных по всему коду (где-то забытых при этом). В php 5.4 вон одумались, убрали safe_mode…

                          Вся прелесть стандарных bsd-шных прав доступа — в их простоте (кстати, даже эта простота обманчива, ведь есть множественные членства в группах). Это перекрывает даже недостатки от их неуниверсальности. В сравнении с ACL-ом, которые в ntfs (и поддерживаются в ext3+ тоже, кстати) — небо и земля.

                          Все IMHO.
                            +1
                            Ой, да ладно. RBAC права простому пользователю понять гораздо проще, чем комбинаторный взрыв членства в группах.

                            ext3+ не поддерживает NT ACL-ы (в смысле сама ФС может хранить что угодно — благо наконец появились расширенные атрибуты, а вот драйвер файловой системы — никакими подобными проверками не занимается). BSD и XNU — поддерживают подмножество.
                            0
                            Мне кажется Вы не вполне верно понимаете значение терминов MAC и DAC (например, во всей статье Вы ни разу не использовали ни одной возможности MAC, хотя и задекларировали преимущество MAC во вступлении). SELinux — это не о преимуществах MAC перед DAC (на пользовательской машине таких преимуществ в общем то нет), это о преимуществах fine grained DAC (хоть и достаточно криво реализованного) над классическими юниксовыми триплетами (да что угодно лучше этого).

                            Что же до POSIX ACLs — они мало того, что были задепрекейчены самими авторами еще 15 лет назад, так еще и не поддерживаются в линуксе (в смысле там конечно есть что-то, что называется POSIX ACLs, но это не те же самые POSIX ACLs, которые были в черновике 1003.1e, хотя и очень близкие к нему).
                              0
                              А что же тогда такое MAC, если не централизованный fine grained DAC?
                                +1
                                Оранжевая книга определяет DAC как (взял из «B1», где впервые встречаются и DAC и MAC):
                                3.1.1.1 Discretionary Access Control

                                The TCB shall define and control access between named users and
                                named objects (e.g., files and programs) in the ADP system.
                                The enforcement mechanism (e.g., self/group/public controls,
                                access control lists) shall allow users to specify and control
                                sharing of those objects by named individuals, or defined groups
                                of individuals, or by both, and shall provide controls to limit
                                propagation of access rights. The discretionary access control
                                mechanism shall, either by explicit user action or by default,
                                provide that objects are protected from unauthorized access.
                                These access controls shall be capable of including or excluding
                                access to the granularity of a single user. Access permission
                                to an object by users not already possessing access permission
                                shall only be assigned by authorized users.


                                А MAC вот так:
                                3.1.1.4 Mandatory Access Control

                                The TCB shall enforce a mandatory access control policy over
                                all subjects and storage objects under its control (e.g.,
                                processes, files, segments, devices). These subjects and
                                objects shall be assigned sensitivity labels that are a
                                combination of hierarchical classification levels and
                                non-hierarchical categories, and the labels shall be used as
                                the basis for mandatory access control decisions. The TCB
                                shall be able to support two or more such security levels.
                                (See the Mandatory Access Control Guidelines.) The following
                                requirements shall hold for all accesses between subjects and
                                objects controlled by the TCB: a subject can read an object
                                only if the hierarchical classification in the subject's
                                security level is greater than or equal to the hierarchical
                                classification in the object's security level and the non-
                                hierarchical categories in the subject's security level include
                                all the non-hierarchical categories in the object's security
                                level. A subject can write an object only if the hierarchical
                                classification in the subject's security level is less than or
                                equal to the hierarchical classification in the object's
                                security level and all the non-hierarchical categories in the
                                subject's security level are included in the non-hierarchical
                                categories in the object's security level. Identification
                                and authentication data shall be used by the TCB to authenti-
                                cate the user's identity and to ensure that the security level
                                and authorization of subjects external to the TCB that may be
                                created to act on behalf of the individual user are dominated
                                by the clearance and authorization of that user.


                                То есть TCSEC (который в общем то и популяризовал эти термины) определяет MAC просто как MLS (Белл-ЛаПадула, который АБСОЛЮТНО бесполезен домашнему пользователю, как впрочем и подавляющему большинству серверов в отличие от, скажем, контроля целостности по Биба).

                                Надо признать, что трактовка весьма узкая, но самая широкая трактовка, из всех что я когда либо видел, просто утверждала, что MAC — это система где ВСЕ решения о назначении объектам прав производится security officer-ом (не уверен как перевести). Обычные виндовые DACL не подходят по такой трактовке только в плане назначения доступа к объектам, «принадлежащим» субъекту (например, созданным им). Почему это важно для работы с гостайной, думаю, объяснять не нужно. Зачем это может понадобиться домашнему пользователю ума не приложу.
                                  0
                                  Да, нужно соблюдать точность, вы абсолютно правы.

                                  Другой вопрос, что под MAC'ом в обиходе зачастую подразумевается некоторая часть из mandatory protection
                              0
                              Интересно, какие права получит пользователь, который успешно проведёт атаку против уязвимого приложения и получит #root:
                              1) он будет root,
                              2) или будет root, но с правами запущенного приложения (т.е. с политикой SELinux)?
                                0
                                «который успешно проведёт атаку против уязвимого приложения и получит #root»

                                Вот этого мы и стараемся избежать.
                                Он получит права пользователя apache и контекст «httpd_t».
                                В таких условиях проблематично произвести повышение привилегий.

                              Only users with full accounts can post comments. Log in, please.