sepgsql

sepgsql — это загружаемый модуль, который поддерживает мандатное управление доступом (Mandatory access control, MAC) с использованием меток, работающее на основе политик безопасности SELinux.

ВНИМАНИЕ!
Текущая реализация имеет существенные ограничения и применяет мандатное управление доступом не для всех действий. См. раздел Ограничения.



Обзор

Этот модуль интегрируется в SELinux, чтобы обеспечить дополнительный уровень проверок безопасности, превышающий те, что предоставляются обычными средствами QHB. С точки зрения SELinux, этот модуль позволяет QHB выполнять роль менеджера объектов в пространстве пользователя. Обращение к каждой таблице или функции, инициируемое запросом DML, будет проверено согласно системной политике безопасности. Эта проверка дополняет обычную проверку разрешений SQL, осуществляемую QHB.

SELinux принимает решения о разрешении доступа на основе меток безопасности, представляемых строками вида system_u:object_r:sepgsql_table_t:s0. В каждом решении учитываются две метки: метка субъекта, пытающегося выполнить действие, и метка объекта, над которым должна совершиться эта операция. Поскольку эти метки могут применяться к объекту любого вида, решения о разрешении доступа к объектам внутри базы данных могут подчиняться (и с этим модулем подчиняются) тем же общим критериям, которые применяются к объектам любого другого типа, например к файлам. Эта конструкция призвана дать возможность организовать централизованную политику безопасности для защиты информационных активов, не зависящую от того, как именно хранятся эти активы.

Назначить метку безопасности объекту базы данных позволяет оператор SECURITY LABEL.



Установка

Модуль sepgsql можно использовать только в Linux 2.6.28 или новее с включенным SELinux. На остальных платформах он недоступен. Также вам понадобится libselinux 2.1.10 или новее и selinux-policy 3.9.13 или новее (хотя в некоторых дистрибутивах можно бэкпортировать необходимые правила к политике старой версии).

Команда sestatus позволяет проверить состояние SELinux. Типичное ее отображение выглядит так:

$ sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted

Если SELinux выключен или не установлен, его необходимо настроить, прежде чем устанавливать этот модуль.

Чтобы собрать этот модуль, добавьте параметр --with-selinux в команду QHB configure. Убедитесь в том, что на момент сборки установлен RPM-пакет libselinux-devel.

Для использования этого модуля следует добавить sepgsql в параметр shared_preload_libraries в qhb.conf. Этот модуль не будет корректно работать, если загрузить его каким-либо иным способом. Когда он загрузится, нужно выполнить sepgsql.sql в каждой базе данных. Этот скрипт установит функции, необходимые для управления метками безопасности, и назначит начальные метки безопасности.

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

$ export PGDATA=/путь/к/каталогу/данных
$ qhb_bootstrap
$ vi $PGDATA/qhb.conf
  изменить
    #shared_preload_libraries = ''                # (после изменения требуется перезапуск)
  на
    shared_preload_libraries = 'sepgsql'          # (после изменения требуется перезапуск)
$ for DBNAME in template0 template1 qhb; do
    qhb --single -F -c exit_on_error=true $DBNAME \
      </usr/local/pgsql/share/contrib/sepgsql.sql >/dev/null
  done

Пожалуйста, обратите внимание, что вы можете увидеть следующие уведомления, в зависимости от конкретных установленных версий libselinux и selinux-policy:

/etc/selinux/targeted/contexts/sepgsql_contexts:  line 33 has invalid object type db_blobs
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 36 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 37 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 38 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 39 has invalid object type db_language
/etc/selinux/targeted/contexts/sepgsql_contexts:  line 40 has invalid object type db_language

Эти сообщения безвредны и их следует игнорировать.

Если процесс установки завершается без ошибок, можно запустить сервер как обычно.



Регрессионные тесты

Учитывая природу SELinux, для проведения регрессионных тестов sepgsql требуется несколько дополнительных этапов конфигурирования, некоторые из которых должен выполнять root. Эти регрессионные тесты не будут запускаться обычной командой make check или make installcheck; необходимо настроить конфигурацию, а затем вызвать тестовый скрипт вручную. Тесты должны запускаться в каталоге contrib/sepgsql сконфигурированного дерева сборки QHB. Несмотря на то, что им требуется дерево сборки, эти тесты рассчитаны на выполнение на установленном сервере, то есть они сравнимы с make installcheck, но не с make check.

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

На втором этапе соберите и установите пакет политики для регрессионного теста. Политика sepgsql-regtest представляет собой политику особого назначения, которая предоставляет набор правил, включаемых во время регрессионных тестов. Ее нужно собрать из исходного файла политики sepgsql-regtest.te, что осуществляется с помощью команды make со скриптом Makefile, предоставляемым SELinux. Вам понадобится найти подходящий Makefile в своей системе; путь, показанный ниже, является всего лишь примером. (Этот Makefile обычно поставляется в пакете RPM selinux-policy-devel или selinux-policy.) Собрав пакет политики, установите его с помощью команды semodule, которая загружает предоставленные пакеты в ядро. Если пакет установлен корректно, команда semodule -l должна показать sepgsql-regtest в списке доступных пакетов политик:

$ cd .../contrib/sepgsql
$ make -f /usr/share/selinux/devel/Makefile
$ sudo semodule -u sepgsql-regtest.pp
$ sudo semodule -l | grep sepgsql
sepgsql-regtest 1.07

На третьем этапе включите параметр sepgsql_regression_test_mode. По соображениям безопасности правила в sepgsql-regtest по умолчанию выключены; параметр sepgsql_regression_test_mode включает правила, необходимые для запуска регрессионных тестов. Включить этот параметр можно командой setsebool:

$ sudo setsebool sepgsql_regression_test_mode on
$ getsebool sepgsql_regression_test_mode
sepgsql_regression_test_mode --> on

На четвертом этапе убедитесь, что ваша оболочка работает в домене unconfined_t:

$ id -Z
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

Если необходимо сменить рабочий домен, подробную информацию об этом см. в разделе Внешние ресурсы.

Наконец, запустите скрипт регрессионного теста:

$ ./test_sepgsql

Этот скрипт попытается проверить, все ли этапы конфигурирования были выполнены корректно, а затем запустит регрессионные тесты для модуля sepgsql.

После завершения тестов рекомендуется выключить параметр sepgsql_regression_test_mode:

$ sudo setsebool sepgsql_regression_test_mode off

Возможно, более предпочтительным будет полностью удалить политику sepgsql-regtest:

$ sudo semodule -r sepgsql-regtest


Параметры GUC

sepgsql.permissive (boolean)
Этот параметр позволяет sepgsql работать в разрешительном режиме, независимо от настроек системы. Значение по умолчанию — off (выключен). Этот параметр можно задать только в файле qhb.conf или в командной строке сервера.
Когда этот параметр включен, sepgsql функционирует в разрешительном режиме, даже если SELinux в целом работает в ограничительном режиме. Этот параметр полезен в первую очередь для тестирования.

sepgsql.debug_audit (boolean)
Этот параметр включает вывод сообщений аудита, независимо от настроек системной политики. Значение по умолчанию — off, означающее, что сообщения будут выводиться согласно настройкам системы.
Политика безопасности SELinux также содержит правила, определяющие, будут ли протоколироваться в журнал определенные обращения. По умолчанию фиксируются нарушения доступа, а успешный доступ — нет.
Этот параметр принудительно включает протоколирование в журнале всех возможных событий, независимо от системной политики.



Функционал

Управляемые классы объектов

Модель безопасности SELinux описывает все правила управления доступом как отношения между сущностью субъекта (обычно это клиент базы данных) и сущностью объекта (например объектом базы данных), каждая из которых определяется меткой безопасности. Если предпринимается попытка доступа к непомеченному объекту, он обрабатывается как объект с меткой unlabeled_t.

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

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


Разрешения для DML

Для всех ссылочных целевых таблиц проверяются разрешения db_table:select, db_table:insert, db_table:update или db_table:delete, в зависимости от вида оператора; кроме того, для всех таблиц, содержащих столбцы, фигурирующие в предложении WHERE или RETURNING, или служащих источником данных для UPDATE и т. п., также проверяется разрешение db_table:select.

Для всех ссылочных столбцов также проверяются разрешения уровня столбцов. Разрешение db_column:select проверяется не только для столбцов, которые считываются оператором SELECT, но и для тех, к которым обращаются другие операторы DML; для столбцов, изменяемых оператором UPDATE или INSERT, также проверяется разрешение db_column:update или db_column:insert соответственно.

Например, рассмотрим запрос:

UPDATE t1 SET x = 2, y = func1(y) WHERE z = 100;

В данном примере разрешение db_column:update будет проверяться для столбца t1.x, так как он изменяется, db_column:{select update} — для t1.y, так как он и изменяется, и считывается, а db_column:select — для t1.z, так как он только считывается. Также на уровне таблицы будет проверяться разрешение db_table:{select update}.

Для последовательностей проверяется разрешение db_sequence:get_value при обращении к объекту последовательности с помощью оператора SELECT; однако обратите внимание, что в настоящее время разрешения на выполнение связанных функций, например lastval(), не проверяются.

Для представлений будет проверяться разрешение db_view:expand, а затем все остальные требуемые разрешения для объектов, развернутых из этого представления, по отдельности.

Для функций будет проверяться разрешение db_procedure:{execute}, когда пользователь попытается выполнить функцию в составе запроса, или при вызове по быстрому пути. Если эта функция является доверенной процедурой, также проверяется разрешение db_procedure:{entrypoint}, чтобы определить, может ли эта функция выступать точкой входа в доверенную процедуру.

Для обращения к любому объекту схемы необходимо разрешение db_schema:search для содержащей его схемы. Когда имя ссылочного объекта не дополняется схемой, схемы, для которых это разрешение отсутствует, не будут просматриваться (то же самое происходит, если у пользователя нет права USAGE для этой схемы). Если имеется явное указание схемы, но у пользователя нет требуемого разрешения для именованной схемы, произойдет ошибка.

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

Система прав базы данных по умолчанию позволяет суперпользователям этой базы изменять системные каталоги с помощью команд DML и обращаться к TOAST-таблицам или модифицировать их. Когда модуль sepgsql активен, эти операции запрещаются.


Разрешения для DDL

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

Для создания нового объекта базы данных требуется разрешение create. SELinux выдает или отказывает в выдаче этого разрешения в зависимости от метки безопасности клиента и предполагаемой метки безопасности нового объекта. В некоторых случаях требуются дополнительные разрешения:

  • Для CREATE DATABASE дополнительно требуется разрешение getattr в исходной или шаблонной базе данных.

  • Для создания объекта схемы дополнительно требуется разрешение add_name в родительской схеме.

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

  • Для создания функции с атрибутом LEAKPROOF дополнительно требуется разрешение install. (Это разрешение также проверяется, когда атрибут LEAKPROOF устанавливается для существующей функции.)

Когда выполняется команда DROP, для удаляемого объекта будет проверяться разрешение drop. Также разрешения будут проверяться для объектов, удаляемых неявно посредством указания CASCADE. Для удаления объектов, содержащихся в определенной схеме (таблиц, представлений, последовательностей и процедур) дополнительно требуется разрешение remove_name в этой схеме.

Когда выполняется команда ALTER, для каждого типа модифицируемого объекта будет проверяться разрешение setattr, за исключением подчиненных объектов, таких как индексы или триггеры таблицы, для которых вместо этого проверяется разрешение родительского объекта. В некоторых случаях требуются дополнительные разрешения:

  • Для перемещения объекта в новую схему дополнительно требуется разрешение remove_name в старой схеме и add_name в новой.

  • Для установки атрибута LEAKPROOF для функции требуется разрешение install.

  • Для использования SECURITY LABEL на объекте дополнительно требуется разрешение relabelfrom для этого объекта в связке со старой меткой безопасности и relabelto для этого же объекта в связке с новой меткой безопасности. (В тех случаях, когда установлено несколько поставщиков меток и пользователь пытается задать метку безопасности, неподконтрольную SELinux, должно проверяться только разрешение setattr. В настоящее время этого не происходит из-за ограничений реализации.)


Доверенные процедуры

Доверенные процедуры схожи с функциями, определяющими контекст безопасности, или командами setuid. SELinux предоставляет возможность запускать доверенный код с меткой безопасности, отличной от метки клиента, обычно с целью предоставления тщательно контролируемого доступа к важным данным (при этом, к примеру, могут отбрасываться строки или может быть снижена точность хранимых значений). Будет ли функция действовать как доверенная процедура, определяется ее меткой безопасности и политикой безопасности операционной системы. Например:

qhb=# CREATE TABLE customer (
               cid     int primary key,
               cname   text,
               credit  text
           );
CREATE TABLE
qhb=# SECURITY LABEL ON COLUMN customer.credit
               IS 'system_u:object_r:sepgsql_secret_table_t:s0';
SECURITY LABEL
qhb=# CREATE FUNCTION show_credit(int) RETURNS text
             AS 'SELECT regexp_replace(credit, ''-[0-9]+$'', ''-xxxx'', ''g'')
                        FROM customer WHERE cid = $1'
           LANGUAGE sql;
CREATE FUNCTION
qhb=# SECURITY LABEL ON FUNCTION show_credit(int)
               IS 'system_u:object_r:sepgsql_trusted_proc_exec_t:s0';
SECURITY LABEL

Показанные выше операции должен выполнять пользователь с правами администратора.

qhb=# SELECT * FROM customer;
ERROR:  SELinux: security policy violation
-- ОШИБКА:  SELinux: нарушение политики безопасности
qhb=# SELECT cid, cname, show_credit(cid) FROM customer;
 cid | cname  |     show_credit
-----+--------+---------------------
   1 | taro   | 1111-2222-3333-xxxx
   2 | hanako | 5555-6666-7777-xxxx
(2 rows)

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


Динамические переключения домена

Функциональную возможность динамического переключения между доменами SELinux можно использовать для перевода метки безопасности клиентского процесса, клиентский домен, в новый контекст, если это допускается политикой безопасности. Для этого клиентскому домену нужно разрешение setcurrent, а также разрешение dyntransition для перехода из старого в новый домен.

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

regression=# select sepgsql_getcon();
                    sepgsql_getcon
-------------------------------------------------------
 unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c4');
 sepgsql_setcon
----------------
 t
(1 row)

regression=# SELECT sepgsql_setcon('unconfined_u:unconfined_r:unconfined_t:s0-s0:c1.c1023');
ERROR:  SELinux: security policy violation
-- ОШИБКА:  SELinux: нарушение политики безопасности

В этом примере нам позволили переключиться из более широкого диапазона MCS c1.c1023 в более узкий c1.c4, но в обратном переключении было отказано.

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


Прочее

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



Функции sepgsql

В Таблице 30 перечислены доступные функции.

Таблица 30. Функции sepgsql

Функция
Описание
sepgsql_getcon () → text
Возвращает клиентский домен, текущую метку безопасности клиента.
sepgsql_setcon ( text ) → boolean
Переключает клиентский домен текущего сеанса в новый домен, если это допускает политика безопасности. Также принимает в аргументе NULL в качестве запроса на переход в исходный домен клиента.
sepgsql_mcstrans_in ( text ) → text
Переводит заданный диапазон MLS/MCS из полной записи в низкоуровневый формат, если работает демон mcstrans.
sepgsql_mcstrans_out ( text ) → text
Переводит заданный диапазон MLS/MCS из низкоуровневого формата в полную запись, если работает демон mcstrans.
sepgsql_restorecon ( text ) → boolean
Устанавливает начальные метки безопасности для всех объектов в текущей базе данных. В аргументе может передаваться NULL или имя файла спецификации для использования вместо стандартного системного.


Ограничения

Разрешения для языка определения данных (Data Definition Language, DDL)

Из-за ограничений реализации для некоторых операций DDL разрешения не проверяются.

Разрешения для языка управления данными (Data Control Language, DCL)

Из-за ограничений реализации для некоторых операций DCL разрешения не проверяются.

Управление доступом на уровне строк

QHB поддерживает доступ на уровне строк, а sepgsql — нет.

Скрытые каналы

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



Внешние ресурсы

SE-PostgreSQL Introduction, Введение в SE-PostgreSQL

На этой вики-странице представлен краткий обзор и описание архитектуры и проекта безопасности, администрирования и ожидаемых в будущем возможностей расширения SE-PostgreSQL.

SELinux User's and Administrator's Guide, Руководство пользователя и администратора SELinux

В этом документе представлен широкий спектр знаний по администрированию SELinux в операционных системах. В первую очередь он ориентирован на системы Red Hat, но не ограничивается только ими.

Fedora SELinux FAQ, FAQ по SELinux в ОС Fedora

В этом документе даются ответы на часто задаваемые вопросы по SELinux. В первую очередь он ориентирован на ОС Fedora, но не ограничивается только ей.


Автор

КайГай Кохэй (KaiGai Kohei), kaigai@ak.jp.nec.com