Поддержка Консалтинг Обучение Jamf Pro Блог

Sandboxing в OS X

Василий Колосов 14.12.2010

Люблю иногда читать на сайте Apple описания их продуктов. Настоящие шедевры в некотором роде: вроде и примелькались со временем все эти «amazing», да «revolutionary», но, тем не менее, гипнотическое воздействие по прежнему велико. Смотришь, бывает, описание нового MacBook Air, и аж слезы к глазам подступают, эмоции теснят грудь, а душа полнится сладостным ощущением превосходства яблочной продукции.

И вот так, смакуя раздел «Security» на страничке Mac OS X, наткнулся я на крошечное упоминание применения в операционной системе sandbox-технологий. Однако, быстрый поиск показывает удивительную вещь: единственным более-менее известным приложением, применяющим сэндбоксинг,  является Google Chrome и… все! Почему же так?

Как это работает

Что такое вообще есть sandbox?  В переводе с английского — песочница, в данном случае для программ. Пользователь запускает приложение в изолированной среде, где оно (теоретически) никак не сможет навредить системе или выполнять определенные действия. В Mac OS X это реализуется при помощи трех компонентов:

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

—   Команды sandbox-exec, запускающей приложение с определенным ранее sandbox-профилем.

—   Расширения ядра sandboxd, реализующего сам функционал.

А теперь давайте заглянем в директорию /usr/share/sandbox.  Что же мы видим?

iMac-Steve-Ballmer:sandbox ballmer$ ls

awacsd.sb               ntpd.sb

bsd.sb                  portmap.sb

cvmsCompAgent.sb        quicklookd-job-creation.sb

cvmsServer.sb           quicklookd.sb

fontmover.sb            sshd.sb

kadmind.sb              syslogd.sb

krb5kdc.sb              xgridagentd.sb

mDNSResponder.sb        xgridagentd_task_nobody.sb

mds.sb                  xgridagentd_task_somebody.sb

mdworker.sb             xgridcontrollerd.sb

named.sb<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; line-height: 19px; white-space: normal; font-size: 13px;"> </span>

Ага! Знакомые имена файлов, не правда ли? Можно предположить, что в Apple подумали о нашей с вами безопасности и загнали некоторые потенциально опасные службы в «песочницу». К сожалению, дальше создания профилей дело не пошло, и на практике все эти процессы запускаются в обычном режиме, хотя в соответствующих файлах конфигурации (например, в com.apple.syslogd.plist) можно включить запуск в sandbox-режиме.

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

(version 1)

(debug deny)

(deny default)

(allow process*)

(deny signal)

(allow sysctl-read)

(allow network*)

;;; Allow NTP specific files

(allow file-read-data file-read-metadata

(regex "^(/private)?/etc/ntp\\.(conf|keys)$"))

(allow file-read-data file-read-metadata file-write-data

(regex "^(/private)?/var/db/ntp\\.drift(\\.TEMP)?$"))

(allow file-write* file-read-data file-read-metadata

(regex "^(/private)?/var/run/ntpd\\.pid$"))

(allow time-set)

(import "bsd.sb")

Для sandbox-профилей вместо привычного XML применяется форма записи параметров в виде описания правила, заключенного в круглые скобки. Сначала идет разрешение или запрет какого-либо действия (allow или deny), а потом описание самого действия. К примеру:
(allow network*)

разрешает приложению любые сетевые соединения, а (deny signal) запрещает отсылать какие-либо системные сигналы.

Строчка (debug deny)  указывает, что все отклоненные действия будут записаны в файл /var/log/system.log.  Затем следует правило (deny default), запрещающее любую активность кроме той, что будет явно объявлена ниже.

(allow process*) разрешает запуск и остановку любых процессов, а (allow sysctl-read) — чтение параметров системы через sysctl.

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

(regex "^(/private)?/etc/ntp\\.(conf|keys)$")

Предпоследняя строчка  (allow time-set) разрешает изменение времени системы. Наконец, (import “bsd.sb”) импортирует правила из профиля bsd.sb, который является шаблоном для стереотипной системной службы.

На практике

Как можно заметить, ничего особенно сложного в конфигурации профиля нет. Поэтому возникает резонный вопрос — а почему бы не заключить в «песочницу» что-нибудь кроме стандартных демонов Mac OS X? К примеру, очевидным кандидатом является браузер Safari, ведь по количеству уязвимостей за 2010 год он уступает только Google Chrome.

На первый взгляд может показаться, что достаточно лишь создать  профиль, разрешающий запуск исполняемого файла, исходящие соединения, да запись в каталог загрузок. Однако, не все так просто. Ведь в Safari входит ряд сторонних плагинов, загружаемых при помощи WebKitPluginHost и компоненты QuickTime. Нет какой-то информации о том, к каким файлам и системным функциям обращается приложение. То есть, помещение Safari в сэндбокс вместе с обеспечением нормальной работы браузера является задачей весьма нетривиальной.

К счастью, несколько разработчиков из компании ROMAB уже создали «бронированный» вариант Safari под названием IronSafari, который использует описанные выше механизмы для помещения приложения в изолированную среду. На их сайте также можно скачать аналогичные версии для Firefox, Adium и VLC.

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

(version 1)

(deny default)

(debug deny)

(allow process-exec

(subpath "/tmp/sandbox")

)

(allow mach-lookup

(global-name "com.apple.CoreServices.coreservicesd")

(global-name "com.apple.SecurityServer")

(global-name "com.apple.dock.server")

(global-name "com.apple.FontServer")

(global-name "com.apple.FontObjectsServer")

(global-name "com.apple.distributed_notifications.2")

(global-name "com.apple.system.notification_center")

(global-name "com.apple.windowserver.active")

(global-name "com.apple.windowserver.session")

(global-name "com.apple.tsm.uiserver")

(global-name "Multilingual (Apple)_OpenStep")

(global-name "en (Apple)_OpenStep")

(global-name "com.apple.pasteboard.1")

)

(allow file-read-data file-read-metadata (regex "^/.*"))

(allow file-write*

(regex "^(/private)?/tmp/")

)

В данном случае мы разрешаем запуск программы только из каталога /tmp/sandbox, в который, соответственно,  и надо будет поместить исполняемый файл. Чтобы программы с графическим интерфейсом могли выполнять какие-то элементарные действия вроде отрисовки окна, необходимо также разрешить базовые вызовы к функциям Mach IPC (InterProcess Cimmunication, механизм взаимодействия программ, отдаленно похожий на сокеты в BSD), это задается параметром mach-lookup. Наконец, разрешено чтение любых файлов, начиная с корневого каталога и запись в /tmp.

Остается только запустить приложение в «песочнице». Как говорилось выше, для этого используется команда sandbox-exec:

sandbox-exec -n lock /tmp/sandbox/CoRD.app/Contents/MacOS/CoRD

Параметр –n указывает имя профиля, находящегося в каталоге /usr/share/sandbox.

И еще. Все изложенные выше правила строились на модели явного разрешения определенных действий и запрета остальных. Но это не всегда бывает необходимо. К примеру, часто нужно просто оградить программу от выхода в интернет. Для этого достаточно воспользоваться таким небольшим профилем:

(version 1)

(allow default)

(deny network*)

Заключение

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

По крайней мере, маркетологи Apple с чистым сердцем могут констатировать факт того, что в Mac OS X есть простая и надежная система сэндбоксинга. Что уже само по себе есть не так плохо.