🧑💻3 Linux
3.1 Практическое занятие. Права доступа. Атрибуты файла. POSIX ACL
Управление доступом с помощью классических битов защиты
При листинге директорий с помощью команды ls -l будет получена информация о дискреционном разграничении доступа к файлам.
Например, следующий вывод:
mpyrev@debian-kb:~$ ls -l
total 44
drwxr-xr-x 3 mpyrev mpyrev 4096 Mar 10 18:29 Desktop
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 Documents
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 Downloads
-rwxr--r-x 1 root root 10 Mar 7 19:37 mk123.sh
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 Music
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 Pictures
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 Public
-rwxr-xr-x 1 root root 79 Mar 7 13:09 script.sh
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 Templates
drwx-w-rwx 2 user1 user1 4096 Mar 7 18:59 test
drwxr-xr-x 2 mpyrev mpyrev 4096 Mar 7 10:28 VideosВ левой части вывода напротив каждого вывода представляется строка вида:
В поле PERMIT указывается информация о типе файла и разрешения разделенные по логике user:group:others или u:g:o. В поле USER указывается владелец файла, в поле GROUP группа владельцев файла. В обозначение others входят все остальные пользователи, которые не являются владельцем или членом группы владельцев.
В unix-системах существуют семь типов файлов:
-— обычный файл (regular file)d— каталог (directory)p— именованный канал (named pipe)l— символическая ссылка (soft link)cиb— символьные и блочные файлы устройств (device file)s— сокет (socket)D— дверь (door)
Биты разрешений могут принимать значения r w x, что означает:
read — чтение
write — запись
execute — выполнение
Изменение классических битов и смена владельца и группы владельцев файла
Изменение классических битов
При необходимости, возможно изменить стандартно назначаемые биты защиты, путем ввода команды:
Данная команда может быть выполнена суперпользователем, администратором с использованием sudo или владельцем файла.
Синтаксис команды:
В данном синтаксисе представлены биты s и t, которые рассмотрены ниже.
Кроме того, биты могут быть записаны в восьмеричном значении:
1 - x
2 - w
4 - r
Таким образом, при необходимости определить все права на файл (например, полные права пользователю, чтение и исполнение группе и только исполнение всем остальным), можно записать в следующем виде (по октетам):
Смена владельца и группы владельцев файла
Если требуется сменить владельца файла или группы владельцев необходимо воспользоваться следующей командой:
Синтаксис команды:
Данная команда может быть выполнена только суперпользователем или администратором с использованием sudo
Специальные разрешения файлов в Linux (SetUID, SetGID, Sticky bit)
SetUID, SetGID
SetUID – это бит разрешения, который позволяет пользователю запускать исполняемый файл с правами владельца этого файла. Другими словами, использование этого бита позволяет нам поднять привилегии пользователя в случае, если это необходимо.
Принцип работы SetGID очень похож на setuid с отличием, что файл будет запускаться пользователем от имени группы, которая владеет файлом.
В случае, если бит на выполнение был удален, бит SetUID или SetGID становится заглавным.
SetUID и SetGID биты действуют только на бинарные файлы, на любых других скриптах игнорируются.
Необходимо с осторожностью назначать SetUID и SetGID биты, так как утилиты могут иметь функции по исполнению команд.
Например, с помощью команды:
При наличии на бинарном файле /usr/bin/find SUID бита, команда выведет консоль от имени суперпользователя.
Sticky bit
В случае, если этот бит установлен для папки, то файлы в этой папке могут быть удалены только их владельцем. Пример использования этого бита в операционной системе это системная папка /tmp . Эта папка разрешена на запись любому пользователю, но удалять файлы в ней могут только пользователи, являющиеся владельцами этих файлов.
При отсутствии бита на исполнение, sticky bit отображается заглавной буквой:
Атрибуты файла
Просмотреть все атрибуты файла возможно командой:
В случае необходимости создать неизменяемый файл, возможно добавить атрибут +i необходимому файлу:
Данная команда может быть выполнена только суперпользователем или администратором с использованием sudo
При назначении данного атрибута, даже суперпользователь не в праве изменить данный файл
Если потребуется создать файл, который является лог-файлом (нельзя изменять, но возможно дописывать), то необходимо добавить атрибут +a
POSIX ACL
ACL (Access control lists) — более сложный, но гибкий инструмент управления правами доступа. Он позволяет сегментировать категорию «other» и разрешить работу с файлом/директорией нескольким конкретным пользователям и группам.
Проверить ACL возможно командой:
Для того, чтобы добавить определенным пользователям права на файл, возможно модифицировать ACL:
В данном случае, помимо добавленных разрешений появилась маска. По умолчанию, составляется как дизъюнкция всех разрешений, кроме владельца. Данная маска необходима для определения максимально возможных прав доступа отличных от владельца пользователям. Например, при маске -wx, будет отображено следующее:
Кроме того, возможно создать шаблон на папку для автоматического распространения ACL при добавлении содержимого (наследственность):
Если необходимо удалить какое-либо разрешение, то потребуется использовать ключ -x для построчного удаления или -b для общего удаления всех ACL:
3.2 Практическое занятие. Настройка OpenLDAP KDC
Предварительная настройка разрешения доменных имен
Для практического занятия потребуются две виртуальные машины (ВМ) Debian. Далее будет использоваться Debian 11 "bullseye". Однако одна ВМ будет настроена без графической оборочки, далее - Debian Server. ВМ с графической оболочкой - Debian Client.
При установке рекомендуется сразу указать домен, к примеру - kb.edu.
Таким образом hostname ВМ будут выглядеть следующим образом: server.kb.edu и client.kb.edu.
В файл /etc/hosts на server.kb.edu необходимо добавить информацию об IP-адресах клиента и сервера. В реальной инфраструктуре данная информация вносится в DNS-сервер.
В файл /etc/hosts на client.kb.edu также необходимо добавить информацию об IP-адресах клиента и сервера.
Также рекомендуется проверить наличие ping при запросе по имени:
Установка OpenLDAP
Где работаем: server
Мы сразу устанавливаем krb5-kdc-ldap, даже несмотря на то, что настроим их позже. Идея заключается в том, чтобы сразу получить необходимые схемы наборов данных OpenLDAP.
Во время установки Вам будет предложено задать некоторые настройки:
пароль учётной записи admin для доступа к конфигурации OpenLDAP;
название области Kerberos (realm);
сервер Kerberos для нашей области;
управляющий сервер области.
На данном этапе эти настройки не важны. Мы последовательно опишем их в дальнейшем.
Прежде чем продолжить, убедитесь, что нужные пакеты установились:
Инициализация конфигурации каталога
Где работаем: server
Инициализацию конфигурации каталога мы произведём с нуля с использованием нового подхода, OLC (cn=config).
Создайте каталог для работы со службой каталогов. У нас будет много конфигурационных файлов, неплохо бы класть их в одно место:
Избавимся от установленных по умолчанию конфигурации slapd и его базы данных:
Создадим пустой каталог для нашей новой конфигурации:
Создадим файл init-config.ldif с новой конфигурацией и запишем в него:
Здесь и далее рекомендуется писать конфигурацию вручную или производить копирование c заменой знаков табуляции вначале каждой строки, если такие имеются
В этом файле первым делом мы определяем корневую запись DIT (Directory Information Tree), cn=config. С помощью директив olcPidFile и olcArgsFile мы указали, куда необходимо записать ID процесса службы каталогов и аргументы его запуска соответственно.
Во втором разделе задаём служебную базу данных конфигурации cn=config. Мы так же добавили правило доступа (ACL, Access Control List), разрешающее манипулировать ей от имени пользователя root (uid=0, gid=0) с помощью механизма SASL EXTERNAL и идентификационной сущности IPC. Помните, что в конце каждого ACL, если не задан модификатор break, подразумевается наличие правила by * none . То есть остальной доступ к объекту в условии to — запрещён.
Последним разделом мы добавляем в конфигурацию контейнер для наборов схем данных.
Инициализируем конфигурацию:
Модификатор -n 0 говорит о том, что мы добавляем данные в базу данных с индексом 0, который зарезервирован для cn=config.
Проверим, всё ли в порядке с нашей конфигурацией:
Поправим права доступа, разрешив пользователю openldap заправлять в каталоге /etc/ldap/slapd.d:
Запуск службы каталогов
Где работаем: server
Разрешим нашей службе каталогов использовать только IPv4. Для этого установим SLAPD_OPTIONS="-4" в файле /etc/default/slapd. В остальном конфигурация стандартная:
Настроим rsyslog, чтобы он писал события службы каталогов в отдельный файл. Для этого достаточно добавить три строки в его конфигурацию после глобальных директив /etc/rsyslog.conf:
Создадим файл для журнала службы каталогов и зададим для него права доступа. Затем перезапустим rsyslog, чтобы изменения вступили в силу:
Настроим logrotate для управления этим журналом. Создадим файл конфигурации /etc/logrotate.d/slapd и запишем в него:
Проверим настройку logrotate:
Наконец запускаем нашу службу каталогов:
Заглянем в файл журнала slapd.log. Всё ли в порядке?
Проверим, активен ли TCP порт 389:
Убедимся, что UNIX сокет тоже активен:
Для пущей убедительности проверим текущую конфигурацию каталога с помощью ldapsearch:
Заметьте, что slapadd (из предыдущего пункта) добавил в наш каталог описание служебной базы данных frontend (в ней можно определить опции, которые будут применяться ко всем базам данных в текущей конфигурации OLC). Однако, если те же самые опции (в том числе правила ACL) определены в конкретной базе данных, то будут применяться именно они.
Подключение динамических модулей
Где работаем: server
Для работы нам понадобится два модуля. Один — для механизма базы данных mdb. На данный момент он рассматривается как основной для нормальных баз данных и должен прийти на смену bdb и hdb. Второй модуль — monitor, для создания и динамической поддержки ветки с информацией о текущем статусе демона slapd.
Чтобы их подключить нам понадобится всего один короткий LDIF-файл и специальная запись cn=module,cn=config. Назовём файл add-modules.ldif и запишем в него:
Каталог с модулями в нашем случае — /usr/lib/ldap.
Добавим наш LDIF-файл в конфигурацию:
Добавление наборов схем данных
Где работаем: server
Прежде чем добавлять наборы схем данных в каталог, необходимо подготовить наборы схем из пакета krb5-kdc-ldap к загрузке (перевести их в формат LDIF).
В используемой нами версии Debian искомые наборы схем находятся по пути /usr/share/doc/krb5-kdc-ldap/kerberos.schema.gz
Скопируем их во временный каталог:
На просторах сети был найден несложный скрипт для преобразования файлов schema в формат LDIF. Немного откорректируем его (для универсальности) и сохраним в том же каталоге ~/ldap под именем schema-ldif.sh:
Сделаем его исполняемым и запустим, передав через переменную SCHEMAS имя файла конвертируемого набора схем:
На выходе должны получить набор схем данных в формате LDIF:
Переместим его в каталог к остальным наборам схем и поправим права доступа:
Удалим ненужный больше набор схем данных:
Создадим LDIF-файл с необходимыми нам наборами схем данных.
Порядок их следования в файле очень важен
Атрибуты наборов схем иерархически связаны и требуют их объявления с соблюдением иерархии. Назовём файл add-schemas.ldif и запишем в него:
Последней строчкой мы указали получившийся в результате конвертации набор схем kerberos.ldif.
Добавим наши наборы схем:
Инициализация базы данных
Где работаем: server
Вот мы и подошли к созданию базы данных, в которой будем хранить нашу рабочую информацию.
Для начала создадим пароль администратора. Утилита slappasswd генерирует посоленный хэш вводимого нами пароля:
Не забудьте сам пароль 😊
Сформируем конфигурационный LDIF-файл для нашей базы данных db.ldif и запишем получившийся хэш в атрибут olcRootPW:
И вновь несколько комментариев...
В качестве механизма манипуляции данными выбираем ранее подключенный модуль mdb.
В качестве суффикса (корневой записи) создаваемого DIT (Directory Information Tree) обычно используется имя домена DNS. Но это не является обязательным. Для примера мы задали суффикс
dc=kb,dc=edu.В атрибуте
olcDbDirectoryмы указали путь к каталогу бузы данных. Атрибут обязательный и требует существование каталога на момент загрузки в базу данных.Механизм mdb требует указания максимального размера базы данных. Он задается в байтах и должен быть больше её ожидаемого размера, даже с учётом прироста. В файловой системе должно быть достаточно свободного места для размещения базы данных такого размера.
В атрибут
olcRootDNмы записываем DN администратора нашей базы данных.Добавляем три правила доступа для базы данных mdb:
Доступ ко всей базе данных:
Разрешить доступ пользователю root с использованием механизма SASL EXTERNAL.
Продолжить анализ ACL, если нет совпадений с субъектами доступа, указанными с помощью директивы
by.
Доступ к атрибуту
userPassword:Разрешить доступ для смены пароля самим пользователем.
Разрешить доступ для аутентификации.
Доступ к остальной базе данных:
Разрешить пользователям просматривать свои записи (важно для аутентификации через nslcd, Настройка аутентификации пользователей через OpenLDAP на клиенте).
С помощью механизма monitor включаем мониторинг базы данных (добавляем базу данных
monitor).
Для нашей базы данных необходимо создать каталог и задать ему права доступа:
Загрузим конфигурацию базы данных:
Определим RootDN для доступа к конфигурации службы каталогов. Он будет ссылаться на RootDN, находящийся в нашей БД. Эта запись желательна только при первоначальной настройке или в тестовой конфигурации. Не оставляйте её в боевой системе! Для {-1}frontend зададим минимально необходимые права для доступа к RootDSE. Создадим LDIF-файл acl-mod.ldif, модифицирующий права доступа:
Загрузим LDIF, изменяющий ACL:
Теперь мы ещё больше повысили значимость учётной записи администратора. С её помощью теперь можно получить полный доступ к службе каталогов. Имейте это ввиду. 😊
Проверим корректность всех ACL и, заодно, наличие всех добавленных нами данных (вывод отформатирован для наглядности):
Убедимся, что учётная запись администратора имеет доступ к нашей службе каталогов:
Отлично! Теперь у нас есть работающий сервер OpenLDAP.
Отредактируем файл /etc/ldap/ldap.conf. Это нужно только для того, чтобы немного упростить себе жизнь и меньше печатать в дальнейшем. В BASE подставьте свой суффикс, а в URI — FQDN Вашего сервера OpenLDAP:
С настройкой TLS мы разберемся в следующем разделе.
И последний штрих. Добавим демон нашей службы каталогов в автозагрузку:
Удостоверяющий центр на основе самоподписанного сертификата с помощью OpenSSL
Где работаем: server
Итак, мы создаём централизованную инфраструктуру открытых ключей (PKI) в миниатюре. Для этого сформируем пару закрытый ключ/корневой сертификат удостоверяющего центра. Причём сертификат будет подписан этим же закрытым ключом (т. е. станет самоподписанным).
Затем сгенерируем новый закрытый ключ для нашей службы каталогов и создадим для неё сертификат, подписанный закрытым ключом нашего удостоверяющего центра. При этом клиенские рабочие станции должны знать только корневой сертификат. Используя его они могут установить безопасное соединение с любым сервером, который имеет закрытый ключ и соответствующий ему сертификат, подписанный нашим УЦ.
Удостоверяющий центр желательно разворачивать на отдельной машине, не имеющей подключения к сети, но для простоты примера мы проделаем всю работу на server.kb.edu.
Создадим каталог для нашего удостоверяющего центра (CA) и установим безопасные права доступа. Затем зададим значение umask таким, чтобы вновь создаваемые файлы имели права доступа чтения и записи только для создавшего их пользователя:
В конфигурационном файле /etc/ssl/openssl.cnf в секции [ CA_default ] для удобства поменяем значение директивы dir = ./demoCA на dir = ./. В этом же разделе директивой default_days задаётся срок действия выпускаемых сертификатов. Можете поменять её значение по своему усмотрению.
Файлы index.txt и serial будут играть роль своеобразной базы данных, чтобы отслеживать статус выпущенных закрытых ключей и сертификатов.
Создадим структуру каталогов и файлов для своего удостоверяющего центра:
Сгенерируем закрытый ключ удостоверяющего центра (длиной 4096 бит). Он должен хранится особенно бережно. Поэтому мы защитим его при помощи шифра AES. Вам будет предложено ввести пароль для доступа к новому закрытому ключу. Запомните его и не потеряйте. Это последний рубеж защиты от злоумышленника. Без пароля выпустить новые сертификаты не получится.
Изменим права доступа к новому ключу, чтобы ненароком его не стереть:
Откройте конфигурационный файл OpenSSL /etc/ssl/openssl.cnf и найдите секции [ usr_cert ] и [ v3_ca ]. Убедитесь, что в них присутствуют следующие директивы:
Сейчас мы можем выпустить корневой сертификат удостоверяющего центра, подписав его закрытым ключом rootca.key. Так как это сертификат УЦ, используем расширение v3_ca:
В качестве алгоритма хэширования мы используем SHA-2 (подвид SHA-256). Стоимость атаки на SHA-1 стремительно падает, а о практическом применении новоявленного SHA-3 говорить пока рано. Почему мы выбрали именно SHA-256, а не SHA-512? С сертификатом, использующим SHA-512, Вы сможете запустить демон slapd, но не сможете к нему подключиться. Увидите лишь такую многозначную ошибку:
Мы так же указываем количество дней, в течении которых сертификат будет действителен. Десять лет — достаточно большой срок.
С помощью модификатора subj заносим в сертификат информацию:
C - Country Name (страна) - RU
ST - State or Province Name (штат или провинция) - Sverdlovskaya
L - Locality Name (город) - Ekaterinburg
O - Organization Name (наименование организации) - UrFU
OU - Organizational Unit Name (наименование подразделения) - KB
CN - Common Name (имя субъекта или FQDN сервера) - ca-server
emailAddress - Email Address (адрес электронной почты) - support@kb.edu
Можем посмотреть содержимое сертификата следующей командой:
Удостоверяющий центр готов к выпуску сертификатов.
Выпуск сертификата для сервера службы каталогов
Где работаем: server
Как правило, закрытые ключи клиентов УЦ не должны хранится в самом УЦ. Клиент может сам сформировать ключевую пару и прислать в УЦ лишь запрос на подпись (Certificate Signing Request, CSR). Запрос содержит открытый ключ. Однако мы будем создавать все ключи и хранить их в одном месте. В организации, которая серьёзно подходит к проблемам безопасности такой процесс работы может быть неприемлемым.
Продолжаем в том же каталоге /root/CA. Создадим закрытый ключ для сервера службы каталогов:
Сгенерируем запрос на подпись сертификата. Наименование организации (UrFU) должно совпадать с наименованием в корневом сертификате УЦ. В качестве Common Name укажем FQDN нашего сервера:
Следующим шагом должно быть подписание запроса CSR существующим доверенным удостоверяющим центром (например, VeriSign) в обмен на деньги. Но нам не хочется платить за эту услугу, или у нас нет своего (корпоративного) CA, или это просто тестовая конфигурация, а может нам просто всё равно. Поэтому мы подпишем его с помощью своего собственного CA:
Создадим каталог для ключевой информации нашего сервера и поместим туда получившиеся у нас файлы:
Установим права доступа для ключевой информации:
Поместим корневой сертификат в каталог с сертификатами операционной системы и зададим для него права доступа:
В заключение можем удалить запрос CSR, он нам больше не нужен:
Каталог /root/CA теперь выполняет роль удостоверяющего центра. Аналогичным образом его можно создать на другой машине, тогда надо будет копировать секретные ключи и подписанные сертификаты по сети с помощью scp или через съёмный носитель. Неплохой идеей будет хранить этот каталог на отдельном носителе и монтировать его только для выпуска новых сертификатов. Сам носитель можно, например, положить в сейф. Процесс создания новых пар ключ-сертификат в будущем будет состоять из трёх этапов:
Генерация секретного ключа и запроса на подписание сертификата;
Подписание сертификата с помощью закрытого ключа нашего CA (
rootca.key);Перемещение новых секретного ключа и подписанного сертификата в каталоги, где они будут использоваться.
Настройка конфигурации TLS
Где работаем: server
Вернёмся во временный каталог:
Создадим LDIF-файл tls-config.ldif для внесения в каталог конфигурации TLS и запишем в него:
Этими записи говорят демону slapd, где лежит его сертификат и ключ, где лежит корневой сертификат УЦ и что от клиентов требовать наличие сертификата не нужно. Чтобы окончательно всё запутать, мы могли бы создать сертификаты для всех клиентов. В реальной жизни такая аутентификация клиента принесёт небольшое усиление защиты за счёт большого увеличения работы по сопровождению всех этих сертификатов. Тем более, далее, на этой практике мы настроим механизмы аутентификации Kerberos.
Загрузим конфигурацию TLS в наш каталог:
Теперь наш сервер OpenLDAP должен поддерживать расширения TLS. Перепроверим, что всё в порядке:
Вновь отредактируем конфигурационный файл /etc/ldap/ldap.conf и включим поддержку TLS:
Обычно для конфигурации cn=config перезагрузка службы не требуется, но чтобы созданная нами ключевая информация подхватилась, придётся это сделать:
Проверьте соединение с сервером с использованием TLS (модификатор -ZZ). На этот раз мы выполним запрос с использованием DN нашего администратора:
Обратите внимание, что в запросе ldapsearch нам не пришлось указывать имя хоста (-H ldap://server.kb.edu). Всё потому что оно указано в файле /etc/ldap/ldap.conf. Что касается TLS, то во время инициирования соединения клиент (на данном этапе клиентский запрос выполняет сам сервер) получает от сервера его подписанный сертификат (server.kb.edu.crt). Клиент может ничего не знать о сервере, но у него есть сертификат CA (rootca.crt), с помощью которого и проверяется сервер.
Создание CRL и отзыв сертификатов
Где работаем: server
Сертификаты не вечны. Во-первых при создании задаётся его срок действия. При этом частота обновления сертификатов — баланс между безопасностью и удобством. Во-вторых он может быть скомпрометирован, если скомпрометирован его закрытый ключ. Как во втором случае оповестить субъектов доступа, что сертификат более не действителен? Для этого и служит Certificate Revocation List (CRL). Он представляет собой список серийных номеров отозванных сертификатов, подписанный УЦ, который их выпустил.
Вернёмся в каталог удостоверяющего центра:
Прежде чем мы сможем сгенерировать CRL, надо создать файл crlnumber. Он нужен openssl, чтобы отслеживать номер следующего CRL:
В стандартной конфигурации openssl использует CRL V1.
Раcкомментируйте строку crl_extensions = crl_ext в /etc/ssl/openssl.cnf, чтобы переключиться на CRL V2. Это хорошая идея, за исключением тех случаев, когда надо использовать именно CRL V1 (например, при использовании сильно устаревшего браузера). Создаём CRL:
Посмотреть результат можно так:
Предположим, что закрытый ключ сервера server был скомпрометирован. Чтобы оповестить об этом клиентские машины, надо отозвать сертификат этого сервера, создать CRL, а затем — распространить CRL среди клиентов.
Отзываем сертификат:
Заглянем в index.txt. Начало записи с нашим сертификатом теперь изменилось с V на R:
Обратите внимание, что копии новых сертификатов так же содержатся в каталоге newcerts. При этом имя файла содержит серийный номер сертификата. Когда отзываете сертификаты, вместо файлов в каталоге certs Вы можете пользоваться каталогом newcerts. Результат будет идентичен. Например:
Обновим CRL:
Взглянём на содержимое CRL:
Вы должны увидеть нечто подобное:
Поместим CRL в каталог, где его увидит клиентское ПО:
Осталось только распространить этот CRL среди клиентов. Мы делаем это простым путём — копированием файлов по сети вручную.
Где работаем: client
На каждой клиентской машине надо будет запустить:
Настроим клиентскую конфигурацию в /etc/ldap/ldap.conf и укажем, где хранится CRL:
Для следующей команды потребуется установить на клиенте утилиты ldap:
Попробуем получить доступ к серверу каталогов:
Наш CRL работает. Но к slapd теперь не подключиться. Надо выпустить новый сертификат для сервера.
Где работаем: server
Сделаем это простой последовательностью команд. Мы повторяем пройденное, комментарии излишни:
Перезапустим демон slapd и убедимся, что к серверу можно подключиться.
Где работаем: client
В целом по отзыву сертификатов... Иногда в реальных условиях лучше применить другой подход. Намного удобней, когда клиентские машины самостоятельно выясняют у сервера, действителен конкретный сертификат или нет. В выпускаемые сертификаты можно вносить запись CRL Distribution Points. Она заставит клиентов самих периодически скачивать новый CRL. Или можно использовать OCSP. Но эта тема выходит за рамки данной практики.
Управление пользователями и группами в OpenLDAP
Где работаем: server
На данном этапе у нас есть пустой каталог OpenLDAP. Мы можем проверить это, просто попытавшись извлечь из него информацию:
Если Вам интересно, коды ошибок LDAP описаны в RFC 4511, в приложении A Результирующие коды LDAP. В случае ошибки 32 сервер информирует нас, что запрашиваемый объект dc=kb,dc=edu не найден. Но такую же ошибку можно получить, если ACL сервера запрещают доступ.
Для работы нашего каталога понадобится создать корневой суффикс базы данных и добавить в него две организационных единицы (Organizational Unit, OU) для хранения пользователей и групп. Создадим LDIF-файл users+groups.ldif, в котором опишем эту информацию:
Добавим эту информацию в наш каталог:
Можем удостовериться в том, что информация добавлена:
Теперь давайте добавим несколько групп:
sysadmin, для объединения системных администраторов Linux;
nssproxy, которая будет использоваться для опроса сервера, чтобы не делать анонимный опрос;
test.group, для тестирования различных частей архитектуры PAM и LDAP.
Этот список не окончательный и может быть дополнен, чтобы соответствовать нуждам Вашей организации.
Для добавления групп в каталог создадим новый LDIF groups.ldif:
Загрузим LDIF в наш каталог:
Настало время создать несколько пользователей. И вновь отмечаем, что список может быть расширен в соответствии с потребностями Вашей организации:
mpyrev - персональный пользователь.
nssproxy, который будет использоваться для опроса сервера, чтобы не делать опрос от анонимного пользователя.
test.user - как и тестовая группа, этот пользователь будет использоваться для проверки наших настроек.
Создадим LDIF-файл users.ldif для добавления пользователей. Пока не беспокойтесь о паролях, мы сейчас к ним вернёмся:
Пользователи связаны с группами через атрибут gidNumber. Для того, чтобы добавить в группу других пользователей, в запись группы необходимо добавить атрибут memberUID, перечислив в нём UID пользователей через запятую. Например, это может выглядеть вот так:
Добавьте пользователей в каталог:
Теперь установим пароли для пользователей. Повторите нижеследующую команду для всех пользователей. Обратите внимание, что сначала Вам будет предложено дважды ввести пароль изменяемой записи, а затем — пароль записи cn=admin,dc=kb,dc=edu:
Если заглянуть в журнал /var/log/slapd.log, то можно увидеть строки, говорящие об изменении записи:
Для того, чтобы пользователь nssproxy имел доступ к информации нашего каталога, необходимо поправить ACL базы данных с пользователями и группами. Но какое у этой базы DN? Давайте вспомним:
В разделе Инициализация базы данных мы дали нашей учетной записи администратора очень широкие права, поэтому он может заглянуть в конфигурацию cn=config.
Теперь мы знаем, что требуется отредактировать ACL записи olcDatabase={1}mdb,cn=config.
Давайте проверим, какие ACL настроены для данного DN (вывод отформатирован):
Мы должны немного изменить ACL, чтобы предоставить доступ пользователю nssproxy на чтение атрибутов учётных записей. Для этого создадим LDIF-файл nssproxy.acl.ldif:
Загрузим LDIF с изменениями:
Проверим, можем ли мы просматривать информацию в каталоге от имени пользователя nssproxy. Для этого выполним запрос с использованием его учётных данных. Результатом запроса должно быть всё DIT (Directory Information Tree). Опустим его, для краткости:
Убедитесь, что другие учётные записи пользователей не имеют доступа к DIT:
Настройка аутентификации пользователей через OpenLDAP на клиенте
Где работаем: client
Перейдём к настройке клиентской рабочей станции. Для начала установим необходимые пакеты:
При установке нам будут предложены некоторые настройки . Далее мы всё равно внесём в конфигурацию изменения, но это нужно сделать, чтобы все пакеты нормально установились:
URI сервера LDAP:
ldap://server.kb.edu;База поиска сервера LDAP:
dc=kb,dc=edu;Имена настраиваемых служб:
passwd,group,shadow,netgroup.
Прежде чем делать запросы к LDAP-серверу, проверим параметры клиента в /etc/ldap/ldap.conf:
Конечно, для того, чтобы всё заработало, сертификат нашего Certificate Authority (rootca.crt) и CRL-файл (rootca.crl) должны быть на месте.
Проверим работоспособность простым запросом. Результат опустим (Вы должны увидеть всё DIT):
Поправим конфигурацию нашей локальной службы имён LDAP в файле /etc/nslcd.conf. Измените значение директивы bindpw на пароль записи cn=nssproxy,ou=users,dc=kb,dc=edu, который мы задавали ранее:
Краткое описание использованных директив:
С помощью директивы
baseмы сообщаем демону nslcd, где в DIT искать ту или иную информацию;bind_timelimitограничивает время на установление соединения с сервером пятью секундами;timelimitустанавливает максимальное время ожидания ответа от сервера в 10 секунд;idle_timelimitзаставит nslcd разорвать соединение с сервером, если в течении минуты в соединении не было никакой активности;sslзаставляет клиента использовать TLS при подключении к серверу;tls_reqcertиtls_cacertfileподобны директивамTLS_REQCERTиTLS_CACERTв конфигурации /etc/ldap/ldap.conf (необходимость проверки сертификата сервера и путь к корневому сертификату для выполнения проверки);nss_initgroups_ignoreusersописывает пользователей системы, поиск которых не нужно производить в DIT (чтобы мы могли работать с машиной при проблемах с доступом к серверу каталогов). В значение этой директивы следует внести имена всех общесистемных пользователей.
Поменяем права доступа к nslcd.conf, потому что теперь в нём хранится информация для аутентификации:
Проверим содержимое /etc/nsswitch.conf:
Убедимся в том, что демон nslcd запускается при старте системы и перезапустим его:
Убедимся, что в системе client НЕТ учётной записи с именем nssproxy. Следующая команда должна выполняться без результата:
Убедимся так же, что кэширующий демон службы имён загружается при старте системы и перезапустим его:
Сделаем пару запросов к LDAP-серверу, используя настроенную нами систему:
Не беспокойтесь, хэш пароля мы видеть не должны.
Отлично, всё работает! Вышеприведённые результаты команд означают, что система client может осуществлять поиск по данным пользователей и групп в нашем каталоге OpenLDAP.
Создадим домашний каталог нашего тестового пользователя и установим для него права доступа:
Запустим в отдельном терминале вывод журнала аутентификации:
В другом терминале выполним:
Мы должны получить приглашение командной строки пользователя test.user.
Теперь попробуем зайти на машину client по сети с использованием ssh под учётной записью test.user.
Демон ssh в конфигурации по умолчанию должен работать с поддержкой PAM (и, соответственно, поддерживать аутентификацию через LDAP). Но на всякий случай приведём рабочую конфигурацию /etc/ssh/sshd_config:
Обратите внимание на строку с директивой AllowGroups. С помощью неё мы ограничиваем список групп пользователей, которые могут быть аутентифицированы через ssh. За информацией по остальным директивам обратитесь к документации.
Проверим работу с использованием какой-нибудь третьей машины. Например, выполним на нашей хостовой машине запрос через PuTTY:
Где работаем: server
Давайте заглянем в /var/log/slapd.log на нашем сервере. Мы можем обнаружить там следующие строки:
С помощью следующей команды мы можем убедиться, что в нашем каталоге пока нет никаких индексов:
Это значит, что в нашей базе данных надо создать индексы для атрибутов из журнала /var/log/slapd.log. Поэтому создадим ещё один LDIF-файл posixAccount.indexes.ldif и запишем в него:
Зачем мелочиться? Укажем побольше индексируемых атрибутов. И загрузим конфигурацию в наш каталог:
Проверим результат изменений:
Отлично! Теперь в журнале /var/log/slapd.log не должно быть ошибок.
Kerberos KDC с использованием OpenLDAP в качестве бэкэнда и аутентификацией SASL GSSAPI
В этом разделе мы научимся использовать OpenLDAP 2.4 в качестве хранилища принципалов (principals) Kerberos и разберем, как настраивать клиентские рабочие станции. Kerberos — это сетевой протокол, который работает на основе билетов (tickets) и позволяет передавать данные через незащищённые сети для безопасной идентификации и аутентификации. Его дизайн преимущественно опирается на клиент-серверную модель и позволяет произвести взаимную аутентификацию субъекта и объекта доступа. Сообщения протокола устойчивы к прослушиванию и атакам повтора. Kerberos работает на основе криптографии с симметричным ключом и требует наличия доверенной третьей стороны, а так же может применяться с использованием криптографии с открытым ключом на некоторых этапах процесса аутентификации.
На текущем практическом занятии в роли сервера Kerberos будем использовать server. Но ничто не мешает Вам использовать для этого отдельную машину.
Настройка сервера Kerberos
Где работаем: server
Включите NTP и убедитесь, что сервер и клиенты синхронизированы! Мы не будем описывать, как настраивать NTP. Вы можете найти множество примеров в сети, если потребуется.
Теперь, когда наш сервер OpenLDAP настроен, мы можем приступить к конфигурированию сервера Kerberos. В этом разделе мы опишем, как развернуть центр распределения ключей Kerberos (KDC, Key Distribution Center) для области (realm) KB.EDU. Начнём с установки необходимых пакетов. В процессе будет так же установлено несколько пакетов-зависимостей. Пакет wamerican создаст файл /usr/share/dict/words, используемый kadmind. Вместо него можно использовать любой другой словарь или несколько словарей. Чтобы посмотреть их список, посмотрите содержимое метапакета wordlist.
В разделе Добавление наборов схем данных мы уже установили схему Kerberos для OpenLDAP сервера, но давайте лишний раз убедимся, что она на месте:
Схема на месте. В ней содержится достаточно много объектов. Чтобы посмотреть их все, используйте следующий запрос:
Эта команда должна вернуть список объектов. Это важно, потому что если новых атрибутов Kerberos LDAP нет, то kdb5_ldap_util(8) выдаст следующую ошибку:
Итак, у нас есть набор схемы данных и объекты. Но есть ли у нас контейнер для принципалов Kerberos?
Нет, нету. Создадим его, а заодно — пользователя и группу, которые будут использоваться Kerberos для взаимодействия с сервером OpenLDAP. Используем для этой цели вот такой LDIF-файл kerberos.ldif:
Загрузим этот файл в базу данных нашего сервера каталогов:
Зададим пароль для пользователя krbadmin. Сохраните пароль.
Создадим конфигурационный файл Kerberos /etc/krb5.conf:
Теперь создадим список контроля доступа (ACL) администратора Kerberos. Не путайте этот ACL с ACL OpenLDAP. Это не одно и то же. Чуть ниже мы поработаем с ACL для OpenLDAP. Создадим файл /etc/krb5kdc/kadm5.acl с таким содержимым:
Отредактируем /etc/krb5kdc/kdc.conf, конфигурационный файл службы аутентификации (AS, Authentication Service) и центра распределения ключей (KDC):
В отдельном терминале включите просмотр журнала сервера OpenLDAP. Так мы сможем увидеть сообщения, генерируемые командой kdb5_ldap_util(8):
Создайте каталог-тайник для пароля. В файле /etc/krb5.conf он указан в переменной ldap_service_password_file:
Извлеките пароль пользователя cn=krbadmin,ou=users,dc=kb,dc=edu, используя kdb5_ldap_util(8):
Вам будет предложено ввести мастер-пароль базы данных.
Очень важно, чтобы вы не забыли этот пароль!
В основном терминале выполните следующую команду для добавления записей Kerberos в базу данных OpenLDAP:
Вышеуказанная команда создаст несколько записей в cn=kerberos,ou=services,dc=kb,dc=edu. Чтобы увидеть их, выполните запрос:
Но может ли кто-нибудь кроме пользователя cn=admin увидеть нашу информацию Kerberos? Это было-бы не очень мудро. Поэтому давайте взглянем на ACL нашего сервера OpenLDAP:
Что нам надо сделать, так это дать права доступа на чтение/запись администратору Kerberos (cn=krbadmin,ou=users,dc=kb,dc=edu) к поддереву cn=kerberos,ou=services,dc=kb,dc=edu. Никакой другой пользователь не должен иметь доступа к этой информации (за исключением администратора каталога).
Для этого сформируем LDIF-файл kerberos.acl.ldif:
Загрузим данные в сервер каталогов:
Убедитесь, что новые ACL работают. Суперпользователь и пользователь cn=admin,dc=kb,dc=edu должны иметь доступ к поддереву cn=kerberos,ou=services,dc=kb,dc=edu. Пользователь cn=nssproxy,ou=users,dc=kb,dc=edu не сможет обнаружить само существование контейнера Kerberos, а cn=krbadmin,ou=users,dc=kb,dc=edu должен не только видеть контейнер, но и иметь для него права на чтение/запись. Мы так же должны убедиться, что обычные пользователи всё ещё могут использовать сервер OpenLDAP для аутентификации и что они могут менять себе пароли.
Этот запрос возвращает поддерево cn=kerberos,ou=services,dc=kb,dc=edu:
Следующий запрос должен завершиться с ошибкой No such object (32):
Теперь с клиентской машины убедимся, что пользователь, учётная запись которого хранится на сервере каталогов, может менять свой пароль:
Где работаем: client
Где работаем: server
Настало время настроить журналирование. Для начала добавим в конфигурацию rsyslog следующие строки (/etc/rsyslog.conf):
Создадим файлы журналов и зададим для них права доступа:
Настроим logrotate. Создадим два конфигурационных файла.
Файл /etc/logrotate.d/krb5kdc для демона krb5-kdc:
Файл /etc/logrotate.d/kadmind для демона krb5-admin-server:
Перезапустим демон rsyslog, чтобы конфигурация вступила в силу. Добавим демоны krb5-kdc и krb5-admin-server в автоматический запуск, затем запустим их:
Загляните в журнал /var/log/krb5kdc.log. Вы должны увидеть там подобную строку:
Проверим, что наши демоны слушают необходимые порты. Порт 88 (krb5kdc), порты 464 и 749 (kadmind):
Поздравляю, теперь у Вас есть рабочий сервер аутентификации (AS) и сервер распределения ключей (KDC) MIT Kerberos 5!
Что дальше? В первую очередь нам необходимо создать принципал для локального сервера. Затем — принципал для пользователя test.user. Сделаем это так (разобьем вывод на части, чтобы добавить комментарии):
Здесь мы создаём принципал машины для текущего сервера (на котором залогинены). Далее выделен вводимый нами текст:
После создания принципала сервера мы можем добавить его в набор ключей Kerberos (/etc/krb5.keytab):
Следующим шагом создадим принципал для персонального пользователя mpyrev и зададим для него пароль:
Теперь создадим принципал пользователя с правами администратора. Помните файл /etc/krb5kdc/kadm5.acl? Вот где он вступает в игру. С помощью этого файла пользователи с префиксом /admin имеют права администратора на доступ к области Kerberos. Это значит, что они могут создавать и удалять записи пользователей и политики доступа. Поэтому убедитесь, что Вы знаете этих пользователей и доверяете им!
Посмотрим список текущих принципалов в области:
А эта команда выведет подробную информацию о принципале host/server.kb.edu@KB.EDU:
Обратите внимание, что был создан новый файл /etc/krb5.keytab. Вот почему мы запустили бинарник kadmin.local от имени суперпользователя. Иначе мы получили бы следующую ошибку:
Только суперпользователь имеет доступ на чтение к файлу-тайнику (/etc/krb5.d/stash.keyfile).
Давайте посмотрим, что записано в /etc/krb5.keytab:
Как мы можем видеть, это список ключей шифрования машины server. Неудивительно, что доступ предоставлен только суперпользователю!
У нас осталась ещё одна вещь на сервере, которую надо поправить. Это ошибка
в журнале /var/log/slapd.log. Создадим LDIF-файл kerberos.indexes.ldif, который внесёт поправки в индексы:
Добавим эти индексы в сервер каталогов:
Отлично! Теперь у нас есть настроенный KDC!
Настройка клиента Kerberos
С действующим KDC мы можем заставить клиентские машины и сервисы использовать его. Обозначим основные цели по настройке клиентов, чтобы интегрировать их в инфраструктуру Kerberos:
Аутентификация Kerberos для sshd.
Аутентификация OpenLDAP с помощью SASL GSSAPI.
Аутентификация Kerberos для sshd
Где работаем: client
Клиенты Kerberos должны иметь возможность подключения к TCP портам KDC с номерами 88 и 749
Установим необходимые пакеты:
Во время установки в качестве области Kerberos можете задать KB.EDU, а в качестве серверов, обслуживающих область, server.kb.edu.
Отредактируйте конфигурацию клиента в файле /etc/krb5.conf следующим образом:
Создайте новый принципал машины для этого хоста. Мы запускаем команду kadmin от имени суперпользователя, чтобы можно было записать результирующий файл /etc/krb5.keytab. Иначе мы получим не очень понятную ошибку No such file or directory while adding key to keytab.
Мы так же должны использовать модификатор -p, чтобы дать понять команде kadmin, от имени какого принципала мы хотим подключиться. Если мы его не зададим, то получим ошибку Client not found in Kerberos database while initializing kadmin interface, потому что не создавали принципал root/admin@KB.EDU.
Не создавайте этот принципал! Мы хотим знать, кто подключается с правами администратора (пользователи с префиксом /admin). Если создадим — не сможем различать администраторов между собой.
Эта команда создала файл /etc/krb5.keytab.
Теперь мы можем отредактировать /etc/ssh/sshd_config и включить аутентификацию Kerberos. Не забудьте добавить test.group в директиву AllowGroups. Иначе мы не сможем протестировать конфигурацию и увидим ошибку User test.user from server.kb.edu not allowed because none of user's groups are listed in AllowGroups в файле /var/log/auth.log.
Перезапустим демон:
Запустите на клиентской рабочей станции отображение файла журнала:
А пока вернёмся на сервер.
Где работаем: server
Создадим принципал пользователя test.user:
Возьмём билет Kerberos у test.user и прикинемся этим пользователем. Сначала мы уничтожим свои собственные билеты (если они есть), используя kdestroy, затем возьмём билет test.user с помощью kinit, а в итоге проверим, что он у нас есть с помощью klist:
Теперь попробуем авторизоваться на клиенте без пароля, используя этот билет:
Где работаем: client
В открытом нами журнале на клиенте /var/log/auth.log мы должны увидеть что-то подобное:
Успех! Переходим к следующей цели.
Аутентификация OpenLDAP с помощью SASL GSSAPI
Где работаем: server
Для настройки аутентификации SASL GSSAPI мы должны изменить конфигурацию сервера OpenLDAP таким образом, чтобы он знал о существовании нашей области Kerberos. После этого мы можем настроить клиентов.
Подключимся к KDC и создадим новый принципал. Мы по-прежнему запускаем kadmin от имени суперпользователя, потому что хотим создать новый набор ключей в файле /etc/ldap/krb5.keytab, чтобы наш демон slapd имел свой набор.
Поменяем права доступа на этот файл, чтобы демон slapd смог его читать:
Создадим LDIF-файл sasl.ldif с директивами SASL:
И загрузим его в базу данных службы каталогов:
Сейчас проверим, загрузил ли демон slapd нашу конфигурацию SASL:
Хорошо! Теперь нам нужно добавить параметр KRB5_KTNAME в файл /etc/default/slapd:
Для того, чтобы изменения вступили в силу, нам нужно перезапустить демон slapd:
Демон slapd снова запущен — мы можем переходить к настройке клиента.
Где работаем: client
Получим билет от KDC:
Все настройки для доступа на сервер у нас уже внесены в файл /etc/ldap/ldap.conf. Проверим, можем ли мы сделать запрос к LDAP-серверу:
Отлично. Теперь попробуем зайти с хостовой машины на client под пользователем test.user и поменять ему пароль.
Процесс обновления пароля изменился. Если мы попытаемся запустить команду passwd от имени пользователя, которого нет в локальном файле /etc/passwd, пароль будет изменен с использованием механизмов Kerberos.
Вот и всё! На этом танцы с бубном у Kerberos закончились. 😊
За основу была взята статья: https://www.opennet.ru/docs/RUS/openldap_ubuntu
3.3 Практическое занятие. Настройка AppArmor
Подготовка окружения
Клонировать код web сервера из репозитория на server:
Cоздать виртуальное окружение, чтобы символическая ссылка заменилась на копию интерпретатора
Установить все необходимые пакеты в окружение
Убедиться, что все пакеты установились успешно
Демонстрация уязвимостей web сервера
Запустить web-сервер от имени текущего пользователя
Убедиться, что сервер успешно запустился
Сформировать URLEncoded строку (например, https://www.urlencoder.org/) для кода
Выполнение этого кода создает копию файла /etc/shadow в рабочем каталоге сервере (откуда его запустили)
Перейти по URL <IP адрес сервера>/command?command=<URLencoded строка кода>. Убедиться, что, что команда успешно выполнена (отображается result 0).
Сформировать URLEncoded строку для кода
Перейти по URL <IP адрес сервера>/command?command=<URLencoded строка кода>, убедиться, что отображается содержимое файла /etc/shadow
Настройка безопасности сервера
Создать специальную учетную запись для web-сервера с помощью команды:
Рекомендуется перед выполнением команды перейти в каталог, содержащий файл app.py
Значения флагов команд:
создается учетная запись без полноценного домашнего каталога (с помощью опции
–dзадается явный домашний каталог, в данном случае совпадающий с текущим каталогом, опция–Mговорит, что каталог не нужно инициализировать);создается системная учетная запись (т.е. uid менее 1000 – чистое украшательство), что задается опцией
–r;у учетной записи отсутствует пароль и шелл (опция
–sзадает специальный «шелл»/usr/sbin/nologin) – это делает невозможным обычный вход от имени этой учетной записи (что локальный, что по SSH).
Сменить владельца каталога с файлами web-сервера:
Показать, что просто так перейти в сеанс учетной записи невозможно:
Запустить web-сервер из под учетной записи flask-run (в сеанс перешли в предыдущей демонстрации), команды предполагают, что текущий каталог это /home/mpyrev, а не web_server_for_OWASP:
Повторно пробудем прочитать файл /etc/shadow (демонстрация), убеждаемся, что прочитать не удалось.
Для удобства управления сервером создаем скрипты для запуска и останова сервера:
Скрипт start.sh:
Скрипт stop.sh:
start-stop-daemon – утилита, которая берет на себя рутину по «демонизации» любых процессов, поэтому удобно ее использовать для запуска различных серверов.
Пояснения по синтаксису:
-S – команда запуска
-K – команда останова
-b – запуск в режиме демона (освобождение консоли)
--make-pidfile – указывает что start-stop-daemon самостоятельно позаботиться о создании PID файла
--pidfile – указывает имя PID файла, которое надо использовать
-u flask-run – способ проверки, что демон еще не запущен (в данном случае по имени пользователя – если уже будет процесс python3 от имени flask-run, то start-stop-daemon ничего не запустит)
-d – указывает на домашний каталог демона (обязательно, иначе сервер не найдет свои файлы – БД, шаблоны и пр.)
-a – что, собственно, запускать (здесь сделано через подстановку результата работы утилиты which для универсальности, но можно просто задать полное имя)
-c – от чьего имени запускать
После -- идут опции, которые передаются запускаемому демону
Опционально можно убедиться, что через web сервер мы прекрасно можем прочитать файл start.sh (да и любой другой, к которому у flask-run есть доступ на чтение)
Помещение сервера в изолированный профиль AppArmor
Информацию про Linux Security Modules (механизм реализации альтернативной модели безопасности в Linux) можно прочитать в лекциях (презентации Лекция_13 и Лекция_16)
Создание нового профиля AppArmor
Останавливаем web сервер (stop.sh)
Устанавливаем утилиты для работы с профилями AppArmor:
Запускаем интерактивное формирование профиля для сервера:
Во второй консоли запускаем web сервер (start.sh), выполняем все легитимные действия с сервером (all, one, create, update, predict).
Останавливаем web сервер (stop.sh).
В первой консоли (где работает aa-genprof) нажимаем s ((S)can system log for AppArmor events).
Отвечаем на вопросы утилиты, руководствуясь следующими соображениями:
всегда выбираем конкретный каталог сервера и виртуального окружения (утилита будет пытаться маскировать имя пользователя в пути по умолчанию)
используем
(G)lobдля путей, где предполагаются массовые однотипные действия с файлами (типаsite-packages, templates, dev/shm)соглашаемся на инклюды системных политик
После завершения вопросов утилиты сохраняем полученный профиль (можно предварительно его отобразить на экране)
Проверка профиля AppArmor
Проводим проверку профиля
Во второй консоли также запускаем web сервер и снова выполняем все легитимные действия. Можно сделать что-то запрещенное, убедиться, что все получилось, но запомнить, что сделали, чтобы не добавить потом это действие в разрешения профиля.
Если сервер перестал работать, возможно скорректировать профиль по пути /etc/apparmor.d в данной папке возможно найти профиль home.mpyrev.venv.bin.python3 и проверить что запрещено (строка начинается сdeny)
После сохранение профиля необходимо перезапустить сервис Apparmor командой
systemctl restart apparmor
Останавливаем web-сервер во второй консоли
Запускаем утилиту сканирования журнала:
Анализируем вывод утилиты (аналогичен aa-genprof). Если видно, что запрашиваются какие-то нужные права – подтверждаем. Всякие сомнительные – либо Ignore, либо Deny (отличие в том, что Deny больше не попадет в логи вообще, а так оба варианта запрещают действие, так как политика AppArmor строится на принципе запрещено все, что не разрешено).
Боевой запуск профиля AppArmor
Переводим профиль в боевой режим:
Запускаем web сервер, проводим проверку легитимных действий (должно все получиться)
Пробуем сделать что-то нелегитимное (например, прочитать start.sh) – убеждаемся, что больше это не получается.
Прочитать сам app.py получится, так как мы разрешили это в профиле (иначе скрипт не запустился бы)
Настройка контроля целостности
Устанавливаем пакет AIDE
Прячем все стандартные политики AIDE, чтобы они не использовались далее:
Создаем новый файл с правилами для нашего сервера:
Содержимое файла:
Пояснение по содержимому: первые две сроки задают каталоги для контроля целостности и способ контроля. Full – это макрос, который говорит контролировать все, использовать все поддерживаемые контрольные суммы. Кому интересно, может найти определение макроса в /etc/aide/aide.conf (там сильная вложенность макросов).
Последние две строки задают исключения для контроля целостности.
Создаем первичный снимок каталогов:
Выполняем тестовую проверку:
В выводе должна присутствовать строка:
Проверяем работу AIDE: модифицируем файл app.py (произвольным образом)
Запускаем проверку
Теперь в выводе должны присутствовать строки вида:
При необходимости обновляем конфигурацию.
3.4 Практическое занятие. Настройка окружения SELinux на примере LAMP-сервера
Подготовка
Установим стандартный комплект софта для LAMP:
Минимально настроим софт:
Отключим временно SELinux:
Запустим все необходимые сервисы:
Включим обратно SELinux:
Добавим какого-нибудь пользователя, например phpbb:
И создадим простой тестовый файл с phpinfo():
Перейдем по ссылке…

… и получим именно то, что получают все 😊
Разбираемся с ошибками
В отличие от других мануалов, где следующим шагом идет «отключите SELinux», мы сейчас узнаем, почему так получилось и что можно сделать. Для начала — установим консольные утилиты для управления политиками SELinux:
А потом — включим нужные нам модули ( командой semodule ):
Давайте посмотрим, с какими именно проблемами столкнулся apache при открытии этой страницы?
Все верно: папка www (а так-же папки web и public_html) внутри домашней директории пользователя автоматически получает тип httpd_user_content_t, что и указано в правилах:
Лечение указано в выводе audit2allow, установка переменных выполняется командой setsebool(или semanage boolean).
Обновляем страницу и получаем:

Смотрим логи:
Все ясно: httpd не может коннектиться куда попало, httpd может ходить только куда нужно. Это логично: если веб-сервер вдруг соединяется по ssh, то явно происходит что-то странное. Давайте посмотрим, куда веб-серверу ходить можно?
В квадратных скобках указаны переменные, которые отвечают за работу этого правила.
Итого: нужно добавить порт 9009 в один из типов, к которым разрешен коннект, а затем установить переменную httpd_can_network_relay в 1.
Новый порт добавляется при помощи команды semanage port:
Обновляем страницу и видим:

Что-то посложнее
Давайте теперь усложним задачу и поставим phpbb на этот хост.
Создадим базу данных:
Пробуем зайти в инсталляшку phpbb:

Почему так? Потому что httpd не может изменять пользовательские данные. Давайте узнаем, какие же он изменять может?
Устанавливаем php-xml и php-mbstring включаем httpd_builtin_scripting и назначаем контекст httpd_user_rw_content_t на указанные файлы и папки (командой chcon):
Получаем:

Устанавливаем phpBB дальше, удаляем install и получаем работающий форум:

Меняем контекст конфига обратно:
Наслаждаемся безопасным форумом 😊
Небольшой cheatsheet
Команды.
semodule — управляет списком модулей
sestatus — текущий статус SELinux
setenforce 1/0 — включить/выключить enforcing
audit2allow — утилита для генерации правил ( и для подсказок )
sesearch — утилита для поиска правил в политике
seinfo — показывает информацию о типах, ролях, атрибутах итд
semanage — позволяет вносить изменения в политики
chcon — позволяет менять контекст на ФС
restorecon — востанавливает контекст по-умолчанию
setsebool — устанавливает переменную в on/off. С -P — пишет на диск
getsebool — получает переменную. -a — посмотреть все
Изменения политики
semanage port -a/-d -t httpd_port_t -p tcp 8044 — добавить/удалить номер порта к контексту
semanage fcontext -a/-d -t httpd_cache_t "/srv/http/cache(/.*)?" — добавить/удалить контекст для этой маски
semanage permissive -a/-d httpd_t — включить/выключить режим permissive для httpd_
Аргументы к командам
id -Z — показывает контекст текущего пользователя
ls -Z — показывает контекст файлов
ps -Z — показывает контекст процессов
netstat -Z — показывает контекст соединений
usermod/useradd -Z связать пользователя с SELinux-пользователем
ausearch -m AVC — показывает нарушения политик
Источники для дополнительного ознакомления:
Last updated