systemd
enable services to run with a whole suite of hardening and sandboxing features from the Linux kernel. Here’s how to get a quick security review of the services running on your system and how to go about hardening their security.
The Linux kernel can filter and limit access to file systems, networks, devices, kernel capabilities and system calls (syscalls), and more. In this article, I’ll focus on sandboxing access to the file system as a simple introduction to systemd
service security hardening.
The systemd
service security review tool was added in version 240 (released in .) You’ll need to be running that or a later version to follow along with this article.
Security overview of systemd
services
Run the systemd-analyze security
command to get a security audit of all your systemd
services. It will list each service unit and give them a security exposure score rating from 0–10. Lower scores are more secure.
The exposure score is entirely based on a service’s utilization of security features provided by systemd
. It doesn’t consider security features built-in to the program or enforced by access control policies like Security-Enhanced Linux (SELinux) or AppArmor. Nor does the score in any way evaluate the risk factors of a program or its configuration.
In the above example, you’ll notice that task scheduling daemons like atd
and crond
and the remote terminal access daemon for sshd
are considered to be unsafe. That’s an accurate assessment as these services are designed to allow unrestricted execution of arbitrary commands. You may want to disable these services entirely unless you need them.
You can also see that the httpd
(Apache HTTP Server) service has a slightly lower score. This is because Fedora Linux, which is the distribution I use, ships its httpd
service unit with a few systemd
security directives enabled by default. Let’s look at how to review a service’s security directives next.
Analyze a service’s security directives
You should start by analyzing any service that is exposed to the public internet or deal with untrusted/user-provided data. These services will benefit system security the most from being sandboxed. We looked at the Apache web server earlier, so let us stick with that example.
Run the systemd-analyze security httpd.service
command to generate a report of the security directives applied to the httpd.service
.
As of version 233, there are 77 tests in the security review. Below, I’ve included a small selection of test results that focus on file system access.
We can see that Apache HTTP Server is restricted to its own sandboxed temp directory and that it doesn’t have access to the system /tmp
directory. This is a default policy for httpd
on Fedora Linux. You may get different results in your Linux distribution of choice.
The test results show us that our web server could definitively be configured to be more secure. There’s a lot of room for improvement, depending on your Apache HTTP Server configuration. Your web server probably doesn’t need write-access to most locations in your file hierarchy. It probably doesn’t even need read-access.
Let’s move on to tightening the security of the httpd.service
.
Service unit security hardening
Run the systemctl edit httpd.service
command to make changes to the httpd
service unit. This will open a text editor where any change you make will override the service’s default directives. (It will use your default text editor as specified in the EDITOR
environmental variable.)
The following is an example service unit override that addresses some of the points identified in the above security review. Please refer to the systemd.exec
man page for extensive documentation on each directive.
Save this to the override file, run the systemctl daemon-reload
command to make systemd
aware of the changes, and finally systemctl restart httpd.service
to make the changes take effect. You should see about 2 points improvement if you re-run the service security directive testing.
You now need to do extensive testing to ensure that everything still works as expected. You’ve put in place restrictions that the program was never designed to run under. It or programs you run on top of it may misbehave under these conditions. You may need to grant it access to specific files or directories. Let’s look at how you do that.
If something breaks with the above configuration, it might suggest that you’ve tasked your web server to do something potentially risky.
Further locking down access
The ProtectSystem=full
directive makes the /boot
, /etc
, and /usr
directories read-only. This will prevent a compromised program from interfering with system configurations. However, a compromised program can still read and copy sensitive data such as your Let’s Encrypt certificates from the /etc/letsencrypt
directory.
You can block access to specific directories by adding them to the InaccessiblePaths=-/etc/letsencrypt
directive. You can specify multiple paths separated by space characters. Any file or directory under that path in the file hierarchy will be made inaccessible. The minus in front of the path tells systemd
not to raise an error if the path doesn’t exist at runtime.
The InaccessiblePaths
directive combined with the ones from the above example can be used to effectively prevent different processes from getting at each other’s data. You may not want to maintain a white-list per service. However, you should at least set up a block-list of sensitive locations and make them inaccessible to every other service.
You can take it one step further and manually specify ReadWritePaths
, ReadOnlyPaths
, and InaccessiblePaths
. A utility like strace -e trace=%file program
can help you identify what paths a program requires. Requirements will change over time so a setup like this requires ongoing monitoring.
You can go even further and change the root directory with the RootDirectory
directive. This works like the traditional chroot
command and lets you set up a mock file system and launch the service inside it.
Conclusions
systemd
can offer extra protections for your custom services as well as services shipped by your Linux distributed. Your Linux distributions may ship services with little or no protections. Security needs differ from installation to installation so it’s up to the system administrator to enable security protections.
You can quickly strengthen your system security by deploying some of the standard sandboxing directives. It may just be the thing that saves your organization from having a compromised service turn into a security nightmare.
Read on to part two for a tutorial on more advanced systemd
security directives.