Introduction
To provide an additional layer of server security, one can use 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 .
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 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 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:
Source: habr.com
