Mandatory rights distribution model in FreeBSD

Introduction

To provide an additional layer of server security, one can use a mandated model of access distribution. This publication will describe how to run Apache in a jail with access only to the components necessary for the proper functioning of Apache and PHP. This principle can be applied not only to Apache but also to any other stack.

Preparation

This method is suitable only for the UFS file system; in this example, the main system will use ZFS, while the jail will use UFS. First, you need to rebuild the kernel; when installing FreeBSD, install the source code.
After the system is installed, edit the file:

/usr/src/sys/amd64/conf/GENERIC

You need to add just one line to this file:

options     MAC_MLS

The label mls/high will take precedence over the label mls/low; applications launched with the label mls/low will not be able to access files labeled mls/high. More details about all available labels in the FreeBSD system can be found in this the guide.
Next, navigate to the directory /usr/src:

cd /usr/src

To start the kernel build, execute (in the j option, specify the number of cores in the system):

make -j 4 buildkernel KERNCONF=GENERIC

Once the kernel is built, it needs to be installed:

make installkernel KERNCONF=GENERIC

After installing the kernel, do not rush to reboot the system, as it is necessary to transition users to the login class after configuring it. Edit the file /etc/login.conf, in this file you need to edit the default login class, changing it to:

default:
        :passwd_format=sha512:
        :copyright=/etc/COPYRIGHT:
        :welcome=/etc/motd:
        :setenv=MAIL=/var/mail/$,BLOCKSIZE=K:
        :path=/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin ~/bin:
        :nologin=/var/run/nologin:
        :cputime=unlimited:
        :datasize=unlimited:
        :stacksize=unlimited:
        :memorylocked=64K:
        :memoryuse=unlimited:
        :filesize=unlimited:
        :coredumpsize=unlimited:
        :openfiles=unlimited:
        :maxproc=unlimited:
        :sbsize=unlimited:
        :vmemoryuse=unlimited:
        :swapuse=unlimited:
        :pseudoterminals=unlimited:
        :kqueues=unlimited:
        :umtxp=unlimited:
        :priority=0:
        :ignoretime@:
        :umask=022:
        :label=mls/equal:

The line :label=mls/equal will allow users who belong to this class to access files marked with any label (mls/low, mls/high). After these manipulations, you need to rebuild the database and place the root user (as well as those who need it) in this login class:

cap_mkdb /etc/login.conf
pw usermod root -L default

To ensure that the policy only applies to files, you need to edit the file /etc/mac.conf and leave only one line in it:

default_labels file ?mls

You also need to add the mac_mls.ko module to autoload:

echo 'mac_mls_load="YES"' >> /boot/loader.conf

After this, you can safely reboot the system. How to create jail can be read in one of my publications. But before creating a jail, you need to add a hard drive, create a filesystem on it, and enable multilabel. Create a ufs2 filesystem with a cluster size of 64kb:

newfs -O 2 -b 64kb /dev/ada1
tunefs -l enable /dev/ada1

After creating the filesystem and adding multilabel, you need to add the hard drive to /etc/fstab. Add the following line to this file:

/dev/ada1               /jail  ufs     rw              0       1

In the Mountpoint, specify the directory where you will mount the hard drive. In Pass, be sure to specify 1 (the order in which this hard drive will be checked) — this is necessary, as the ufs filesystem is sensitive to sudden power outages. After these steps, mount the disk:

mount /dev/ada1 /jail

Install the jail in this directory. After the jail is up and running, it is necessary to carry out the same manipulations as in the main system with users and files /etc/login.conf, /etc/mac.conf.

Settings

Before setting the necessary labels, I recommend installing all the required packages. In my case, the labels will be set considering these packages:

mod_php73-7.3.4_1              PHP Scripting Language
php73-7.3.4_1                  PHP Scripting Language
php73-ctype-7.3.4_1            The ctype shared extension for php
php73-curl-7.3.4_1             The curl shared extension for php
php73-dom-7.3.4_1              The dom shared extension for php
php73-extensions-1.0           "meta-port" to install PHP extensions
php73-filter-7.3.4_1           The filter shared extension for php
php73-gd-7.3.4_1               The gd shared extension for php
php73-gettext-7.3.4_1          The gettext shared extension for php
php73-hash-7.3.4_1             The hash shared extension for php
php73-iconv-7.3.4_1            The iconv shared extension for php
php73-json-7.3.4_1             The json shared extension for php
php73-mysqli-7.3.4_1           The mysqli shared extension for php
php73-opcache-7.3.4_1          The opcache shared extension for php
php73-openssl-7.3.4_1          The openssl shared extension for php
php73-pdo-7.3.4_1              The pdo shared extension for php
php73-pdo_sqlite-7.3.4_1       The pdo_sqlite shared extension for php
php73-phar-7.3.4_1             The phar shared extension for php
php73-posix-7.3.4_1            The posix shared extension for php
php73-session-7.3.4_1          The session shared extension for php
php73-simplexml-7.3.4_1        The simplexml shared extension for php
php73-sqlite3-7.3.4_1          The sqlite3 shared extension for php
php73-tokenizer-7.3.4_1        The tokenizer shared extension for php
php73-xml-7.3.4_1              The xml shared extension for php
php73-xmlreader-7.3.4_1        The xmlreader shared extension for php
php73-xmlrpc-7.3.4_1           The xmlrpc shared extension for php
php73-xmlwriter-7.3.4_1        The xmlwriter shared extension for php
php73-xsl-7.3.4_1              The xsl shared extension for php
php73-zip-7.3.4_1              The zip shared extension for php
php73-zlib-7.3.4_1             The zlib shared extension for php
apache24-2.4.39 

In this example, labels will be assigned considering the dependencies of these packages. Of course, it would be simpler to set labels mls/low for the directory /usr/local/lib and the files located in this directory, allowing subsequent installed packages (like additional extensions for php) to access libraries in this directory. However, I think it’s better to grant access only to the files that are necessary. Stop the jail and set the labels mls/high for all files:

setfmac -R mls/high /jail

When assigning labels, the process will be halted if setfmac encounters hard links. In my example, I removed hard links in the following directories:

/var/db/etcupdate/current/
/var/db/etcupdate/current/etc
/var/db/etcupdate/current/usr/share/openssl/man/en.ISO8859-15
/var/db/etcupdate/current/usr/share/man/en.ISO8859-15
/var/db/etcupdate/current/usr/share/man/en.UTF-8
/var/db/etcupdate/current/usr/share/nls
/etc/ssl
/usr/local/etc
/usr/local/etc/fonts/conf.d
/usr/local/openssl

After the labels are set, it is necessary to set the labels mls/low for apache. First, you need to determine which files are required to run apache:

ldd /usr/local/sbin/httpd

After executing this command, dependencies will be displayed on the screen, but setting the necessary labels on these files will not be sufficient, as the directories containing these files have the mls/high label; therefore, the mls/low label must also be applied to these directories. When starting Apache, it will also provide the files necessary for its operation, and for PHP, these dependencies can be found in the httpd-error.log.

setfmac mls/low /
setfmac mls/low /usr/local/lib/libpcre.so.1
setfmac mls/low /usr/local/lib/libaprutil-1.so.0
setfmac mls/low /usr/local/lib/libdb-5.3.so.0
setfmac mls/low /usr/local/lib/libgdbm.so.6
setfmac mls/low /usr/local/lib/libexpat.so.1
setfmac mls/low /usr/local/lib/libapr-1.so.0
setfmac mls/low /lib/libcrypt.so.5
setfmac mls/low /lib/libthr.so.3
setfmac mls/low /lib/libc.so.7
setfmac mls/low /usr/local/lib/libintl.so.8
setfmac mls/low /var
setfmac mls/low /var/run
setfmac mls/low /var/log
setfmac mls/low /var/log/httpd-access.log
setfmac mls/low /var/log/httpd-error.log
setfmac mls/low /var/run/httpd.pid
setfmac mls/low /lib
setfmac mls/low /lib/libcrypt.so.5
setfmac mls/low /usr/local/lib/db5/libdb-5.3.so.0
setfmac mls/low /usr/local/lib/db5/libdb-5.3.so.0.0.0
setfmac mls/low /usr/local/lib/db5
setfmac mls/low /usr/local/lib
setfmac mls/low /libexec
setfmac mls/low /libexec/ld-elf.so.1
setfmac  mls/low /dev
setfmac  mls/low /dev/random
setfmac  mls/low /usr/local/libexec
setfmac  mls/low /usr/local/libexec/apache24
setfmac  mls/low /usr/local/libexec/apache24/*
setfmac  mls/low /etc/pwd.db
setfmac  mls/low /etc/passwd
setfmac  mls/low /etc/group
setfmac  mls/low /etc/
setfmac  mls/low /usr/local/etc
setfmac -R mls/low /usr/local/etc/apache24
setfmac mls/low /usr
setfmac mls/low /usr/local
setfmac mls/low /usr/local/sbin
setfmac mls/low /usr/local/sbin/*
setfmac -R mls/low /usr/local/etc/rc.d/
setfmac mls/low /usr/local/sbin/htcacheclean
setfmac mls/low /var/log/httpd-access.log
setfmac mls/low /var/log/httpd-error.log
setfmac -R mls/low /usr/local/www
setfmac mls/low /usr/lib
setfmac mls/low /tmp
setfmac -R mls/low /usr/local/lib/php
setfmac -R mls/low /usr/local/etc/php
setfmac mls/low /usr/local/etc/php.conf
setfmac mls/low /lib/libelf.so.2
setfmac mls/low /lib/libm.so.5
setfmac mls/low /usr/local/lib/libxml2.so.2
setfmac mls/low /lib/libz.so.6
setfmac mls/low /usr/lib/liblzma.so.5
setfmac mls/low /usr/local/lib/libiconv.so.2
setfmac mls/low /usr/lib/librt.so.1
setfmac mls/low /lib/libthr.so.3
setfmac mls/low /usr/local/lib/libpng16.so.16
setfmac mls/low /usr/lib/libbz2.so.4
setfmac mls/low /usr/local/lib/libargon2.so.0
setfmac mls/low /usr/local/lib/libpcre2-8.so.0
setfmac mls/low /usr/local/lib/libsqlite3.so.0
setfmac mls/low /usr/local/lib/libgd.so.6
setfmac mls/low /usr/local/lib/libjpeg.so.8
setfmac mls/low /usr/local/lib/libfreetype.so
setfmac mls/low /usr/local/lib/libfontconfig.so.1
setfmac mls/low /usr/local/lib/libtiff.so.5
setfmac mls/low /usr/local/lib/libwebp.so.7
setfmac mls/low /usr/local/lib/libjbig.so.2
setfmac mls/low /usr/lib/libssl.so.8
setfmac mls/low /lib/libcrypto.so.8
setfmac mls/low /usr/local/lib/libzip.so.5
setfmac mls/low /etc/resolv.conf

This list sets the mls/low labels on all files necessary for the proper functioning of the Apache and PHP combination (for the packages installed in my example).

The final touch will be configuring the jail to run at the mls/equal level and Apache at the mls/low level. To start the jail, you need to modify the script /etc/rc.d/jail, find the jail_start function in this script, and set the command variable as follows:

command="setpmac mls/equal $jail_program"

The setpmac command runs the executable at the required mandatory level, in this case mls/equal, to access all labels. In Apache, you need to edit the startup script /usr/local/etc/rc.d/apache24. Make changes in the apache24_prestart function:

apache24_prestart() {
        apache24_checkfib
        apache24_precmd
        eval "setpmac mls/low" ${command} ${apache24_flags}
}

In official the guide provides a different example, but I was unable to use it as I constantly received a message stating that the setpmac command could not be used.

Output

This method of access distribution adds an additional layer of security to Apache (although this method is applicable to any other stack) which runs in a jail, while for the administrator, all of this will happen transparently and unnoticed.

A list of sources that helped me in writing this publication:

https://www.freebsd.org/doc/ru_RU.KOI8-R/books/handbook/mac.html

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster