Особенности применения мандатной модели управления доступом Astra Linux при разработке веб-приложений +9




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

Мандатная модель управления доступом (далее будем называть её MAC) используется в специализированных системах, связанных с обработкой секретной информации, требующей особых правил управления доступом. Эти правила достаточно подробно расписаны в специализированной литературе.

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

Данная статья является сборником практических рецептов и рекомендаций, цель которой — упростить разработку приложений для мандатной модели управления доступом Astra Linux. Данный опыт приобретён нашей командой в процессе разработки системы управления инцидентами информационной безопасности Jet Signal. Система Jet Signal использует следующий стек технологий: PHP5.4/7.2, Yii2, ReactJS, PostgreSQL, RabbitMQ, поэтому листинги кода будут указаны на языке PHP, частично будут использоваться функции фреймворка Yii2, SQL-запросы PostgreSQL.

Мандатная модель в Astra Linux


Мандатная модель Astra Linux (далее будем использовать термин MAC, от англ. Mandatory Access Control) реализует два ключевых понятия: мандатные уровни и мандатные категории доступа. Мандатные уровни (мандатные метки) используются для пометки субъектов и объектов, чтобы обозначить тот или иной мандатный уровень доступа. Мандатные категории могут быть использованы для разграничения доступа по структурным подразделениям организации. Мандатная метка объекта в AL описывается целым числом, и всегда хранится в тесной связке с помеченным объектов.

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

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

В ОС поставляется набор приложений, в которых реализована полная поддержка мандатной модели управления доступом. Данные приложения предоставляют функциональность обработки объектов приложения (записей в БД, дочерних процессов и т.д.) с учётом правил и требований MAC. Наиболее важными из них для нас являются:

  • СУБД PostgreSQL. PostgreSQL имеет интеграцию с хранилищем учётных записей и мандатных меток ОС. СУБД предоставляет функциональность присваивания мандатной метки к таким объектам, как кластер, база данных, таблица, столбец и запись.
  • Веб-сервер Apache2. Обязателен при разработке веб-приложений. Позволяет считывать мандатную метку посредством модуля pam_auth, создавать процессы веб-приложения в режиме мандатной метки, переданной из браузера.
  • Браузер Mozilla Firefox. Обязателен для работы с приложением в режиме мандатной метки. Позволяет транслировать мандатную метку в веб-сервер Apache2.

Также в нашем распоряжении функциональность MAC файловой системы, позволяющая устанавливать диапазоны разрешённых мандатных меток на каталоги, устанавливать мандатные метки на файл, и многое другое.

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

Проектирование и разработка веб-приложения, поддерживающего мандатную модель управления доступом


MAC накладывает ограничения на проектирование приложения. То, что в приложении на обычной ОС (без мандатных меток) кажется тривиальным, в Astra Linux может принести множество неожиданных сюрпризов, которые обычно выявляются тогда, когда всё уже реализовано…

Именно поэтому имеется первая, но крайне важная рекомендация:

Предусмотрите в вашем приложении параметр (например, MAC_ENABLED), позволяющий включать и выключать поддержку мандатных меток централизованно, в одном месте. И пользуйтесь этим параметром во всех местах, в любых условных конструкциях, которые напрямую или косвенно сталкиваются с инфраструктурой MAC Astra Linux.

Этим вы сохраните своему приложению возможность развиваться с любыми другими Linux и не-Linux операционными системами. Если даже речь не идёт о production-использовании данного параметра, возможность завести приложение внутри Docker-контейнера может дорогого стоить!

Использование мандатной модели управления доступом порой вносит серьёзные коррективы в бизнес-логику приложения. Это та самая инфраструктура, абстрагироваться от которой очень сложно, а порой — невозможно. И крайне неприятен тот факт, часто нюансы работы с мандатными метками выявляются после проведения работ по аналитике, проектированию и разработке — на этапе тестирования. А это приводит к потенциальному росту затрат на полный цикл разработки в 10 и более раз.

Поэтому при проектировании приложения под Astra Linux обязательно необходимо выделить модули, в которых требуется поддержка нескольких мандатных меток.

Для модуля возможны следующие варианты:

  • Модуль работает с данными только 0 мандатной метки;
  • модуль работает с данными только одной, не 0 мандатной метки;
  • модуль работает с данными нескольких мандатных меток.

При проектировании следует постараться обеспечить минимальную связность (cohesion) модулей, работающих в различных парадигмах обработки мандатных меток.

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


Этот кейс является наиболее простым случаем. Проектирование модуля в режиме работы с данными 0 метки целесообразно в следующих случаях:

  • Модуль обрабатывает системную информацию, которая не является секретной, и используется приложением для решения своих внутренних задач. Например, модуль управления RBAC (ролевой моделью управления доступом), обрабатывающий списки пользователей, ролей и операций.
  • Модуль сильно связан с инфраструктурой операционной системы, которая ограничивает использование модуля в режиме мандатной метки, отличной от 0.

При выполнении операций, связанных с мандатной меткой, рекомендуется выполнять следующие проверки:
  • Проверять, включены ли мандатные метки (на основе глобального параметра приложения MAC_ENABLED);
  • проверять текущую мандатную метку процесса; если метка не равна 0 — запрещать доступ к операции.

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

В системе Jet Signal примером такого модуля является модуль «Безопасность», реализующий управление учётными записями пользователей, ролями и операциями:



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

При использовании данного кейса можно практически ни о чём не беспокоиться: тестирование и отладка 0 мандатной метки практически ничем не отличается от отладки обычного приложения. Но самое интересное начинается, когда в ход идут другие мандатные метки…

Случай средней сложности: модуль работает с данными только одной, не 0 мандатной меткой


Этот кейс чуть сложнее, но во многом похож на случай с 0 мандатной меткой.

Данный кейс может быть полезен в следующих случаях:

  • Была допущена ошибка при аналитике и проектировании модуля (не были заложены особенности обработки записей в MAC) и нет ни времени, ни ресурсов всё переписывать;
  • в соответствии с бизнес-требованиями модуль должен обрабатывать именно указанную мандатную метку.

Для поддержки данного кейса рекомендуется добавить в приложение параметр, хранящий мандатную метку по умолчанию (например, MAC_DEFAULT_LEVEL).

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

На что следует обратить внимание при реализации подобного кейса:

  • Нельзя менять мандатную метку по умолчанию (MAC_DEFAULT_LEVEL) в процессе эксплуатации приложения. Это гарантированно приведёт к неожиданным и сложным в диагностике проблемам, а бизнес-логика приложения может попросту развалиться.
  • По возможности следует добавить проверку мандатной метки какой-нибудь эталонной записи, создаваемой при инсталляции приложения, и данного параметра. В случае некорректной установки параметра приложению следует бить в колокола и звать на помощь системного администратора!

Сложный случай: модуль работает с данными нескольких мандатных меток


Это самый сложный кейс, требующий основательного проектирования и обдумывания.
Он полезен только в одном случае: вам необходимо обрабатывать данные нескольких мандатных меток! Просто взять и переложить эту ответственность на базу данных не получится — эти данные необходимо разграничивать и обрабатывать на прикладном уровне по различным правилам.

Для полноценной реализации данного кейса необходимо спроектировать в приложении следующие функции:

  • Функция получение мандатной метки текущего процесса приложения;
  • функция получения мандатной метки записи (если речь идёт о работе с записью в БД) или файла (если мы обрабатываем файлы в каталоге);
  • функция получения мандатной метки записей/файлов в коллекции.


Получение мандатной метки текущего процесса приложения


Для получения мандатной метки текущего процесса приложения мы используем команду:

if (!$pid) {
    $pid = 0;
}
$macLevel = trim(shell_exec("/usr/bin/psmac -n $pid"));

Получение мандатной метки записи в базе данных


Для получения мандатной метки записи в базе данных потребовалось доработать механизм чтения схемы БД. Мандатная метка записи в БД хранится в поле maclabel.

При выполнении SQL-запроса SELECT * FROM public.incident; СУБД вернёт все имеющиеся столбцы, но не вернёт столбец, содержащий мандатную метку записи. Делать это необходимо принудительно:

SELECT *,maclabel FROM public.incident;

В результате получим выборку, содержащую maclabel (пропущены остальные столбцы):

        id        | maclabel
------------------+----------
 2806503429898302 | {0,0}
 2806503429898372 | {0,0}
 2806503429898303 | {0,0}

Доработка запроса получения схемы фреймворком для ORM


Большинство фреймворков, предоставляющих функциональность ORM, требуют доработки функции чтения схемы БД и конструктора запросов, чтобы «научиться» читать и писать корректным образом столбец maclabel. Например, в Yii2 была произведена доработка запроса получения схемы (компонент yii\db\Schema) следующим образом:

SELECT
    d.nspname AS table_schema,
    c.relname AS table_name,
    a.attname AS column_name,
    t.typname AS data_type,
    a.attlen AS character_maximum_length,
    pg_catalog.col_description(c.oid, a.attnum) AS column_comment,
    a.atttypmod AS modifier,
    a.attnotnull = false AS is_nullable,
    CAST(pg_get_expr(ad.adbin, ad.adrelid) AS varchar) AS column_default,
    coalesce(pg_get_expr(ad.adbin, ad.adrelid) ~ 'nextval',false) AS is_autoinc,
    array_to_string((select array_agg(enumlabel) from pg_enum where enumtypid=a.atttypid)::varchar[],',') as enum_values,
    CASE atttypid
         WHEN 21 /*int2*/ THEN 16
         WHEN 23 /*int4*/ THEN 32
         WHEN 20 /*int8*/ THEN 64
         WHEN 1700 /*numeric*/ THEN
              CASE WHEN atttypmod = -1
               THEN null
               ELSE ((atttypmod - 4) >> 16) & 65535
               END
         WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
         WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
         ELSE null
      END   AS numeric_precision,
      CASE
        WHEN atttypid IN (21, 23, 20) THEN 0
        WHEN atttypid IN (1700) THEN
        CASE
            WHEN atttypmod = -1 THEN null
            ELSE (atttypmod - 4) & 65535
        END
           ELSE null
      END AS numeric_scale,
    CAST(
             information_schema._pg_char_max_length(information_schema._pg_truetypid(a, t), information_schema._pg_truetypmod(a, t))
             AS numeric
    ) AS size,
    a.attnum = any (ct.conkey) as is_pkey
FROM
    pg_class c
    LEFT JOIN pg_attribute a ON a.attrelid = c.oid
    LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
    LEFT JOIN pg_type t ON a.atttypid = t.oid
    LEFT JOIN pg_namespace d ON d.oid = c.relnamespace
    LEFT join pg_constraint ct on ct.conrelid=c.oid and ct.contype='p'
WHERE
    ((a.attnum > 0 and t.typname != '') or (a.attname = 'maclabel'))
    and c.relname = {$tableName}
    and d.nspname = {$schemaName}
ORDER BY
    a.attnum;

В запрос было добавлено считывание параметра a.attname = 'maclabel'.

Бизнес-процессы при использовании нескольких мандатных меток


Указанные выше функции очень понадобятся нам при реализации обязательных для обработки множества мандатных меток бизнес-процессов:

  • Разрешение/запрещение редактирования записи/файла с мандатной меткой, отличной от мандатной метки текущего процесса;
  • получение коллекции записей/файлов с определённой мандатной меткой (фильтрация обрабатываемых данных на основе мандатной метки).

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

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

Например, в системе Jet Signal реализована обработка записей с учётом мандатной метки: пользователь не может отредактировать запись, если метка текущего сеанса пользователя не соответствует мандатной метке приложения.

В системе Jet Signal реализована поддержка нескольких мандатных меток в модуле управления инцидентами информационной безопасности. Мандатная метка каждой записи выводится справа в пользовательском интерфейсе:



Также мандатная метка в сокращённом виде выводится в карточке каждой записи в интерфейсе системы (возле номера — «СС», совершенно секретно):



Управление структурой базы данных


Современные веб-приложения самостоятельно осуществляют управление базой данных при помощи механизмов миграции. Но мандатная модель Astra Linux накладывает свои ограничения. Для того, чтобы полноценно использовать мандатные метки на базе данных, нам необходимо выполнить целый ряд команд на всех основных объектах БД: кластере, базе данных, схемах, таблицах… и даже sequence и триггерах! Вручную, как указано в руководстве администратора, это непостижимая работа.

Именно поэтому рекомендуется предусмотреть механизм, который будет в автоматическом режиме считывать структуру базы данных и производить последовательную установку мандатных меток на объекты БД.

Мы реализовали компонент, который производит установку мандатных меток командами MAC LABEL и MAC CCR на следующие объекты:

  • База данных (database);
  • схема (schema);
  • последовательность (sequence);
  • таблица (table).

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

Аутентификация пользователя и использование учётных данных


Для полноценной работы веб-приложения в Astra Linux необходимо использование учётных данных, хранящихся в операционной системе. Именно для этого требуется реализация в приложении многоуровневой схемы аутентификации — проверка на уровне операционной системы, затем на уровне СУБД, и уже после этого на уровне хранилища учётных данных самого приложения.

Общая схема использования данных аутентификации выглядит следующим образом:



На схеме изображено следующее взаимодействие:

  1. Веб-сервер получает данные аутентификации от браузера с АРМ пользователя, производит их сверку с учётной записью пользователя в ОС;
  2. если всё в порядке, веб-сервер порождает процесс PHP-приложения Сигнал (с ретрансляцией мандатной метки) и передаёт в переменных логин и пароль;
  3. PHP-приложение производит проверку данных аутентификации в СУБД, пытаясь подключиться с ними; производится ретрансляция мандатной метки пользователя в подключение СУБД;
  4. если всё в порядке, PHP-приложение производит проверку учётной записи пользователя на основе своей таблицы в БД;
  5. если всё в порядке — пользователь считается аутентифицированным и допускается в приложение с установленными в RBAC/ACL приложения ролями.

Аутентификация пользователя в веб-приложении


Получение логина и пароля пользователя производится веб-сервером Apache2 от браузера Mozilla Firefox посредством модуля аутентификации HTTP Basic.

В результате работы цепочки «браузер — веб-сервер» приложении можно прочитать открытым текстом пару логин-пароль, которые попадают в переменные окружения веб-сервера.
Листинг PHP-кода с примером получения учётных данных пользователя и многоуровневой аутентификации в приложении

public function authenticate($user, $request, $response)
{
    $login = $request->authUser;
    $password = $request->authPassword;
    $connection = Yii::$app->get('db');

    if ($connection->isActive) {
        $connection->close();
    }
    $connection->username = $login;
    $connection->password = $password;
    $connection->open();
    
    Yii::$app->set('db', $connection);

    $model = new UserORM(['scenario' => 'login']);
    $model->setAttributes(compact('login', 'password'));

    if (!$model->login(0)) {
        throw new UnauthorizedHttpException();
    }

    return Yii::$app->user;
}

В данном примере реализуется следующий алгоритм:

  1. Получаем пару логин-пароль из переменной окружения REQUEST;
  2. Производим попытку подключиться с указанными учётными данными к БД;
  3. Если попытка успешна — производим проверку пользователя в БД и попытку его аутентификации.

Особенности метода аутентификации


Для поддержания корректной работы механизма HTTP Basic необходимо производить выполнение данной функции на каждый запрос. Это позволяет не сохранять учётные данные между запросами в небезопасных хранилищах, управляемых приложением, и полностью довериться средствам защиты операционной системы.

Минусы данного метода аутентификации:

  • Обработка логина и пароля в открытом виде. Следует следить за использованием данных текстовых данных в приложении. Рекомендуется использовать их только в рамках одной функции, а после желательно «подчищать». Это позволит быть уверенным, что никто не использует их не по назначению.
  • Отсутствие возможности нормального «выхода» из системы с целью дальнейшего входа под другой учётной записью. Для решения этой проблемы придётся реализовать воркэраунд, подменяющий учётные данные на данные несуществующей учётной записи, чтобы получить ошибку и благополучно завершить сессию.

В итоге получается надёжный механизм аутентификации, позволяющий порождать процессы приложения с мандатной меткой пользователя АРМ, работающего с браузером Mozilla Firefox. Данная реализация механизма аутентификации опробована на практике и показала себя с положительной стороны.

Работа веб-приложения с файлами и каталогами


При выполнении своих задач веб-приложение часто формирует следующие файлы:

  • Логи приложения;
  • кеш;
  • статика CSS+JS (в случае сборки «на лету»).

В классическом веб-приложении достаточно выполнить chmod -R 775 и chown -R www-data:www-data, и дело за малым! Тут такой номер не пройдёт.

В Astra Linux используется целый «бутерброд» из средств управления доступом к файлам и каталогам:

  • Стандартные средства разграничения прав доступа к фалам и каталогам (chmod/chown);
  • механизм ACL (getfacl/setfacl);
  • мандатная модель (pdpl-file).

Поддержка трёх средств управления доступом к файлам в веб-приложении


Большинство фреймворков и библиотек не понимают таких сложностей, и поэтому может потребоваться «научить» фреймворк правильно понимать следующие вещи:

  • Имеется ли права на запись в каталог/файл?
  • Существует ли каталог или файл в ФС?

Рецепт прав на каталог, хранящий файлы/подкаталоги с мандатной меткой:

mkdir -p $path
chgrp -R www-data $path;
chmod -R 775 $path;
setfacl -Rm "g:www-data:rwx" $path
pdpl-file -v $mac:0:0:ccnr $path

Где $path — путь к каталогу, а $mac — мандатная метка, соответствующая объектам, хранимым в каталоге.

Всем учётным записям пользователей приложения после создания необходимо выставлять группу www-data: adduser admin www-data

Хранение файлов с различными мандатными метками


Если нам необходимо хранить файлы с различными мандатными метками, следует делать это по отдельности, в разных каталогах!

Например, журналы, кеш и прочие файлы пишутся у нас в каталог /var/www/webapp/runtime/. В таком случае создаём на каждую метку свой подкаталог:

  • /var/www/webapp/runtime/0/ — для 0 метки;
  • /var/www/webapp/runtime/1/ — для 1 метки;
  • и т.д.

При этом каталоги /var/www, /var/www/webapp/ и /var/www/webapp/runtime при помощи команды pdpl-file должны получить максимальную мандатную метку приложения, так как включают в себя другие объекты (каталоги) с различными мандатными метками.

Использование указанных рецептов по работе с файлами позволит избежать множества проблем и трат времени.

Резюме


Тема использования мандатных меток при разработке приложений обширна, и одной статьёй покрыть её практически невозможно.

Главный вывод: инфраструктура оказывает сильное влияние на бизнес-процессы приложения при использовании мандатной модели управления доступом. Имеется целый ряд функциональных ограничений, допустимых в классическом бизнес-прилжении, и невозможных при использовании мандатной модели. Всем участникам процесса проектирования и подготовки требований к системе необходимо детально ознакомиться со всеми нюансами применения мандатной модели управления доступом.

Дмитрий Грудинин, руководитель группы PHP-разработки. Центр внедрения бизнес-систем «Инфосистемы Джет»




К сожалению, не доступен сервер mySQL