Random BSD Notes

How to run X Applications as another User

I sandbox some applications on all systems I use and I run them under another user. I do this for multiple reasons:

  • If the application is compromised, the attacker cannot directly access my home directory. Yes, there was a 0day vulnerability in Firefox that has been actively exploited.
  • You have an application you don’t trust but somehow need to run.

Examples of applications I run as another user:

  • All web browsers (Firefox for daily usage, Iridium for “unprotected” web access to book stuff, etc)
  • Tor Browser
  • Commercial clients on Linux like Dropbox

Getting Started

The following steps show how to do this on OpenBSD but it also works on other BSDs and Linux as well. On Linux you need to look up the correct iptables rules.

I use xodo to run X programs under another user. While I could do this by hand, xodo does all that stuff for me. And since I am lazy… Download xodo from GitHub and place it in the path of your choice, mine is under /usr/local/bin.

# ftp https://raw.githubusercontent.com/garotosopa/xodo/master/xodo.sh
# mv xodo.sh /usr/local/bin/xodo
# chmod a+x /usr/local/bin/xodo

An alternative to xodo is SSH. Basically, you run a SSH server on localhost and do the following steps:

scp ~/.Xauthority firefox@
ssh firefox@ -n "export DISPLAY=:0.0; TZ=UTC exec firefox"

Create a new User and Privilege Escalation Rules

xodo has a special option to add a new user to the system can creates the needed doas/sudo rules automatically.

# xodo --setup /usr/local/bin/firefox --as firefox --for joe
The following steps will be executed:
 - add user firefox if it doesn't exist;
 - make firefox's home readable and writable by its group;
 - add group firefox to user joe;
 - add an entry to /etc/doas.conf
   allowing existing user joe
   to execute /usr/local/bin/firefox
   as new user firefox with no password.
Proceed? [y/n] y
If user joe is logged in, it must log out and in again before using xodo as firefox, so that it gets added to the new group.

After this is done you have a new user on the system and a doas/sudo rule to run the specified command:

# cat /etc/doas.conf
permit nopass setenv { DISPLAY HOME=/home/firefox USER=firefox } joe as firefox cmd /usr/local/bin/firefox
# id firefox
uid=1000(firefox) gid=1000(firefox) groups=1000(firefox)

How to start the Application

Now I have the needed prerequisites to start Firefox as another user but how do I start it? The simplest solution would be a shell script/alias to run it. If you’re running a current version of OpenBSD (> 6.3) Firefox is pledged and requires a running D-Bus session. Otherwise, it will be killed by pledge. Thus, I created a small shell script to set the session up in advance. You might not need it if you run a full-blown desktop environment.

$ cat /usr/local/bin/ffdbus
/usr/local/bin/dbus-launch /usr/local/bin/firefox "$@"

Don’t forget to replace firefox with ffdbus in the Exec line of the desktop file.

If you use a window manager that honors desktop files you can use the following.

$ cat ~/.local/share/applications/ Firefox\ Default.desktop
#!/usr/bin/env xdg-open
[Desktop Entry]
Name=Firefox Default
GenericName=Web Browser
Comment=Browse the Web
Exec=/usr/local/bin/xodo firefox --as firefox %u

Limit the Application’s Disk Space

Depending on your application you might want to limit the disk space the sandbox user might take up. Just to make sure that the application or a malicious user that took over the application cannot fill up your partition. You do use separate partitions on your systems, do you? I do this by just using disk quotas on the partition.

As you can see I allow 500MB as hard limit for my Firefox. Keep in mind that this is enough for most uses cases, however, not for large downloads. Just adjust the number to a value that suitable for your needs.

# quota firefox
Disk quotas for user firefox (uid 1001):
  Filesystem  KBytes    quota   limit   grace    files   quota   limit   grace
       /home  167252        0  500000            1462        0       0

Restrict Network Access

Sometimes it might be desirable to also block all outgoing network traffic for the user of the sandboxed application. The following example shows how to block all outgoing TCP and UDP traffic for the user sandbox with OpenBSD’s pf. Add this line to the beginning of your /etc/pf.conf.

block out quick proto { tcp, udp } from self user sandbox

Note that only TCP and UDP can be firewalled by pf.

$Id: sandbox.md,v 1.4 2019/06/09 12:11:18 cvs Exp $