Заблокировать подозрительное поведение программы? Смягчить последствия от эксплуатации уязвимостей? Исключить выполнение несанкционированного кода?
TOMOYO Linux — реализация мандатного управления доступом для операционной системы Linux. Встроена в ядро по умолчанию. Позволяет взять под контроль поведение системы и жестко ограничить в рамках заданной политики.
Ниже будет описано создание политик, как на отдельные приложения, так и на всю систему в целом.
Примеры будут построены на базе Debian Wheezy и Tomoyo 2.5 имеющейся в ядре.
Основы
1. Домены.
Tomoyo в своей работе руководствуется таким понятием, как Домены. Домены это процессы и взаимосвязь между процессами domain transition.
Базовый домен это всегда
О него разрастаются все остальные.
<kernel> - домен
<kernel> /sbin/init - домен
<kernel> /sbin/init /etc/rc.d/rc - еще домен
<kernel> /etc/init.d/gdm3 /sbin/start-stop-daemon /usr/sbin/gdm3 - еще
При этом учитывается, как был запущен процесс и кто его родитель.
Возьмем к примеру процесс /bin/bash, он может быть запущен локально, а может и от sshd в процессе удаленного логина.
Эти два состояния так-же сажаются в отдельные домены.
/sbin/init ..... /bin/bash
/sbin/init ..... /usr/sbin/sshd /bin/bash
К каждому домену можно применить свою политику безопасности.
Например, если bash запущен локально - одну. А если bash запущен удаленно - другую, более жесткую. Это сильная особенность Tomoyo.
Основным инструментом работы с доменами и политиками является редактор tomoyo-editpolicy.
Вот так выглядят домены в редакторе tomoyo-editpolicy
Редактор полностью управляется с клавиатуры. Вот так выглядит главное меню.
Для вывода главного меню нужно нажать W, для переключения к списку доменов D (w & d).
2. Политики
Политики содержат различные контроли поведения доменов. Операции записи, чтения, выхода в сеть, создания дочерних процессов. В общем стандартные вещи.
file execute /bin/ls - разрешение запуска ls
Помимо этого, каждый контроль можно обвешивать условиями его срабатывания.
file execute /bin/ls task.uid=0 - разрешение запуска ls только суперпользователю.
3. Профили.
Поведение каждого домена, помимо политик, определяется наложенным на него профилем.
Существует 4 базовых профиля.
0 - политики отключены, домен свободен от ограничений.
1 - режим обучения, все действия разрешаются и дописываются в политику конкретного домена.
2 - режим разрешения, по сути тоже что и 0
3 - режим запрета, запрещено все, что не определено политикой конкретного домена.
Вот так выглядят профили в редакторе tomoyo-editpolicy (w & p)
Стандартная цель для усиления безопасности - составить политику для домена и наложить профиль 3
4. Исключения.
Поведение доменов, так-же определяется с помощью Исключений. Исключения действуют глобально. Могут применяться ко всем доменам сразу. В политику исключений так-же прописывают различные, часто вызываемые переменные. Исключения используют для упрощения создания политик и улучшения читаемости конфигов.
Вот так выглядят исключения в редакторе tomoyo-editpolicy (w & e)
5. Конфиги
Конфигурационные файлы вышеописанных составляющих находятся тут:
/etc/tomoyo/domain_policy.conf - политики для каждого домена
/etc/tomoyo/profile.conf - профили
/etc/tomoyo/exception_policy.conf - исключения
Важно понимать, что когда вы запускаете tomoyo-editpolicy и начинаете править домены, накладывать ограничения. Вы правите оперативные правила загруженные в ядро. Не кофигурационные файлы!
Для сохранения проделанных изменений служат отдельные утилиты.
6. Утилиты
tomoyo-editpolicy - основной инструмент для работы. Позволяет работать с текущими загруженными в ядро оперативными политиками.
tomoyo-loadpolicy - загружает в ядро ранее сохраненные или свежесозданные в сторонних редакторах политики.
tomoyo-savepolicy - сохраняет политику, работающую в ядре на диск. Это важно! Если вы что-то правили в оперативных политиках с помощью tomoyo-editpolicy. А потом забыли дать эту команду сохранения, все будет потеряно.
tomoyo-checkpolicy - проверяет сохраненные политики на ошибки.
Это не все утилиты, далее будет еще несколько примеров.
Подробнее о внутреннем устройстве Tomoyo: tomoyo.sourceforge.jp/2.5/chapter-4.html.en
Подробнее об утилитах: tomoyo.sourceforge.jp/2.5/man-pages/index.html.en
Включение Tomoyo.
1. Правим GRUB /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet security=tomoyo"
Даем команду
update-grub
2. Ставим пакеты:
aptitude install tomoyo-tools
3. Выполняем команду:
/usr/lib/tomoyo/init_policy
для первичной инициализации системы.
4. Важно!
Если вы так закрутили гайки с помощью Tomoyo, что даже система не грузится. Ничего страшного, при загрузке нажмите e в меню grub и поменяйте:
security=tomoyo
на
security=none
Пишем политику для приложения
Попробуем наложить ограничения на браузер midori.
Выше было описано, что в зависимости от того, как процесс был запущен, создается каждый раз отдельный домен.
Сейчас нам нужно создать одну общую политику, в независимости от метода запуска midori.
Для этого в Исключениях используем команду initialize_domain.
Запускаем tomoyo-editpolicy.
Заходим в раздел Exeption Policy Editor (w & e) и нажав на клавиатуре A добавляем строчку:
initialize_domain /usr/bin/midori from any
Подробнее об управлениями доменами в Исключениях.
tomoyo.sourceforge.jp/2.5/chapter-5.html.en
После этого возвращаемся в окно Domain Transition Editor (w & d)
И находим наш домен /usr/bin/midori с пометкой *
Нажав S переводим домен в режим обучения, выставив ему 1.
Запускаем midori и работаем в нем пару минут, совершая штатные операции. Посетим пару сайтов, сохраним страничку, покопаемся в настройках и тд.
Закроем midori.
В окне Domain Transition Editor нажимаем Enter на домене и попадаем в редактор политик Domain Policy Editor, видим все операции которые совершал midori в своей работе.
Основная работа будет проходить в этом окне.
Нажимая клавишу @ можно сортировать данные на экране в различных сочетаниях. По пути файлов или по выполняемой операции.
По сути это уже готовый конфиг. Теперь надо упростить его используя регулярные выражения.
В качестве примера используем типичные операции работы программы со своими настройками.
Разрешим некоторые операции для файлов по пути /home/home/.config/midori/
Нажимаем кнопку А (append) и пишем.
file read/write/unlink/truncate/rename /home/home/.config/midori/\*
Теперь удалим строчки попавшие под регулярку.
Нажимаем О и редактор выделяет все совпадения, затем нажимаем D и редактор удаляет теперь уже ненужные строчки, конфиг сокращается.
А вот, например, такой конструкцией можно разрешить определенные операции и для файлов любых подкаталогов /home/home/.config/midori/
file read/write/append/unlink/truncate /home/home/.config/midori/\{\*\}/\*
Синтаксис регулярных выражений описан здесь
tomoyo.sourceforge.jp/2.5/policy-specification/expression-rules.html.en#wildcard
Возможные файловые операции здесь
tomoyo.sourceforge.jp/2.5/policy-specification/domain-policy-syntax.html.en
Давайте теперь посмотрим на операции с сетью.
Создадим правило разрешающее посещение любого сайта в интернете, с использованием определенных портов.
network inet stream connect 0.0.0.0-255.255.255.255 80-443
//упростил указав диапазон портов
И по аналогии выше применяем его, с сокращением конфига (O & D).
Операции с сетью описаны тут
tomoyo.sourceforge.jp/2.5/policy-specification/domain-policy-syntax.html.en#network_inet
Постепенно сокращая конфиг, переходим наконец к запрету подозрительных операций.
Например, мне не нравится, что midori читает /etc/passwd
Попробуем удалить это разрешение и протестировать результат.
Нажимаем D, удалив таким образом разрешение.
Затем возвращаемся в Domain Transition Editor (w & d), нажимаем S и меняем профиль обучения 1 на профиль запрета 3.
Пробуем запустить.
Приложение работает? Значит так тому и быть. Приложение не работает? Значит стоит задуматься о доверии к такому приложению.
После всех манипуляций по причесыванию конфига сохраним его.
tomoyo-savepolicy -d | tomoyo-selectpolicy -r '<kernel> /usr/bin/midori' >> /etc/tomoyo/domain_policy.conf
Пояснение:
tomoyo-savepolicy -d
выводит всю кучу доменов.
tomoyo-selectpolicy -r '<kernel> /usr/bin/midori'
выбирает только нужный домен, с нужной политикой.
>> /etc/tomoyo/domain_policy.conf
сохраняем политику домена.
Что в итоге получилось в политике для midori
/etc/tomoyo/domain_policy.conf
<kernel> /usr/bin/midori
use_profile 3
use_group 0
misc env GNOME_KEYRING_PID
misc env USER
misc env SSH_AGENT_PID
misc env HOME
misc env DESKTOP_SESSION
misc env XDG_SESSION_COOKIE
misc env DBUS_SESSION_BUS_ADDRESS
misc env GNOME_KEYRING_CONTROL
misc env LOGNAME
misc env USERNAME
misc env WINDOWPATH
misc env PATH
misc env DISPLAY
misc env LANG
misc env XAUTHORITY
misc env SSH_AUTH_SOCK
misc env SHELL
misc env GDMSESSION
misc env PWD
misc env XDG_DATA_DIRS
misc env GNOME_DESKTOP_SESSION_ID
misc env SESSION_MANAGER
misc env GPG_AGENT_INFO
misc env GIO_LAUNCHED_DESKTOP_FILE
misc env GIO_LAUNCHED_DESKTOP_FILE_PID
misc env DESKTOP_STARTUP_ID
file read proc:/filesystems
file read /usr/lib/locale/locale-archive
file read /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
network unix stream connect /var/run/nscd/socket
file read /etc/nsswitch.conf
network unix stream connect \000/tmp/.X11-unix/X0
file read /run/gdm3/auth-for-home-WxYaIE/database
file read /usr/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/engines/libclearlooks.so
file read /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/libcanberra-gtk-module.so
network unix stream connect \000/tmp/dbus-BKDp9V4Rww
file read /usr/lib/x86_64-linux-gnu/gio/modules/giomodule.cache
file read /usr/lib/x86_64-linux-gnu/gio/modules/libgiognomeproxy.so
file read /usr/lib/x86_64-linux-gnu/gio/modules/libgiolibproxy.so
file read /usr/lib/x86_64-linux-gnu/gio/modules/libdconfsettings.so
file read /etc/xdg/midori/search
file read /usr/lib/x86_64-linux-gnu/gio/modules/libgiognutls.so
file read proc:/sys/crypto/fips_enabled
file read /dev/urandom
file read /etc/pkcs11/modules/gnome-keyring-module
file read /usr/lib/x86_64-linux-gnu/pkcs11/gnome-keyring-pkcs11.so
network unix stream connect /home/home/.cache/keyring-XULOQY/pkcs11
file read /etc/ssl/certs/ca-certificates.crt
file read /usr/lib/x86_64-linux-gnu/gio/modules/libgvfsdbus.so
file read /usr/lib/x86_64-linux-gnu/gvfs/libgvfscommon.so
file read /usr/lib/midori/libaddons.so
file read /usr/lib/midori/libtoolbar-editor.so
file read /usr/lib/midori/libtab-panel.so
file read /usr/lib/midori/libadblock.so
file read /usr/lib/midori/libcookie-manager.so
file read /usr/lib/midori/libstatusbar-features.so
file read /usr/lib/midori/libweb-cache.so
file read /usr/lib/midori/libshortcuts.so
file read /usr/lib/midori/libformhistory.so
file read /usr/lib/midori/libstatus-clock.so
file read /usr/lib/midori/libcolorful-tabs.so
file read /usr/lib/midori/libfeed-panel.so
file read /usr/lib/midori/libhistory-list.so
file read /usr/lib/midori/libmouse-gestures.so
file read /usr/lib/midori/libcopy-tabs.so
file read /usr/lib/midori/libtabs-minimized.so
file read /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders.cache
file read /usr/lib/x86_64-linux-gnu/pango/1.6.0/module-files.d/libpango1.0-0.modules
file read /etc/fonts/fonts.conf
file read /usr/lib/x86_64-linux-gnu/pango/1.6.0/modules/pango-basic-fc.so
file read /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so
file read /usr/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/gtk.immodules
file read /usr/lib/enchant/libenchant_hspell.so
file read /usr/lib/enchant/libenchant_aspell.so
file read /usr/lib/enchant/libenchant_myspell.so
file read /usr/lib/enchant/libenchant_ispell.so
file read /usr/lib/x86_64-linux-gnu/gconv/KOI8-R.so
file read /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so
file read /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ico.so
file read /etc/host.conf
file read /etc/resolv.conf
file read /etc/hosts
file ioctl socket:[family=2:type=2:protocol=17] 0x541B
file read /etc/gai.conf
file read /usr/lib/x86_64-linux-gnu/gio/modules/libgioremote-volume-monitor.so
file ioctl anon_inode:inotify 0x541B
file read /etc/gnome/defaults.list
file read /usr/lib/libreoffice/share/\{\*\}/\*
file read/write/append/unlink/truncate /home/home/\{\*\}/\*
file read/write/append/unlink/truncate /home/home/\*
file create/chmod /home/home/\* 0-0666
file create/chmod /home/home/\{\*\}/\* 0-0666
file rename /home/home/\* /home/home/\*
file rename /home/home/\{\*\}/\* /home/home/\{\*\}/\*
file rename /home/\{\*\}/\* /home/home/\{\*\}/\*
file read /etc/fonts/\{\*\}/\*
file read /usr/share/\{\*\}/\*
file read /var/cache/\{\*\}/\*
network inet stream connect 0.0.0.0-255.255.255.255 80-443
network inet dgram send 192.168.1.1 53
Затем сохраним политику исключений.
tomoyo-savepolicy -e > /etc/tomoyo/exception_policy.conf
После этого, по желанию, можно провести доводку в любом файловом редакторе.
Например добавить глобальную файловую группу с распространенными путями в exception_policy.conf
path_group Midoi_Allow /home/\*/midory/\{\*\}/\*
path_group Midoi_Allow /home/\*/.config/midori/\{\*\}/\*
path_group Midoi_Allow /home/home/.config/midori/\*
И прописать ее в domain_policy.conf, еще больше упростив конфиг.
file read/write/append/unlink/truncate @Midoi_Allow
В случае такой ручной правки, обязательно проверяем конфиги на ошибки, ведь обычный редактор не учитывает синтаксис Tomoyo.
tomoyo-checkpolicy d < /etc/tomoyo/domain_policy.conf
tomoyo-checkpolicy e < /etc/tomoyo/exception_policy.conf
Может случиться так, что приложение будет периодически падать или глючить из-за редких вызовов каких-то разрешений, которых не было в режиме обучения.
Тогда запускаем программу логирования запретов tomoyo-auditd и как только приложение глюкнуло, идем в /var/log/tomoyo и смотрим на что сработал запрет.
Примеры политик для некоторых программ
wiki.archlinux.org/index.php/skype#TOMOYO
wiki.archlinux.org/index.php/Adobe_Reader
Пишем глобальные правила
В Tomoyo можно реализовывать глобальные правила, применяющиеся для всех доменов.
Давайте сделаем глобальную политику запрета запуска программ из /home и /tmp для всех пользователей кроме учетной записи root.
Для отдельных программ установим более жесткие политики.
Создаем новый профиль с контролем только выполнения файлов.
/etc/tomoyo/profile.conf4-COMMENT=-----Enforcing file::execute only-----
4-PREFERENCE={ max_audit_log=1024 max_learning_entry=2048 }
4-CONFIG={ mode=disabled grant_log=yes reject_log=yes }
4-CONFIG::file::execute={ mode=enforcing grant_log=no reject_log=yes }
Добавляем в исключения следующие строчки.
/etc/tomoyo/exception_policy.conf
path_group ALLOW_EXEC /\*
path_group ALLOW_EXEC /bin/\{\*\}/\*
path_group ALLOW_EXEC /etc/\{\*\}/\*
path_group ALLOW_EXEC /sbin/\{\*\}/\*
path_group ALLOW_EXEC /sys/\{\*\}/\*
path_group ALLOW_EXEC /boot/\{\*\}/\*
path_group ALLOW_EXEC /usr/\{\*\}/\*\-medit\-midori
path_group ALLOW_EXEC /run/\{\*\}/\*
path_group ALLOW_EXEC /bin/\*
path_group ALLOW_EXEC /etc/\*
path_group ALLOW_EXEC /sbin/\*
path_group ALLOW_EXEC /sys/\*
path_group ALLOW_EXEC /boot/\*
path_group ALLOW_EXEC /usr/\*
path_group ALLOW_EXEC /run/\*
path_group ALLOW_EXEC_ROOT /lib/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /lib64/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /home/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /opt/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /tmp/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /var/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /mnt/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /media/\{\*\}/\*
path_group ALLOW_EXEC_ROOT /lib/\*
path_group ALLOW_EXEC_ROOT /lib64/\*
path_group ALLOW_EXEC_ROOT /home/\*
path_group ALLOW_EXEC_ROOT /opt/\*
path_group ALLOW_EXEC_ROOT /tmp/\*
path_group ALLOW_EXEC_ROOT /var/\*
path_group ALLOW_EXEC_ROOT /mnt/\*
path_group ALLOW_EXEC_ROOT /media/\*
keep_domain any from <kernel>
initialize_domain /usr/bin/midori from any
Правим политику домена:
/etc/tomoyo/domain_policy.conf
<kernel>
use_profile 4
use_group 0
file execute @ALLOW_EXEC
file execute @ALLOW_EXEC_ROOT task.uid=0
file execute /usr/bin/medit
file execute /usr/bin/midori
<kernel> /usr/bin/midori
use_profile 3
use_group 0
Разбор полетов.
1.
Для чего сначала пришлось удалять midori из регулярки \-midori, а потом явно указывать снова через file execute /usr/bin/medit?
Все дело в логике Tomoyo. Когда система разбирает заданные правила, она учитывает как помечается каждый домен в конфиге и требует его указания в явном виде. Это свойство работает только для команд связанных с переходами между доменами, но не с запрещающими правилами.
Поэтому команда initialize_domain /usr/bin/midori from any при переходе в домен medit, отработает только если она указана в явном виде в родительском домене .
2.
file execute @ALLOW_EXEC_ROOT task.uid=0
Тут мы ставим условие на контроль, которое определяет, что только суперпользователь имеет право выполнять программы из заданных директорий.
Подробнее об условиях.
tomoyo.sourceforge.jp/2.5/chapter-10.html.en
3.
keep_domain any from <kernel>
Опция управления доменами в Исключениях. Принудительно оставляет все созданные дочерние процессы в рамках одного домена.
initialize_domain /usr/bin/midori from any
Помимо включения опции независимого запуска, принудительно выводит процесс в отдельные домен. То есть выходит процесс из под ограничения keep_domain.
4.
4-CONFIG::file::execute={ mode=enforcing grant_log=no reject_log=yes }
Настраиваем профиль только на контроль выполнения файлов. Командой use_profile 4, применяем данный профиль к политике.
Подробнее о возможных состояния профиля.
tomoyo.sourceforge.jp/2.5/chapter-9.html.en
Итог
Tomoyo позволяет несколькими простыми шагами, поднять безопасность системы в целом.
Можно распространить конфигурацию по сети и защитить таким образом целые сегменты.
ps. Для интересующихся темой mac. Один из разработчиков Tomoyo, продемонстрировал еще один инструмент принудительного контроля - caitsith.sourceforge.jp
Update!
Выявлена возможность простого обхода правил Tomoyo из под прав простого пользователя.
Обход возможен с помощью ld-linux.so.2 библиотеки динамической линковки программ.
Поэтому во все конфиги обязательно включайте запрет на прямой вызов данной библиотеки.
Например:
<kernel> /lib/x86_64-linux-gnu/ld-2.13.so
use_profile 3
use_group 0
initialize_domain /lib/x86_64-linux-gnu/ld-2.13.so from any
Учтите, что может быть несколько копий данной библиотеки в системе.