Сообщений 0 Оценка 0 Оценить |
Все мы давно привыкли к разграничению доступа к приложениям и файлам на наших компьютерах на основе избирательного управления доступом (Discretionary Access Control или DAC). Обычно подобная система выглядит как ограниченный в правах пользователь, имеющий доступ к ряду строго определенных ресурсов (файлам, приложениям и т.д.), и администратор, обладающий полным доступом ко всем ресурсам системы.
В целом подобное разграничение представляется достаточным для большинства ситуаций или иногда даже избыточным с точки зрения пользователя, что подтверждает изрядное их количество, работающее на своих компьютерах с правами администратора.
Тем не менее, довольно часто возникают ситуации, когда разграничение прав на основе DAC становится недостаточным, причем не только в случае с корпоративными, но и домашними пользователями. Так, типичной ситуацией с корпоративными пользователями является использование систем предотвращения утечек информации (Data Loss Prevention или DLP), доступа к управлению которым пользователь, даже обладающий правами администратора, иметь не должен. Отличным примером недостаточности DAC как для корпоративных, так и для домашних пользователей могут послужить антивирусы и межсетевые экраны. К примеру, довольно известный Flashback.C OS X Trojan попросту удалял встроенный антивирус Apple из автозагрузки, чему немало способствовал тот факт, что создаваемый на Mac OS X пользователь по умолчанию обладает правами администратора и является sudoer-ом.
Собственно, идея написания этой статьи как раз и родилась из общения с компанией, занимающейся разработкой DLP-систем, которая хотела защитить свое детище от удаления пользователями с правами администратора на компьютерах под управлением Mac OS X.
К счастью, подобная задача довольно легко решается в Mac OS X, так как система имеет встроенные средства для реализации разграничения доступа на основе мандатного управления доступом (Mandatory Access Control или MAC). В общем случае под MAC понимается разграничение доступа к объектам, основанное на назначении метки конфиденциальности для информации, содержащейся в объектах, и выдаче разрешений на обращение к информации такого уровня конфиденциальности. Таким образом, в случае с MAC, вне зависимости от того, кто обращается к ресурсу, простой пользователь или администратор, появляется прекрасная возможность отфильтровать попытку доступа и пресечь ее при необходимости.
Существует довольно большое количество реализаций концепции MAC на разных платформах. Так, в случае Linux это будет SELinux и AppArmor, в Solaris — Solaris Trusted Extensions, ну а в BSD или Mac OS X — TrustedBSD. В рамках данной статьи речь пойдет исключительно о работе с версией TrustedBSD для Mac OS X.
Фреймворк TrustedBSD на Mac OS X появился довольно давно, и основная масса интерфейсов доступна, начиная с версии 10.5. Сам фреймворк довольно активно используется Apple как в Mac OS X, так и в iOS для изоляции приложений посредством «песочницы». К сожалению, уже существующая «песочница» не позволяет защитить приложение от пользователя, и нацелена на защиту пользователя от приложения, так что для решения описанной выше проблемы не подходит. Но это ничуть не мешает воспользоваться TrustedBSD и написать расширение для него.
СОВЕТ Документация Apple, посвященная TrustedBSD, крайне скудна, и при поиске информации лучше всего использовать «FreeBSD Architecture Handbook», в которой приводится качественное описание TrustedBSD. В целом, интерфейсы, предоставляемые TrustedBSD для Mac OS X и FreeBSD, схожи, но обычно имеют несколько отличающиеся имена. К примеру, функция обратного вызова mpo_vnode_check_open (которая будет использоваться в примере чуть ниже) в случае с FreeBSD будет называться mpo_check_vnode_open. Это несколько затрудняет работу с фреймворком, так как приходится угадывать имена интерфейсов, но позволяет получить более полную картину происходящего. |
При помощи TrustedBSD можно фильтровать практически все события, возникающие в процессе работы приложения. Фильтруемые события можно условно разделить на несколько групп:
Хотя данный список не является исчерпывающим, он охватывает основную массу возможностей, предоставляемых TrustedBSD, и позволяет получить представления о возможностях фреймворка.
Теперь можно перейти к практической части и реализовать TrustedBSD-расширение, обеспечивающее ограничение доступа к определенным файлам. Написание подобного расширения не потребует каких-то особых знаний и умений, достаточно создать шаблонный драйвер при помощи Xcode, так как расширения TrustedBSD представляют собой не что иное, как kext-модули, и реализовать пару обработчиков.
СОВЕТ Данная статья не рассматривает вопросы, связанные с созданием, загрузкой, выгрузкой драйверов для Mac OS X или обеспечением взаимодействия между драйвером и пространством пользователя. Если эти вопросы в новинку, то стоит ознакомиться с великолепным введением в разработку драйверов для Mac OS X, «Kernel Extension Programming Topics», которое можно найти на сайте developers.apple.com. |
Непосредственная работа с фреймворком TrustedBSD очень проста. Дело в том, что разработчику доступны всего две функции: mac_policy_register и mac_policy_unregister, которые отвечают за регистрацию и дерегистрацию политик, соответственно.
Для регистрации политик необходимо заполнить две структуры: mac_policy_conf и mac_policy_ops. Структура mac_policy_ops хранит в себе указатели на пользовательские функции обратного вызова, используемые для обработки возникающих событий. В структуру mac_policy_conf помещается служебная информация о конфигурации политики: имя политики, указатель на структуру mac_policy_conf, флаги, управляющие возможностью выгрузки политики, и т.д.
Удобнее всего выполнять действия, связанные с инициализацией политик, из точки входа драйвера, а дерегистрацию – при его завершении. Таким образом, в рассматриваемом примере код инициализации будет предельно прост.
// Заполним структуру указателями на функции обратного вызова. static struct mac_policy_ops mac_ops ={ .mpo_policy_initbsd = mac_policy_initbsd, // инициализация политики .mpo_vnode_check_open = mac_policy_open, // обработчик открытия файла .mpo_vnode_check_unlink = mac_policy_unlink, // обработчик удаления файла}; } // А также структуру, содержащую информацию о нашей политике.staticstruct mac_policy_conf mac_policy_conf = { .mpc_name = "protect_demo", .mpc_fullname = "Protect demo!", .mpc_labelnames = NULL, .mpc_labelname_count = 0, .mpc_ops = &mac_ops, .mpc_loadtime_flags = MPC_LOADTIME_FLAG_UNLOADOK, // Политика ВЫГРУЖАЕМА! .mpc_field_off = NULL, .mpc_runtime_flags = 0 }; // Указатель на зарегистрированную политику. // Необходим для дерегистрации политики.static mac_policy_handle_t mac_handle; // Точка входа драйвераint PolicyKext_start(void * d) { // В случае успешного выполнения функции mac_policy_register // в переменную mac_handle будет записан указатель // на зарегистрированную политику.// Зарегистрируем политику.return mac_policy_register(&mac_policy_conf, &mac_handle, d); } |
Дерегистрация политики осуществляется еще проще.
// Точка выхода драйвера.int PolicyKext _stop() { return mac_policy_unregister(mac_handle); // Дерегистрируем политику. } |
Стоит также обратить внимание на функцию обратного вызова mac_policy_initbsd. Данная функция вызывается после того, как политика была загружена и инициализирована, и в нашем случае представляет собой просто заглушку. Если же возникает необходимость в размещении в mac_policy_initbsd дополнительной логики, важно помнить о том, что при загрузке политик, на старте операционной системы, данная функция будет вызвана до старта процесса kernel_task (самый первый процесс, PID которого всегда равно 0). Вызов функции wait из mac_policy_initbsd запрещен, прочие вызовы рекомендуется делать с осторожностью.
Нельзя обойти стороной такой важный вопрос, как выгрузка политик. Очевидно, что в процессе разработки политики должны быть выгружаемыми, а в версии, включенной в финальный продукт, наоборот, не выгружаемыми (за редкими исключениями). Чтобы политика была выгружаемой, при ее регистрации необходимо установить в поле mpc_loadtime_flags структуры mac_policy_conf значение MPC_LOADTIME_FLAG_UNLOADOK. Для запрета выгрузки политики данное поле должно быть инициализировано 0. Это не единственно возможные значения флага, и за более подробной информацией стоит обратиться к документации.
Теперь осталось совсем немного, необходимо написать обработчики следующего вида для событий открытия и удаления файлов:
В обоих случаях наибольший интерес представляет собой структура vnode – vp, содержащая информацию об объекте, к которому пытаются получить доступ. Довольно много полезной информации можно извлечь и из структуры kauth_cred_t, например, эффективный и реальный идентификаторы и группы пользователя.
Заключительный шаг – получить информацию об имени текущего процесса, его PID и имя файла, к которому обращаются. Для этого понадобятся следующие функции:
Пора переходить к примерной реализации обработчиков, описанных выше:
static int is_file_accessible(struct vnode *vp) { constchar *vname = NULL; char cbuf[MAXCOMLEN+1]; int retvalue = 0; if (vp == NULL) // В ряде случаев отсутствие информации о ноде нормально,// поэтому разрешаем продолжить выполнение функции.return (retvalue); vname = vnode_getname(vp); if(vname) // Имя нода не пустое { // И идет попытка получить// доступ к конфигурационному файлу, отвечающему за запуск антивирусаif(strcasecmp(vname, "com.apple.xprotectupdater.plist") == 0) { proc_selfname(cbuf, sizeof(cbuf)); // и процесс обращающийся к файлу не является // системой обновления антивирусаif (strcasecmp(cbuf,"XProtectUpdater")) { retvalue = EPERM; // Доступ необходимо заблокировать. } } vnode_putname(vname); // Очистим запрошенное ранее имя нода } return(retvalue); } staticint mac_policy_open( kauth_cred_t cred, struct vnode *vp, struct label *label, int acc_mode) { return is_file_accessible(vp); } staticint mac_policy_unlink( kauth_cred_t cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp) { return is_file_accessible(vp); } |
Как видно из данных примеров, реализация расширения для TrustedBSD не является чем-то сложным или запутанным. При этом такое расширение позволяет легко контролировать практически все аспекты выполнения процессов на компьютере.
Сообщений 0 Оценка 0 Оценить |