Браузер в песочнице

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

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

  • Запустить генератор профайла и выкинуть все лишнее;
  • Запускать приложение и отслеживать все, что выводится в консоль с тегом sandbox.


Вариант с генератором довольно прост. Создаем профайл, который ничего не блокирует а только записывает требуемые права.

(version 1)
(trace "/tmp/trace.sb") ;; (1)

Ну и запускаем Firefox с этим профайлом.

sandbox-exec -f trace.sb /Applications/Firefox.app/Contents/MacOS/firefox
sandbox-simplify /tmp/trace.sb > ./trace.sb #(2)

Результаты трассировки будут записаны в файл /tmp/trace.sb 1, в не очень удобном для понимания формате. Поэтому, необходимо воспользоваться утилитой sandbox-simplify 2 для преобразования профайла в что-то более читабельное.

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

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

(version 1)
(deny default)         ;; (1)
(import "bsd.sb")
(import "system.sb")

(allow process-exec    ;; (2)
  (regex "^/Applications/Firefox.app"))

(allow file-read*      ;; (3)
  (literal "/Library/Preferences/\.GlobalPreferences\.plist")
  (regex "^/Users/.*/Library/Preferences/org\.mozilla\.firefox\.plist$")
  (regex "^/Users/.*/Library/Preferences/com\.apple\.LaunchServices/com\.apple\.launchservices\.secure\.plist$")
  (regex "^/Users/.*/Library/Preferences/com\.apple\.universalaccess\.plist$")
  (regex "^/Users/.*/Library/Preferences/\.GlobalPreferences\.plist$")
  (regex "^/Users/.*/Library/Preferences/ByHost/\.GlobalPreferences\..*\.plist$")
  (regex "^/Users/.*/Library/Keyboard Layouts")
  (regex "^/Users/.*/Library/Input Methods")
  (literal "^/Library/Fonts/")
  (literal "/Library/Preferences/com.apple.HIToolbox.plist")
  (regex "^/Users/.*/Library/Preferences/com.apple.HIToolbox.plist")
  (regex "^/Users/.*/Preferences/com.apple.ATS.plist")
  (regex "^/Users/.*/Library/Internet Plug-Ins")
  (literal "/Library/Internet Plug-Ins")
  (regex "^/Applications/Firefox.app.*"))

(allow file-read* file-write*    ;; (4)
  (regex "^/private/tmp")
  (regex "^/private/var/tmp")
  (regex "^/Users/.*/Library/Caches/Firefox")
  (regex "^/Users/.*/Library/Application Support/Firefox")
  (regex "^/Users/.*/Library/Application Support/Mozilla"))

(allow mach-lookup                ;; (5)
  (global-name "com.apple.CoreServices.coreservicesd")
  (global-name "com.apple.dock.server")
  (global-name "com.apple.FontServer")
  (global-name "com.apple.PowerManagement.control")
  (global-name "com.apple.SystemConfiguration.configd")
  (global-name "com.apple.coreservices.launchservicesd")
  (global-name "com.apple.pasteboard.1")
  (global-name "com.apple.coreservices.quarantine-resolver")
  (global-name "com.apple.ocspd")
  (global-name "com.apple.networkd")
  (global-name "com.apple.cvmsServ")
  (global-name "com.apple.tsm.uiserver")
  (global-name "com.apple.SystemConfiguration.SCNetworkReachability")
  (global-name "com.apple.SystemConfiguration.NetworkInformation")
  (global-name "com.apple.distributed_notifications@Uv3")
  (global-name "com.apple.coreservices.appleevents")
  (global-name "com.apple.window_proxies")
  (global-name "com.apple.pbs.fetch_services")
  (global-name "com.apple.windowserver.active"))

(allow iokit-open                 ;; (6)
  (iokit-user-client-class "AppleMGPUPowerControlClient")
  (iokit-user-client-class "AMDRadeonX4000_AMDAccelDevice")
  (iokit-user-client-class "AMDRadeonX4000_AMDAccelSharedUserClient")
  (iokit-user-client-class "IOHIDParamUserClient")
  (iokit-user-client-class "RootDomainUserClient"))

(allow network-outbound          ;; (7)
  (remote tcp)
  (remote udp)
  (remote unix-socket (path-literal "/private/var/run/mDNSResponder")))

(allow system-socket)
(allow ipc-posix-shm)
(allow file-read-metadata)
(allow process-fork)            ;; (8)

Профайл получается очень простой и, в основном, очевидный: блокируем все по умолчанию и подключаем разрешения из системных правил 1, разрешаем запускать Firefox 2, даем разрешения на чтение 3, запись 4, общение с IPC сервисами 5, взаимодействие с рядом драйверов 6, установление сетевых соединений 7 и fork 8.
Ряд моментов мне показался довольно странным или неожиданным. Так, доступ на запись не подразумевает доступа на чтение и если хочется что бы Firefox мог не только писать, но и читать файл который пишет, нужно давать разрешение на обе операции 4. Кроме того, зачем Firefox понадобился fork 8? Ничего криминального, конечно, но не совсем ожидаемо для браузера.

Можно запускать и радоваться!

sandbox-exec -f ff.sb /Applications/Firefox.app/Contents/MacOS/firefox

3 Comments Браузер в песочнице

Leave a Reply