FreeBSD Permissions Mandate Model

Introduction

To provide an additional layer of server security, you can use mandate model distribution of access. This publication will describe how you can run apache in jail with access only to those components that need access for the correct operation of apache and php. By this principle, you can limit not only apache, but also any other stack.

Prepare

This method is only suitable for the ufs file system, in this example, zfs will be used in the main system, and ufs in jail, respectively. The first step is 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 only need to add one line to this file:

options     MAC_MLS

The mls/high label will take precedence over the mls/low label, applications running with the mls/low label will not be able to access files that have the mls/high label. You can read more about all available labels in a FreeBSD system in this guide.
Next, change to the /usr/src directory:

cd /usr/src

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

make -j 4 buildkernel KERNCONF=GENERIC

After the kernel is built, it must be installed:

make installkernel KERNCONF=GENERIC

After installing the kernel, do not rush to reboot the system, as it is necessary to transfer users to the login class, having previously configured it. Edit the /etc/login.conf file, in this file you need to edit the default login class, bring it to the form:

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 :label=mls/equal line will allow users who are in this class to access files that are marked with any label (mls/low, mls/high). After these manipulations, it is necessary 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

In order for the policy to concern only files, you need to edit the /etc/mac.conf file, leave only one line in it:

default_labels file ?mls

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

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

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

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

After creating the file system and adding the multilabel, you need to add the hard drive to /etc/fstab, add a line to this file:

/dev/ada1               /jail  ufs     rw              0       1

In Mountpoint, specify the directory in which you will mount the hard drive, in Pass, be sure to specify 1 (in what sequence this hard drive will be checked) - this is necessary, since the ufs file system is sensitive to sudden power outages. After these steps, mount the disk:

mount /dev/ada1 /jail

Install jail in this directory. After the jail works, you need to do the same manipulations in it as in the main system with users and files /etc/login.conf, /etc/mac.conf.

Setting

Before installing the necessary tags, I recommend installing all the necessary packages, in my case the tags will be set taking into account 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, the labels will be set taking into account the dependencies of these packages. Of course, you can do it easier, for the /usr/local/lib folder and the files that are in this directory, set the labels mls/low and subsequent installed packages (for example, additional extensions for php) will be able to access the libraries in this directory, but it seems to me better provide access only to those files that are needed. Stop jail and set mls/high tags on all files:

setfmac -R mls/high /jail

When flagging, the process will be stopped 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, you need to set the mls / low labels for apache, the first thing you need to do is find out what files are needed to run apache:

ldd /usr/local/sbin/httpd

After executing this command, the dependencies will be displayed on the screen, but it will not be enough to put the necessary labels on these files, since the directories in which these files are located have the mls/high label, so these directories must also be labeled mls/low. When you start apache, it will also issue the files that are necessary for its launch, and for php, these dependencies can be found in the httpd-error.log 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

In this list, mls/low tags are set for all files that are necessary for the correct operation of the apache and php bundle (for those packages that are installed in my example).

The final touch will be setting jail to run at the mls/equal level, and apache at the mls/low level. To start jail, you need to make changes to the /etc/rc.d/jail script, find the jail_start functions in this script, change the command variable to the form:

command="setpmac mls/equal $jail_program"

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

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

В official There is a different example in the manual, but I was unable to use it because it kept getting a message about not being able to use the setpmac command.

Hack and predictor Aviator

This method of access distribution will add an additional layer of security to apache (although this method is suitable for any other stack), which, in addition, is launched in jail, at the same time, for the administrator, all this will happen transparently and not noticeable.

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

Add a comment