Mar 9, 2019 • SysadminEditsPermalink

Sandboxing All The Things with Firejail

Sometimes, I run software that I trust less. All software I use on a daily basis is open-source, but there is still closed-source software I run occasionally, like video games. Unfortunately, the usual Unix security model does not protect against such software misbehaving, as illustrated by this XKCD. There is no good reason that these applications should have access to all my personal information and secret keys that I have stored on my system, but without proper application isolation (like we are used to on mobile devices nowadays) nothing stops them from leaking all this data. I didn’t want to wait until such technology becomes the default on Linux desktops, so I did some research for ways to sandbox existing applications and ended up with Firejail.

Firejail is packaged for Debian and other distributions, so you should be able to install it with your distribution’s package manager. It runs an application in a sandbox, the details of which are configured in a profile. Firejail comes with profiles for many applications. For example, firejail firefox will start Firefox inside the sandbox. This adds an extra layer of security around Firefox’ security mechanisms.

However, I have found that my setup is sufficiently non-standard that I often have to customize the profiles. The most complex piece of the profile is to configure which parts of the file system the application will be able to access. Unfortunately, the configuration language can be quite hard to use—it is often difficult to find out why access to a particular file does not work. Also, the whitelisting mechanism is fairly inflexible: you cannot control which directory gets whitelisted; instead, when you whitelist something in /home/user/foo, whitelisting gets turned on for all of /home (and similar for a bunch of other hard-coded “whitelisting roots”). But with some experimentation, you’ll get things to work eventually.

For example, if there are extra directories that no sandboxed application should be able to access, you can add them in /etc/firejail/disable-common.local. I am blacklisting all my personal files:

# Personal files
blacklist ${HOME}/Documents

This will affect all sandboxes, because disable-common.inc is included pretty much everywhere, and that includes disable-common.local.

Custom Profiles

Firejail cannot come with profiles for all applications, so sometimes you have to write your own. For example, I use one profile for all video games as well as TeamSpeak, which is based on the profile for Steam and looks like this (I store it in /etc/firejail/gaming.profile):

# Steam profile (applies to games/apps launched from Steam as well)
noblacklist ${HOME}/.steam
noblacklist ${HOME}/.steampath
noblacklist ${HOME}/.steampid
noblacklist ${HOME}/.local/share/steam
noblacklist ${HOME}/.wine
noblacklist ${HOME}/.ts3client
include /etc/firejail/disable-common.inc
include /etc/firejail/disable-programs.inc
include /etc/firejail/disable-passwdmgr.inc

caps.drop all
netfilter
nonewprivs
noroot
protocol unix,inet,inet6,netlink
# wine/games don't work properly with seccomp
#seccomp

# give access to some directories
read-write ${HOME}/.cache/winetricks
read-write ${HOME}/.ts3client
read-write ${HOME}/.steam
read-write ${HOME}/bin/teamspeak3
whitelist /mnt/store/r/games
# -> implicitly, the rest of /mnt is blocked

Obviously, you will have to adjust the paths. If one particular application needs something that got globally blacklisted, you can use noblacklist. However, you might also have to whitelist it if something else sets up a whitelist for this directory. Also, there seems to be no way to have something on the blacklist globally but then make it read-only for a particular sandbox only. (This is what I mean by the configuration language being hard to use.)

Next, it is a good idea to test the profile. You can start a shell inside the sandbox with:

firejail --profile=/etc/firejail/gaming.profile bash

Now you can do things like ls ~/.ssh to make sure your secret keys are not accessible in the sandbox. Also test accessing the directories where the games are stored. Use exit to leave the sandbox.

I have created a file ~/bin/gamejail to conveniently start an application inside the sandbox:

#!/bin/bash
exec firejail --profile=/etc/firejail/gaming.profile "$@"

Now you just have to wrap the call to run the application inside gamejail, for example gamejail steam.

That’s all I got. I hope this little tutorial helps you to make your system a bit more secure by restricting application privileges. Firejail is far from perfect, but it works quite well and it is extremely customizable. In case you have trouble configuring the sandbox properly, I have found it very helpful to look at all the examples that are shipped in /etc/firejail.

Posted on Ralf's Ramblings on Mar 9, 2019.
Comments? Drop me a mail!