Wondering how to Sandbox Processes on Ubuntu 20.04 with Systemd?
At Bobcares we often handle similar requests from our customers as a part of our Server Management Services.
Today let’s see how we do this for our customers with ease.
How to Sandbox Processes on Ubuntu 20.04 with Systemd?
Before moving into the steps to the sandbox process we will see what sandboxing means.
What is Sandboxing Process?
Sandboxing is used for isolating a program or process from parts of a system that are not needed during normal operations.
When a new program runs it will have all the privileges that the user has. These privileges are usually much more than the program needs to perform its function.
And can cause security issues if anyone manipulates the program to access some of its unused privileges to do something unusual than the program usually does.
With the help of sandboxing, we can fix this since it allows the programs to use only the required privileges and thus not allowing them to access all the privileges a user has.
Steps for Sandboxing Processes on Ubuntu 20.04 with Systemd
We will be using systemd here as it has many sandboxing options to restrict the process from accessing the host system unnecessarily.
This will make the server more secure. Here we will discuss the steps to sandbox processes on Ubuntu 20.04.
1. Installing lighttpd
We will sandbox the lighttpd web server as it is a small program with a single function that is easy to the sandbox.
It can be installed using the following commands:
$ sudo apt update
$ sudo apt install lighttpd
This installation will automatically install and enable a systemd service file for lighttpd and will make lighttpd start on a system reboot.
2. Using Systemd to sandbox processes on Ubuntu
As we know systemd uses service files to define how to manage a process.
The following command will show you the location of the active service file and display any overrides that are in use:
$ sudo systemctl cat lighttpd.service
We will receive an output of the following form:
# /lib/systemd/system/lighttpd.service [Unit] Description=Lighttpd Daemon After=network-online.target [Service] Type=simple PIDFile=/run/lighttpd.pid ExecStartPre=/usr/sbin/lighttpd -tt -f /etc/lighttpd/lighttpd.conf ExecStart=/usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.conf ExecReload=/bin/kill -USR1 $MAINPID Restart=on-failure [Install] WantedBy=multi-user.target
We will use overrides to sandbox lighttpd with a dedicated override file.
Override files are located at /etc/systemd/system/process.service.d/override.conf.
systemd has a dedicated edit command that will create an override file at the correct location. And this will run systemctl daemon-reload after saving and exiting the editor.
The systemctl daemon-reload instructs systemd to use any new configuration you wrote.
Comand that is used for editing is given below:
$ sudo systemctl edit process.service
During sandboxing, we will make many changes that break the process we are trying to sandbox. So we will open a second terminal and dedicate it to following the system log.
Use the following command in the new terminal.
$ sudo journalctl -f -u process.service
To print only lighttpd’s errors use the following command:
$ sudo journalctl -f -u lighttpd.service
3. Creation of User and Group
We will set the non-root user that lighttpd will run as.
By default configuration, lighttpd starts running as the root user and then changes to the www-data user and group.
And running as root it can do anything that root can do.
systemd provides the ability to start and run the process as a non-root user to fix this problem.
In the first terminal session run the following command:
$ sudo -E systemctl edit lighttpd.service
And add the following lines:
[Service] User=www-data Group=www-data
Next, we can save and exit the editor.
Finally, restart lighttpd with the following command:
$ sudo systemctl restart lighttpd.service
We will see that lighttpd will not be able to start because it was using the root authority to write a PID file to a location owned by root.
From the system log in the other terminal session we will be able to see the following:
journalctl error message Oct 29 11:37:35 systemd lighttpd[7097]: 2020-10-29 11:37:35: (server.c.1233) opening pid-file failed: /run/lighttpd.pid Permission denied
The next step is managing PID to sandbox processes on Ubuntu.
[Need assistance? We are here for you!]
3. Managing the PID File
We found that lighttpd was unable to write its PID file to /run/lighttpd.pid as /run/ belongs to root.
systemd uses RuntimeDirectory option to give lighttpd a location to write its PID file to.
The RuntimeDirectory option allows specifying a directory under /run/ that can be created by the user and group we set when systemd starts lighttpd.
After this lighttpd will be able to write its PID into this directory without root permission.
First, open and edit the override file with the following command:
$ sudo -E systemctl edit lighttpd.service
And then add the following line under the two lines that we already added to the override file:
RuntimeDirectory=lighttpd
Save and exit.
Now we need to configure lighttpd to write its PID file into the new directory /run/lighttpd/ instead of /run/.
Open lighttpd’s configuration file with a text editor:
$ sudo nano /etc/lighttpd/lighttpd.conf
And change the following line:
server.pid-file = "/run/lighttpd.pid"
To:
server.pid-file = "/run/lighttpd/lighttpd.pid"
Save and exit the editor.
Now, restart lighttpd:
$ sudo systemctl restart lighttpd.service
We can see that the service is still not active and running. To fix this we will go to the next step of providing proper privileges.
5. Obtaining Capabilities for User from Root.
From the logs, in the other terminal, we will be able to see the following error.
journalctl error message Oct 29 12:07:22 systemd lighttpd[7220]: 2020-10-29 12:07:22: (network.c.311) can't bind to socket: 0.0.0.0:80 Permission denied
The issue is resolved by giving the lighttpd process a small part of the root’s privilege to open ports below 1024.
The systemd option to give a process one or more of root’s capabilities is using the AmbientCapabilities.
First, open the override file:
$ sudo -E systemctl edit lighttpd.service
Then add the following line under the lines you already added:
AmbientCapabilities=CAP_NET_BIND_SERVICE The CAP_NET_BIND_SERVICE capability allows a process to open ports under 1024.
Save and exit the file.
lighttpd will be started now.
In the next step, we will restrict lighttpd to access the whole file system unnecessarily in order to sandbox processes on Ubuntu.
6. Locking Down the Filesystem
The lighttpd process runs as a ‘www-data’ user and can access any file on the system that www-data has permission to read and write to.
The first and easiest sandbox setting is the ProtectHome option.
This option stops the process from reading or writing to anything under /home/.
lighttpd does not need access to anything under /home/ so we can protect all other private files without affecting Lighttpd.
First, open the override file:
$ sudo -E systemctl edit lighttpd.service
And add the following line at the bottom of the file:
ProtectHome=true
Save and exit.
Finally, restart lighttpd with the following command:
$ sudo systemctl restart lighttpd.service
Now we have protected /home/, but that still leaves the rest of the file system.
We can use the ProtectSystem option, which stops a process from writing to parts of the file system.
The ProtectSystem option has three settings that offer increasing levels of protection.
They are as follows:
1. true: Sets the following directories to read only: /usr/ /boot/ /efi/ 2. full: Sets the following directories to read only: /usr/ /boot/ /efi/ /etc/ 3. strict: Sets the following directories to read only: Entire file system
For a higher level of protection we can set the ProtectSystem option to strict by adding the following line to the override file:
ProtectSystem=strict
Save and exit.
Using the below command we can make a few more changes:
$ sudo -E systemctl edit lighttpd.service
The lighttpd log directory is /var/log/lighttpd/ so we need to add the following line to the bottom of the override file:
LogsDirectory=lighttpd
Save and exit the editor and restart lighttpd.
[Need assistance to sandbox any process? We are happy to help you!]
Conclusion
To conclude we saw how to Sandbox Processes on Ubuntu 20.04 with Systemd for Lighttpd. Also, we saw the method used by our Support Engineers to implement this.
0 Comments