One thing I that like about the Android App security model is that for a given app, it presents the permissions to the user and the user has to accept them. This is good because the user has control over the software it runs, and is an invaluable tool to be able to use an App without granting it too much access without having to renounce to use it altogether.

Fortunately, the Linux world is a much more friendly environment in terms of malicious software. A big reason for this, is the fact that software is audited and curated by distro package maintainers. I recommend this interesting post on the subject.

Even the best written software can contain vulnerabilities that can be exploited. With the advent of container technologies, such as docker, flatpak or LXC, many have suggested to use them to isolate software from the rest of the system and in doing so mitigate the harm of possible breaches.

By sandboxing software this way, you get some more control over what it is capable of doing, effectively getting closer to the Android security model.

Some alternatives

Well, containers are just a buzzword, in the sense that they are really no first class citizens in Linux. There is no concept of container in the Linux kernel. Rather, containers are a smart combination of existing kernel techniques that help isolate parts of the system. The big contribution of container technologies is to make it easier to use this Linux features. There are others I have not tested, such as Sandstorm.io and runC.

Docker

Docker is the most prominent actor in this scenario. While docker security has improved greately the past few years, and you can use it to run contained graphical applications by mounting the X server socket, it seems an overkill to require a docker daemon to run firefox more securely.

Among other recent security improvements, docker now supports user namespaces, allowing to map the root user so that a priviledged process inside the containers runs as a normal user outside of it.

Also, as the docker daemon runs with root privileges, and it is a pretty big featureful piece of software, it expands the attack surface unnecessarily just to provide sandboxing. There has to be a better way.

Bubblewrap

We also can have look at bubblewrap from ProjectAtomic. It is derived from the Flatpak project, and compared to Docker it is designed to be run by user processes with no privileges, like desktop applications.

This kind of software is the focus of the Flatpak project, whereas Docker is designed towards servers, daemons, cloud and the whole IaaS thing.

For a regular, security conscious user it seems a bit too hard to manage and setup. Just have a look at the (always awesome) Arch Wiki page and see for yourself.

It is the smallest of the three and that is a benefit in terms of attack surface. The downside is that it does not cover and does not try to cover all scenarios, so it does not play well with pulseaudio, X11 or DBus. Bubblewrap designers argue that this is more secure, so Flatpak tries to make software such as Wayland aware of the sandbox.

In short, it does not play well with all software.

Firejail

Finally, I would like to recommend Firejail, which is the one I use personally. It is easy to use, easy to install and configure, and it comes with a very nice set of configuration files for common software. If you want to get advanced, it has that too.

It tries to cover all software, so it is far more complex. This is seen by many as a bad thing because it is really hard to secure a complex SUID program. The benefit is that it will work easily with all your current software.

But before we learn how to use it, let’s see how these “sandboxes” work.

How do sandboxes work

As we mentioned before, the so called containers merely use some existing Linux features. All container technologies that I know build on top of these.

Linux namespaces

The Linux kernel has the concept of namespaces. These namespaces represent different views of different parts of the system.

For example, only if two processes run in the same file namespace they will be able to see the same file and directory tree and access to the same files. Files in other namespaces will be invisible and inaccesible to them.

There are 7 namespaces in Linux, such as the file namespace, the network namespace, the cgroup namespace, the user namespace, the pid namespace and so on. For instance, we can have two processes use the same network interface without being able to see each other (net namespace), or have different views of the pid tree or user ids (pid and uid namespaces).

We can see what namespaces are available in our system with

$ ls /proc/self/ns cgroup ipc mnt net pid pid_for_children uts

Linux capabilities

Traditionally, Linux has had the concept of an all powerful root priveleged user. That user has unlimited powers and access to all parts of the system. SUID programs are allowed all these privileges even if run by an unprivileged user.

While there is a legitimate need for this in some situations, it is also dangerous and unnecessary. For instance, many will be surprised to know that the simple ping command requires access to raw sockets in order to send the ICMP packages.

Linux capabilities allows us to improve this black and white situation. We can limit what the root user is able to perform by indivilually setting its capabilities. Things such as chowning files, ignoring DAC permissions, changing the network configuration or killing processes can be determined individually for a given process.

Here is the complete list of capabilities. For instance, we can check the default capabilities of the ping executable with getcap.

$ getcap /usr/bin/ping /usr/bin/ping = cap_net_raw+ep

Sandboxes often allow us to decide what capabilities we grant to a privileged process, providing an extra level of control.

Seccomp filters

Most userspace processes need to interact with the kernel, even if we don’t realize it. There’s very few interesting things a program can do without access to files, network or standard output.

Userspace programs use kernel facilities through system calls. There are over 300 system calls in Linux. These are often used to try to exploit kernel bugs and escalate privileges, and needless to say, that most often userland software doesn’t need all of them.

seccomp-bpf is a feature of the kernel that allows us to use BPF filters, to specify what syscalls are we allowing for our processes.

If a program is a text processor, why would it need access to the network? we can control that.

Firejail basic usage

Now that we understand the basics, let’s see how to use Firejail.

Install the package from your distro repository and you are ready to go.

If you want to run a sandboxed program, just run the command after firejail

$ firejail program_name

It supports one time flags, such as —seccomp to filter system calls, or –private in order to hide even the home folder from the process.

Do you want some private square browsing?

$ firejail --private firefox --private window

For more granular control, a profile configuration file can be used, but creating one is rarely needed. Firejail comes with a nice set of preconfigured profiles that you can find in /etc/firejail

ls /etc/firejail/  2.12 L  ✓ 0ad.profile clementine.profile feh.profile google-chrome-unstable.profile konversation.profile neverball.profile seamonkey-bin.profile viewnior.profile 2048-qt.profile clipit.profile file-roller.profile google-chrome.profile ktorrent.profile nolocal.net seamonkey.profile viking.profile 7z.profile cmus.profile file.profile google-play-music-desktop-player.profile kwrite.profile nylas.profile server.profile vim.profile Cryptocat.profile conkeror.profile filezilla.profile gpa.profile leafpad.profile obs.profile silentarmy.profile virtualbox.profile Cyberfox.profile corebird.profile firefox-esr.profile gpg-agent.profile less.profile odt2txt.profile simple-scan.profile vivaldi-beta.profile FossaMail.profile cpio.profile firefox-nightly.profile gpg.profile libreoffice.profile okular.profile simutrans.profile vivaldi-stable.profile Gitter.profile cryptocat.profile firefox.profile gpicview.profile liferea.profile open-invaders.profile skanlite.profile vivaldi.profile Mathematica.profile curl.profile firejail.config gpredict.profile localc.profile openbox.profile skype.profile vlc.profile Telegram.profile cvlc.profile flashpeak-slimjet.profile gtar.profile lodraw.profile openshot.profile skypeforlinux.profile vym.profile Thunar.profile cyberfox.profile flowblade.profile gthumb.profile loffice.profile opera-beta.profile slack.profile w3m.profile VirtualBox.profile darktable.profile fontforge.profile guayadeque.profile lofromtemplate.profile opera.profile smplayer.profile warzone2100.profile Wire.profile deadbeef.profile fossamail.profile gucharmap.profile login.users orage.profile snap.profile waterfox.profile Xephyr.profile default.profile franz.profile gwenview.profile loimpress.profile palemoon.profile soffice.profile webserver.net Xvfb.profile deluge.profile frozen-bubble.profile gzip.profile lollypop.profile parole.profile soundconverter.profile weechat-curses.profile abrowser.profile dex2jar.profile gajim.profile handbrake-gtk.profile lomath.profile pcmanfm.profile spotify.profile weechat.profile akregator.profile dia.profile galculator.profile handbrake.profile loweb.profile pdfsam.profile sqlitebrowser.profile wesnoth.profile amarok.profile digikam.profile geany.profile hashcat.profile lowriter.profile pdftotext.profile ssh-agent.profile wget.profile android-studio.profile dillo.profile geary.profile hedgewars.profile luminance-hdr.profile peek.profile ssh.profile whitelist-common.inc apktool.profile dino.profile gedit.profile hexchat.profile lximage-qt.profile picard.profile start-tor-browser.profile wine.profile arduino.profile disable-common.inc geeqie.profile highlight.profile lxmusic.profile pidgin.profile steam.profile wire.profile ark.profile disable-devel.inc ghb.profile hugin.profile lxterminal.profile pingus.profile stellarium.profile wireshark-gtk.profile arm.profile disable-passwdmgr.inc gimp-2.8.profile icecat.profile lynx.profile pithos.profile strings.profile wireshark-qt.profile atom-beta.profile disable-programs.inc gimp.profile icedove.profile mate-calc.profile pix.profile supertux2.profile wireshark.profile atom.profile display.profile git.profile iceweasel.profile mate-calculator.profile pluma.profile synfigstudio.profile xchat.profile atool.profile dnscrypt-proxy.profile gitg.profile idea.sh.profile mate-color-select.profile polari.profile tar.profile xed.profile atril.profile dnsmasq.profile gitter.profile img2txt.profile mate-dictionary.profile psi-plus.profile telegram-desktop.profile xfburn.profile audacious.profile dolphin.profile gjs.profile inkscape.profile mathematica.profile qbittorrent.profile telegram.profile xfce4-dict.profile audacity.profile dosbox.profile globaltime.profile inox.profile mcabber.profile qemu-launcher.profile thunar.profile xfce4-notes.profile aweather.profile dragon.profile gnome-2048.profile iridium-browser.profile mediainfo.profile qemu-system-x86_64.profile thunderbird.profile xiphos.profile baloo_file.profile dropbox.profile gnome-books.profile iridium.profile mediathekview.profile qlipper.profile torbrowser-launcher.profile xmms.profile baobab.profile ebook-viewer.profile gnome-calculator.profile itch.profile meld.profile qpdfview.profile totem.profile xonotic-glx.profile bibletime.profile electron.profile gnome-chess.profile jd-gui.profile midori.profile qtox.profile tracker.profile xonotic-sdl.profile bitlbee.profile elinks.profile gnome-clocks.profile jitsi.profile minetest.profile quassel.profile transmission-cli.profile xonotic.profile bleachbit.profile emacs.profile gnome-contacts.profile k3b.profile mousepad.profile quiterss.profile transmission-gtk.profile xpdf.profile blender.profile empathy.profile gnome-documents.profile kate.profile mplayer.profile qupzilla.profile transmission-qt.profile xplayer.profile bless.profile enchant.profile gnome-font-viewer.profile kcalc.profile mpv.profile qutebrowser.profile transmission-show.profile xpra.profile brasero.profile engrampa.profile gnome-maps.profile keepass.profile multimc5.profile rambox.profile truecraft.profile xreader.profile brave.profile eog.profile gnome-mplayer.profile keepass2.profile mumble.profile ranger.profile tuxguitar.profile xviewer.profile caja.profile eom.profile gnome-music.profile keepassx.profile mupdf.profile remmina.profile uget-gtk.profile xz.profile calibre.profile epiphany.profile gnome-photos.profile keepassx2.profile mupen64plus.profile rhythmbox.profile unbound.profile xzdec.profile catfish.profile etr.profile gnome-twitch.profile keepassxc.profile musescore.profile riot-web.profile unknown-horizons.profile yandex-browser.profile cherrytree.profile evince.profile gnome-weather.profile kino.profile mutt.profile ristretto.profile unrar.profile youtube-dl.profile chromium-browser.profile evolution.profile goobox.profile kmail.profile nautilus.profile rtorrent.profile unzip.profile zathura.profile chromium.profile exiftool.profile google-chrome-beta.profile knotes.profile nemo.profile scribus.profile uudeview.profile zoom.profile claws-mail.profile fbreader.profile google-chrome-stable.profile kodi.profile netsurf.profile sdat2img.profile uzbl-browser.profile

It becomes a hassle to always prepend firejail to your commands, so you can easily configure your system to firejail everything you have a profile for. The command

$ sudo firecfg Configuring symlinks in /usr/local/bin audacious created audacity created brasero created cvlc created display created dnsmasq created evince created feh created filezilla created firefox created ghb created gimp created gimp-2.8 created gitg created gthumb created img2txt created inkscape created k3b created keepassxc created less created libreoffice created localc created lodraw created loffice created lofromtemplate created loimpress created lomath created loweb created lowriter created meld created mplayer created pdftotext created pidgin created simple-scan created soffice created ssh created ssh-agent created strings created telegram-desktop created tracker created transmission-gtk created vlc created wget created wireshark-gtk created

will create symlinks in /usr/local/bin for programs that exist in the profile folder, so that they will be opened by firejail.

Also, it comes with desktop integration, and a widget called firetools

You can create your symlinks to use firejail with any other program

$ sudo ln -s /usr/bin/firejail /usr/local/bin/<program name>

Sometimes, you want to run the program without the sandbox only once. For instance, you might want to use meld in arbitrary paths. Instead of editing the profile, you can just find the binary

$ which -a meld /usr/local/bin/meld /usr/bin/meld /usr/local/bin/meld /usr/bin/meld

, and knowing that the one in /usr/local/bin is the symlink, we can just invoke it as

$ /usr/bin/meld

Firejail advanced usage

You can check what applications you have sandboxed with

$ firejail --list 738:nacho:firejail --list 26599:nacho:firejail /usr/bin/filezilla 30047:nacho:/usr/bin/firejail /usr/bin/keepassxc 31180:nacho:/usr/bin/firejail /usr/bin/firefox

Likewise, you can inspect processes inside a sandbox with

$ firejail --tree 2126:nacho:/usr/bin/firejail /usr/bin/firefox 2140:nacho:/usr/bin/firejail /usr/bin/firefox 2201:nacho:/usr/lib/firefox/firefox 2129:nacho:/usr/bin/firejail /usr/bin/mumble 2145:nacho:/usr/bin/firejail /usr/bin/mumble 2221:nacho:/usr/bin/mumble 2131:nacho:/usr/bin/firejail /usr/bin/thunderbird 2152:nacho:/usr/bin/firejail /usr/bin/thunderbird 2225:nacho:/usr/lib/thunderbird/thunderbird 3286:nacho:gpg-agent --homedir /home/nacho/.gnupg --use-standard-socket --daemon 2738:nacho:/usr/bin/firejail /usr/bin/keepassxc 2739:nacho:/usr/bin/firejail /usr/bin/keepassxc 2745:nacho:/usr/bin/keepassxc

or monitor resources with –top or –netstats

$firejail --top PID User RES(KiB) SHR(KiB) CPU% Prcs Uptime Command 26599 nacho 59236 44404 13.0 3 00:07:33 firejail /usr/bin/filezilla 31180 nacho 761036 132316 12.0 3 00:02:14 firejail /usr/bin/firefox 369 nacho 2192 1940 0.0 1 00:00:09 firejail --top 30047 nacho 76340 56716 0.0 3 00:03:10 firejail /usr/bin/keepassxc

You can copy files in and out of the sandbox with –ls, –put and –get

$ firejail --name=mybrowser --private firefox $ firejail --ls=mybrowser ~/Downloads drwxr-xr-x netblue netblue 4096 . drwxr-xr-x netblue netblue 4096 .. -rw-r--r-- netblue netblue 7847 x11-x305.png -rw-r--r-- netblue netblue 6800 x11-x642.png -rw-r--r-- netblue netblue 34139 xpra-clipboard.png $ firejail --get=mybrowser ~/Downloads/xpra-clipboard.png $ firejail --put=mybrowser xpra-clipboard.png ~/Downloads/xpra-clipboard.png

You can traffic shape with –bandwidth ( download/upload 80KBps/20KBps )

firejail --bandwidth=mybrowser set eth0 80 20

You can even shell inside the sandbox with –join, in a similar way as doing docker exec -ti container bash

Other cool options are –disable-mnt which is self-explanatory and –chroot=dirname which will mount dirname read only.

The man pages contain excelent information.

Playing around

We can check our current namespaces with

$ lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 75 592 nacho /usr/lib/systemd/systemd --user 4026531836 pid 74 592 nacho /usr/lib/systemd/systemd --user 4026531838 uts 70 592 nacho /usr/lib/systemd/systemd --user 4026531839 ipc 74 592 nacho /usr/lib/systemd/systemd --user 4026531840 mnt 70 592 nacho /usr/lib/systemd/systemd --user 4026531993 net 75 592 nacho /usr/lib/systemd/systemd --user 4026532421 mnt 1 2201 nacho /usr/lib/firefox/firefox 4026532422 uts 1 2201 nacho /usr/lib/firefox/firefox 4026532423 pid 1 2201 nacho /usr/lib/firefox/firefox 4026532424 mnt 1 2221 nacho /usr/bin/mumble 4026532425 uts 1 2221 nacho /usr/bin/mumble 4026532426 pid 2 2221 nacho /usr/bin/mumble 4026532487 mnt 2 2225 nacho /usr/lib/thunderbird/thunderbird 4026532488 uts 2 2225 nacho /usr/lib/thunderbird/thunderbird 4026532489 pid 2 2225 nacho /usr/lib/thunderbird/thunderbird 4026532633 mnt 1 2266 nacho /usr/bin/ssh -Y xxxx@xxxxx.xxxx

, and elevated capabilities with

$ pscap ppid pid name command capabilities 1 266 root systemd-journal chown, dac_override, dac_read_search, fowner, setgid, setuid, sys_ptrace, sys_admin, audit_control, mac_override, syslog, audit_read 1 286 root systemd-udevd full 1 431 root systemd-logind chown, dac_override, dac_read_search, fowner, kill, sys_admin, sys_tty_config, audit_control, mac_admin 1 432 root dockerd full 1 441 root login full 432 450 root docker-containe full 1 732 rtkit rtkit-daemon dac_read_search, sys_ptrace, sys_nice 1 2984 root udisksd full 450 4405 root docker-containe full 4405 4423 root bash chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap 15942 8107 root sudo full 8107 8122 root wpa_supplicant full 1 10113 root upowerd full 450 10710 root docker-containe full 10710 10727 root run.sh full 10727 10814 root nginx full 10814 10815 root nginx full 10814 10816 root nginx full 10814 10817 root nginx full 10814 10819 root nginx full 10814 10820 root nginx full 10814 10821 root nginx full 10814 10822 root nginx full 10814 10823 root nginx full 10727 10830 root php5-fpm full 10727 10834 root nxlog full 10727 10835 root ntpd full 10727 10837 root mysqld full 10727 10842 root sshd full 10727 10847 root in.tftpd full 450 10925 root docker-containe full 10925 10946 root script full 10946 10953 root sh full 10953 10954 root bash full 1 17653 root systemd-hostnam sys_admin 10727 18157 root sleep full 450 21275 root docker-containe full 21275 21291 root bash chown, dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap

Obviously, only priviledged processes are susceptible of having capabilities in the first place, so no user processes on that list.

We can run wireshark with sudo in order for it to have access to the network interfaces. This is a bad idea: permissions should be set properly to avoid this, but we will do it for the sake of the example

$ sudo /usr/bin/wireshark $ pscap | grep wireshark 26219 26221 root wireshark-gtk full

We can compare that to running it in a sandbox, where it has dropped all capabilities that it doesn’t need

$ sudo firejail wireshark-gtk $ pscap | grep wireshark 26803 26817 root wireshark-gtk dac_override, net_admin, net_raw

References

For more advanced configuration options, including writing and auditing profiles, I usually refer to the following sites.

Arch wiki

Firejail home page

https://www.linux.com/news/understanding-and-securing-linux-namespaces