Ограничиваем файловую систему в Debian
В этой статье я попытаюсь собрать в одну кучу наработки по ограничению доступа в файловой системе Linux. Описание делается с уклоном в сторону Debian и Debian based-систем, но легко может быть адаптировано и для других дистрибутивов.
Основная идея описанного ниже - превращение необходимых каталогов в точки монтирования, после чего ограничение прав уже непосредственно точек монтирования. Кроме этого, активно используется фича, добавленная в ядрах 2.6.26+ - bind'инг каталогов в режиме read only.
Все действия делаются последовательными операциями монтирования и целиком описываются в /etc/fstab:
# Каталог ядра и файлов загрузчика. Не меняется во время работы, тут ни исполняемых файлов, ни устройств, ни SUID-файлов # Если /boot на отдельном разделе - параметры монтирования переносятся на него. /boot /boot auto bind 0 0 /boot /boot auto bind,remount,ro,nodev,nosuid,noexec 0 0 # Пример конфигурирования /tmp для использования с tmpfs # В Debian Wheezy можно сделать /tmp в tmpfs, задав RAMTMP=no в /etc/default/tmpfs. Там же задаются размеры этой # и другой точек tmpfs. # Еще одна "публично" доступная tmp-точка - это /var/tmp. По FHS там может быть временный контент, # который не удаляется при перезагрузке. На деле такое встречал только в KDE - там хранился кэш браузера. # В остальных случаях - а, тем более, на сервере - удобнее сделать /var/tmp симлинком на /tmp tmpfs /tmp tmpfs defaults,size=1G,noexec,nosuid,nodev 0 0 # Данная точка описывается, если для /usr не выделен отдельный раздел. Если выделен - переносим параметры туда # /usr не меняется во время работы, поэтому можно держать его в RO. Исключением может быть /usr/src. При необходимости # его можно вынести в отдельный каталог (например, сделать /var/src), а в /usr сделать симлинк. # Кроме того, в /usr не бывает файлов устройств /usr /usr auto bind 0 0 /usr /usr auto bind,remount,nodev,ro 0 0 # Аналогично /usr - если есть отдельный раздел под него - делаем описание параметров там # Данный раздел в RW, но тут не бывает SUID-бинарников # Плюс в /var практически нет исполняемых файлов - возможно, стоит подробнее описать каталоги, где они находятся, # а /var сделать noexec /var /var auto bind 0 0 /var /var auto bind,remount,nodev,nosuid 0 0 # Некоторый софт ставится в /opt - защищаем его. /opt /opt auto bind 0 0 /opt /opt auto bind,remount,ro,nodev 0 0 # Защищаем от записи каталоги исполняемых файлов /bin /bin auto bind 0 0 /bin /bin auto bind,remount,ro,nodev 0 0 /sbin /sbin auto bind 0 0 /sbin /sbin auto bind,remount,ro,nodev 0 0 # Защищаем от записи каталог основных системных библиотек и модулей ядра /lib /lib auto bind 0 0 /lib /lib auto bind,remount,ro,nodev,nosuid 0 0 # Внутри /var переопределяем параметры отдельного каталога, где хранится основная база установленных пакетов # Делаем его доступным только на чтение, а также отключаем возможность размещения там файлов устройств и SUID-файлов /var/lib/dpkg /var/lib/dpkg auto bind 0 0 /var/lib/dpkg /var/lib/dpkg auto bind,remount,ro,nosuid,nodev 0 0
/boot /boot auto bind 0 0 /boot /boot auto bind,remount,ro,nodev,nosuid,noexec 0 0 tmpfs /tmp tmpfs defaults,size=1G,noexec,nosuid,nodev 0 0 /usr /usr auto bind 0 0 /usr /usr auto bind,remount,nodev,ro 0 0 /var /var auto bind 0 0 /var /var auto bind,remount,nodev,nosuid 0 0 /opt /opt auto bind 0 0 /opt /opt auto bind,remount,ro,nodev 0 0 /bin /bin auto bind 0 0 /bin /bin auto bind,remount,ro,nodev 0 0 /sbin /sbin auto bind 0 0 /sbin /sbin auto bind,remount,ro,nodev 0 0 /lib /lib auto bind 0 0 /lib /lib auto bind,remount,ro,nodev,nosuid 0 0 /var/lib/dpkg /var/lib/dpkg auto bind 0 0 /var/lib/dpkg /var/lib/dpkg auto bind,remount,ro,nosuid,nodev 0 0
После применения подобных изменений даже случайное выполнение от рута rm -rf / или рекурсивного chown/chmod от корня оставит шанс на быстрое восстановление системы, пока она еще работает - ведь сохранятся неизменными основные библиотеки, исполняемые файлы, база пакетов и т.п.
В таком же стиле можно описать больше каталогов - например, логичным было бы сделать защиту /etc от изменений (но не забываем, что там есть файлы, изменяющиеся при старте или работе системы, скрипты и так далее), или, например, ограничить домашние каталоги пользователей.
При использовании такой конфигурации всплывают 2 особенности:
- Во-первых, некоторые приложения - а особенно APT - требуют, чтобы /tmp был исполняемый - там размещаются и выполняются скрипты настроек в процессе установки и конфигурации пакетов.
- Во-вторых, как ставить пакеты или обновлять систему, если большая часть ФС в Read Only?
Обе проблемы решаются добавлением нескольких строк в конфиг-файл APT - /etc/apt/apt.conf:
Dpkg::Pre-Invoke {"for i in /boot /usr /opt /bin /sbin /lib /var/lib/dpkg ; do mount -o remount,rw $i ; done";}; Dpkg::Post-Invoke {"for i in /boot /usr /opt /bin /sbin /lib /var/lib/dpkg ; do mount -o remount,ro $i ; done";}; APT::ExtractTemplates::TempDir "/root";
Первые 2 строки перемонтируют перечисленные точки монтирования в RW до начала установки пакетов и обратно в RO - после.
Третья строка переопределяет временный каталог размещения скриптов. Это может быть любой exec-каталог, доступный на запись руту.
Данная конфигурация успешно работает на моем сервере.