Running Mozilla Firefox
Running a chroot Sandbox
Sandboxing Users at Login Time
Joining an Existing Sandbox
Listing Sandboxes and Processes
$ firejail [options] program_and_arguments
$ firejail netstat -rn Parent pid 7961, child pid 7962 Interface IP Mask Status lo 127.0.0.1 255.0.0.0 UP eth0 192.168.1.50 255.255.255.0 UP Child process initialized Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 parent is shutting down, bye... $
Fierjail configures a basic sandbox, runs the program and exits. The sandbox consists of a mount namespace and a new process namespace. In the mount namespace, the main system directories are mounted read-only.
Without any arguments, Firejail starts a regular /bin/bash shell. Only the bash session and its descendants are visible in the sandbox:
$ firejail Parent pid 8037, child pid 8038 Interface IP Mask Status lo 127.0.0.1 255.0.0.0 UP eth0 192.168.1.50 255.255.255.0 UP Child process initialized [netblue@debian ~]$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND netblue 1 8.0 0.4 21004 3724 pts/0 S 09:56 0:00 /bin/bash netblue 44 0.0 0.1 16836 1196 pts/0 R+ 09:56 0:00 ps aux [netblue@debian ~]$
Any type of GUI programs should work in the sandbox. Sound, video and hardware acceleration available on the host platform, should also be available in the sandbox. This makes Firejail ideal for running untrusted programs such as Google Chrome, Dropbox, Skype, Adobe Reader, games.
Running Web Browsers
The command to start Mozilla Firefox is firejail firefox. You can use –debug flag to get status messages as the sandbox is created.
The sandbox mounts read-only the main filesystem directories, and disables /sbin, /usr/sbin and /boot. It also disables some SUID executables such as mount and su. Several user files and directories storing encryption keys and certificates are also blocked. An attacker gaining control of the browser will have no access to these files. Firejail also restricts the processes visible in the sandbox, making Firefox PID 1. On top of all these, Linux capabilities and default seccomp filters are enabled.
ALSA and PulseAudion, flash and html 5 videos are all supported in the sandbox. The projects includes default security profiles for Mozilla Firefox, Chromium, Opera and Midori web browsers. For more information check out this article.
Seccomp is a filtering mechanism that enables the user to specify the system calls that should be allowed (whitelisting) or forbidden (blacklisting) for all processes running in the sandbox. Currently, Firejail supports syscall blacklisting and whitelisting. It also implements an easy to use default blacklist filter. This filter disables most administrative system calls. This filter is enabled by –seccomp command line option.
$ firejail --seccomp program_and_arguments
The seccomp filter immediately terminates the program if any of the following system calls are made: mount, umount2, ptrace, kexec_load, open_by_handle_at, init_module, finit_module, delete_module, iopl, ioperm, swapon, swapoff, mknode, syslog, process_vm_readv, process_vm_writev, sysfs, _sysctl, adjtimex, clock_adjtime, lookup_dcookie, perf_event_open, fanotify_init and kcmp. Additional syscalls can be specified as a parameter to –seccomp option, for example:
$ firejail --seccomp=chmod,fchmod,fchmodat program_and_arguments
Berkeley Packet Filter support for seccomp was introduced in Linux kernel 3.5. A warning is printed on the terminal if the filter cannot be installed.
Private mode is a quick way of hiding all the files in your home directory from programs running inside the sandbox. It is enabled using –private command line option:
$ firejail --private program_and_arguments
Firejail mounts a temporary tmpfs filesystem on top of /home/user directory. Any files created in this directory by the sandboxed programs, will be deleted once the sandbox exits. You can also use an existing directory as home directory for your sandbox, allowing you to have a persistent sandbox home:
$ firejail --private=~/my_private_dir program_and_arguments
Running a chroot Sandbox
Firejail can mount an existing root filesystem using –chroot command line option. The filesystem can be a full Linux distribution installed on a different disk partition, a filesystem built using regular distro tools such as debootstrap, or even a filesystem extracted from an OpenVZ template.
In this example we create a sandbox for a basic Debian filesystem. As root, we start by running debootstrap in a new directory:
# mkdir /imgs && cd /imgs # debootstrap --arch=amd64 jessie jessie
We start the sandbox as usual, passing Debian root directory as a parameter to –chroot:
# firejail --chroot=/imgs/jessie --name=jessie Parent pid 21466, child pid 21467 Interface IP Mask Status lo 127.0.0.1 255.0.0.0 UP eth0 192.168.1.50 255.255.255.0 UP Child process initialized [root@jessie ~]$
If the sandbox is started as a regular user, Linux capabilities and default seccomp filters are enabled. The user is placed inside chroot directory in the same user id account – UIDs on the host and in chroot system should match. For more chroot examples check out this article.
A network namespace is basically a separate TCP/IP stack attached to the sandbox. The new stack has its own socket space, ARP and route tables, a separate netfilter/iptables firewall, and its own set of interfaces created using –net command line option. The sandbox is usually connected to the host stack on a regular kernel bridge device.
In this example vm1 sandbox connects to the host br0 bridge. br0 needs to be created and configured before vm1 sandbox is started using –net=br0:
(as root) # brctl addbr br0 # ifconfig br0 10.10.20.1 (as regular user) $ firejail --net=br0 --ip=10.10.20.10 Parent pid 14749, child pid 14750 Interface IP Mask Status lo 127.0.0.1 255.0.0.0 UP eth0 10.10.20.10 255.255.255.0 DOWN Child process initialized [netblue@debian ~]$
If no IP address is specified, Firejail will find one not in use on bridge br0 and assign it to the sandbox:
$ firejail --net=br0 Parent pid 14817, child pid 14818 Interface IP Mask Status lo 127.0.0.1 255.0.0.0 UP eth0 10.10.20.69 255.255.255.0 UP Child process initialized [netblue@debian ~]$
Other networking options are –ip=none used mainly for DHCP setups, –defaultgw to set a default gateway, –dns to set DNS servers, and –netfilter to specify a firewall configuration. Up to four networks can be specified using –net option. Sandboxes can be connected via bridge devices or macvlan devices in any kind of network topologies. This article describes a simple DMZ setup used to secure a web server.
Use sleep inf to keep Firejail sessions alive while running daemons:
# firejail "/etc/init.d/lighttpd start && sleep inf" # firejail --net=br0 "/etc/init.d/ssh start && sleep inf"
This article describes a full WordPress setup in a jailed environment.
Sandboxing Users at Login Time
Firejail can also work as a user login shell in /etc/passwd. Started by telnet or SSH server, firejail interprets it as a login request, grabs extra user arguments from /etc/firejail/login.users, configures the sandbox and passes the control to /bin/bash.
The steps to configure a jailed user account are as follows:
- Set firejail as a shell in /etc/password (adduser –shell /usr/bin/firejail username, or chsh /usr/bin/firejail username).
- Add extra arguments in /etc/firejail/login.users file.
For example, a sandbox set as firejail –debug –net=br0 requires the following line in /etc/firejail/login.users (I have bingo as username):
For more details, check out this article.
Joining an existing sandbox
To join an existing sandbox, you need to find the PID of the sandbox (–list option), and pass this PID to firejail using –join option:
$ firejail --list 3787:netblue:firejail --seccomp --private 3860:netblue:firejail iceweasel 3963:root:firejail /etc/init.d/nginx start && sleep inf $ firejail --join=3860 Switching to pid 3861, the first child process inside the sandbox [netblue@debian ~]$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND netblue 1 12.1 4.5 996168 320576 ? Sl 07:33 1:59 iceweasel netblue 77 2.5 0.0 20916 3716 pts/2 S 07:49 0:00 /bin/bash netblue 120 0.0 0.0 16840 1256 pts/2 R+ 07:49 0:00 ps aux [netblue@debian ~]$
It works like a regular terminal login in the sandbox. The new shell session inserted in the sandbox has all the restrictions the processes running in the sandbox have, including seccomp and Linux capabilities. It could be used for a quick audit of the sandbox, or to start new processes inside the sandbox.
Joining namespaces was introduce in Linux kernel version 3.8. If running on a system with an earlier kernel, –join will exit with an error.
Listing Sandboxes and Processes
Called with –list option, Firejail will list all running sandboxes:
$ firejail --list 3787:netblue:firejail --seccomp --private 3860:netblue:firejail iceweasel 3963:root:firejail /etc/init.d/nginx start && sleep inf $
Each line represents a sandbox. The format for the information is PID:user name:command.
Called with –tree option, Firejail will print the process tree for each sandbox:
$ firejail --tree 3787:netblue:firejail --seccomp --private 3788:netblue:/bin/bash 3983:netblue:/opt/trickle/tmon 3860:netblue:firejail iceweasel 3861:netblue:iceweasel 3963:root:firejail /etc/init.d/nginx start && sleep inf 3964:root:/bin/bash -c /etc/init.d/nginx start && sleep inf 3969:root:nginx: master process /usr/sbin/nginx 3970:www-data:nginx: worker process 3971:www-data:nginx: worker process 3973:www-data:nginx: worker process 3974:www-data:nginx: worker process 3972:root:sleep inf $
–top option is similar to the regular process top command in Linux:
$ firejail --top PID User RES(KiB) SHR(KiB) CPU% Prcs Uptime Command 3860 netblue 333388 36212 1.2 2 00:12:49 firejail iceweasel 3787 netblue 5404 3116 0.0 3 00:14:18 firejail --seccomp --private 3963 root 11532 4860 0.0 8 00:11:40 firejail /etc/init.d/nginx start && sl
All the process creation, exit, forks and uid/guid changes can be monitored using firemon utility. root privileges are required to run firemon.
Another monitoring tool is provided by Firejail using –trace command line option. It is based on system call interposition, and it traces open, unlink, mkdir, rmdir, stat, access, socket, connect, and bind calls into glibc. This is a small example:
$ firejail --trace wget -q debian.org Parent pid 4307, child pid 4308 Interface IP Mask Status lo 127.0.0.1 255.0.0.0 UP eth0 192.168.1.60 255.255.255.0 UP Child process initialized 1:bash:open /dev/tty 1:wget:fopen64 /etc/wgetrc 1:wget:fopen /etc/hosts 1:wget:socket AF_INET SOCK_DGRAM IPPROTO_IP 1:wget:connect 18.104.22.168:53 1:wget:socket AF_INET SOCK_STREAM IPPROTO_IP 1:wget:connect 22.214.171.124:80 1:wget:fopen /etc/hosts 1:wget:socket AF_INET SOCK_DGRAM IPPROTO_IP 1:wget:connect 126.96.36.199:53 1:wget:socket AF_INET SOCK_STREAM IPPROTO_IP 1:wget:connect 188.8.131.52:80 1:wget:fopen64 index.html parent is shutting down, bye... $