Введение
В данной публикации пойдёт речь о мандатной модели bsdextended, на handbook её описывают как брандмауэр файловой системы. Преимущество данного подхода над тем который я описывал в данном руководстве является тот факт, что не имеет значения какая файловая система используется, так как ограничения будут происходить не по меткам на файлах, а по uid и gid пользователей.
Подготовка
Все действия будут произведены в jail, поэтому необходимо изначально настроить jail. Данное руководство написано с учётом того, что jail установлен в каталог /jails/famp. Первым делом установим необходимые модули в «автозапуск», а также запустим их(данные действия необходимо проделывать не в jail) и установим возможность использовать порты 80, 443 пользователю www без root прав:
echo 'mac_portacl_load="YES"' >>/boot/loader.conf
echo 'mac_bsdextended_load="YES"' >> /boot/loader.conf
kldload mac_portacl.ko
kldload mac_bsdextended.ko
sysctl net.inet.ip.portrange.reservedlow=0
sysctl net.inet.ip.portrange.reservedhigh=0
sysctl security.mac.portacl.rules=uid:80:tcp:80,uid:80:tcp:443
echo 'net.inet.ip.portrange.reservedlow=0' >> /etc/sysctl.conf
echo 'net.inet.ip.portrange.reservedhigh=0' >> /etc/sysctl.conf
echo 'security.mac.portacl.rules=uid:80:tcp:80,uid:80:tcp:443' >> /etc/sysctl.conf
Далее в jail необходимо установить зависимости для сборки apache и php, а также установить порты:
pkg install apr autoconf autoconf-wrapper automake ca_root_nss cmake curl db5 dialog4ports expat fontconfig freetype2 gdbm gettext-runtime gettext-tools giflib gmake gmp gperf help2man indexinfo jbigkit jpeg-turbo jsoncpp libarchive libargon2 libffi libgcrypt libgd libgpg-error libiconv liblz4 libnghttp2 libtextstyle libtool libuv libxml2 libxslt libzip lzo2 m4 meson nasm ninja oniguruma p5-Locale-gettext p5-Locale-libintl p5-Text-Unidecode p5-Unicode-EastAsianWidth pcre pcre2 perl5 pkgconf png py37-Babel py37-Jinja2 py37-MarkupSafe py37-alabaster py37-asn1crypto py37-certifi py37-cffi py37-chardet py37-cryptography py37-cython py37-docutils py37-idna py37-imagesize py37-openssl py37-pycparser py37-pygments py37-pysocks py37-pystemmer py37-pytz py37-requests py37-setuptools py37-six py37-snowballstemmer py37-sphinx py37-sphinx_rtd_theme py37-sphinxcontrib-websupport py37-urllib3 python37 re2c readline rhash sqlite3 texinfo tiff webp openssl wget
portsnap fetch extract
Сборка
Перейдём в каталог порта apache, в данном каталоге необходимо выполнить «конфигурирование» порта таким образом, что-бы он установился в каталог /famp:
mkdir /famp
cd /usr/ports/www/apache24
make config
make configure
cd work
cd httpd-2.4.43
./configure --prefix=/famp
cd ..//..
make BATCH=yes PREFIX=/famp install clean
После данных манипуляций apache установится в каталог /famp, php таким образом не установить, поэтому установим из исходного кода:
cd /
wget https://www.php.net/distributions/php-7.4.5.tar.xz
xz -d php-7.4.5.tar.xz
tar -xvf php-7.4.5.tar
cd php-7.4.5
После данных манипуляций необходимо выполнить сборку php указав корректный путь до apxs:
./configure --prefix=/famp --with-apxs2=/famp/sbin/apxs --with-openssl --with-zlib --with-curl --enable-mbstring --with-zip --enable-mysqlnd --enable-maintainer-zts --with-mysqli
gmake install
#После того как php будет установлен, необходимо настроить каталоги для сессий и каталогов temp.
touch /famp/lib/php.ini
nano /famp/lib/php.ini
#В данный файл внесите следующие строки
upload_tmp_dir = “/famp/temp”
sys_temp_dir = “/famp/temp”
session.save_path = “/famp/temp”
opcache.lockfile_path=“/famp/temp”
Настройка
Дальнейшим действием будет корректная настройка httpd.conf (а также остальных необходимых «конфигов»), копирование каталога rc.d и создание необходимых каталогов:
mkdir /famp/log
mkdir /famp/run
mkdir /famp/temp
cp -R /famp/etc/rc.d/ /usr/local/etc/rc.d
#в скрипте инициализации /usr/local/etc/rc.d/apache24 необходимо отредактировать одну строку, для корректного использования pid`а процесса
_pidprefix="/famp/run/httpd"
#в httpd.conf отредактируйте следующие строки
Mutex default:/famp/run
PidFile "/famp/run/httpd.pid"
ErrorLog "/famp/log/httpd-error.log"
CustomLog "/famp/log/httpd-access.log
#httpd-ssl.conf (также необходимо отредактировать пути до сертификатов)
SSLSessionCache "shmcb:/famp/run/ssl_scache(512000)"
DocumentRoot "/famp/www/apache24/data"
ErrorLog "/famp/log/httpd-error.log"
TransferLog "/famp/log/httpd-access.log"
CustomLog "/famp/log/httpd-ssl_request.log"
<Directory "/famp/www/apache24/cgi-bin">
Для того что-бы все процессы apache запускались из под имени www необходимо на файл httpd установить setuid бит, а также необходимо выставить рекурсивно владельца на каталог famp пользователю www, а также необходим доступ к каталогу etc, и файлу resolv.conf:
chown -R www:www /famp
chmod 4755 /famp/sbin/httpd
chown www:wheel /etc
chown www:wheel /etc/resolv.conf
После данным манипуляций apache будет иметь доступ ко всем файл которые необходимы для его работы в изолированной среде, но на мой взгляд не совсем корректно то, что все эти файлы принадлежат пользователю www, по этой причине можно использовать флаги неизменяемости, данные флаги необходимо устанавливать не из jail, так как по умолчанию jail запускается с ограниченными правами:
chflags schg /jails/famp
chflags schg /jails/famp/etc
#доступ к resolv.conf необходим apache для загрузки динамического контента например для rss, или загрузки обновлений для cms
chflags schg /jails/famp/etc/resolv.conf
chflags -R schg /jails/famp/famp
#на данные каталоги не нужно устанавливать данные флаги, так как в них должны быть права на запись
chflags -R noschg /jails/famp/famp/log
chflags -R noschg /jails/famp/famp/run
chflags -R noschg /jails/famp/famp/temp
#если используется cms joomla необходимо разрешить запись в каталог с кэш
chflags -R noschg /jails/famp/famp/www/apache24/data/cache
#Флаг sunlink запретит удалять каталоги, или файлы (в данном случаи каталоги tmp, cache, log, run, temp не имеют флагов неизменяемости, по этому чисто теоретически apache имеет права на удалени данных каталогов)
chflags sunlink /jails/famp/temp
chflags sunlink /jails/famp/famp/www/apache24/data/cache
chflags -R sunlink /jails/famp/famp/log
chflags sunlink /jails/famp/famp/run
# Флаг sappend разрешает только дозапись в файл, т.е. в логи apache можно только дописывать данные, но не удалять и не редактировать.
chflags -R sappend /jails/famp/famp/log
И наконец последним штрихом будет выставление параметра для bsdextended, данные правила добавим в файл иницивлизации jail
nano /etc/rc.d/jail
#В данный файл поместите строку в начало скрипта(при этом произойдет выгрузка модуля, apache и mysql при этом корректно загрузятся)
kldunload mac_bsdextended.ko
#далее необходимо в конец скрипта добавить строки которые загрузят модуль и добавят ограничения для apache и mysql
sleep 3
kldload mac_bsdextended.ko
ugidfw set 1 subject uid 80 object ! uid 80 mode n
ugidfw set 2 subject uid 88 object ! uid 88 mode rx
Данный параметр запретит пользователю www иметь доступ к файлам и каталогам которые принадлежат не пользователю www. Mysql будет иметь доступ к файлам, которые не принадлежат пользователю mysql, только на чтение и запуск.
Вывод
Как видно из данной публикации такой метод для ограничения процессов приведёт к высокой степени защищённости вэб сервера (а также любого другого стека к которому будет применён данный метод).
Список источников которые мне очень помогли в написании данной публикации.
www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/mac-bsdextended.html
www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/mac-portacl.html