$Id: manual-privsep,v 1.6 2021/11/23 02:53:38 nanons Exp $

Manual privilege separation
===========================

In general, all programs from OpenBSD's base system that can be
privilege separated already are.  Unfortunately, the same can't be said
about most third party programs with lower standards of code quality.

While "sandboxing" is possible at the time of writing, it's strongly
discouraged for security reasons and will eventually be removed:

	https://marc.info/?t=160070764700007&r=1&w=2

The only option for minimizing attack surface while executing dangerous
code is running programs as unprivileged users, optionally also inside
a chroot(2) environment (using chroot(8) with the -u flag).

Unprivileged users
==================

Using the lynx browser as an example:

	# pkg_add lynx

Create the unprivileged user, let's call it "lynx":

	# useradd -m -d /home/lynx -s /sbin/nologin lynx

Depending on the program, a home directory or valid shell may or may not
be needed.  First try with a home directory of /nonexistent and shell of
/sbin/nologin, then change if it doesn't work.

For lynx, a home directory is needed for ~/.lynxrc, but the shell is
unnecessary as OpenBSD's port of lynx uses pledge(2) to deny itself
access to running executables.

From then on, always start lynx as the unprivileged user:

	$ doas -u lynx /usr/local/bin/lynx

See doas(1) and doas.conf(5) for allowing your user to access doas and
disabling the password prompt, and ksh(1) or csh(1) for aliasing
lynx to run with the doas command when invoked as "lynx".

A word of caution: Without chroot(2), unprivileged users can read
world-readable files, including your home directory or each other's
home directories.  Restricting access to these is recommended:

	# chmod o-rwx /home/lynx $HOME

Graphical software
==================

Running graphical software as different users is not enough because they
can also access the X11 server and keylog, type, or record the screen.

To restrict access to the main X11 server, either run multiple X11
servers (see xenodm(1) and ttys(5)) or set up untrusted X11 connections.
Untrusted connections are much more limited and can't run some programs.

The easiest way to set up an untrusted connection is ssh(1)-ing locally.
X11Forwarding must be first enabled (see ssh/sshd_config).  Then, to run
a graphical program, for example xeyes(1), as the user "puffy" over an
untrusted X11 connection:

	$ ssh -X puffy@localhost xeyes

The harder way is manually using xauth(1).  It is faster than the
ssh(1) method because it accesses X11 directly.
To use it, append to /etc/X11/xenodm/Xsetup_0:

	users="puffy salmah"
	umask 077
	for user in $users; do
		eval auth=~$user/.Xauthority
		xauth -f $auth generate :0 . untrusted timeout 0
		chown $user $auth
	done

Note: If xenodm(1) autoLogin is enabled, Xsetup_0 will not be sourced.
The snippet should be copied to /etc/X11/xenodm/GiveConsole instead.

This will create untrusted cookies for the users "puffy" and "salmah"
when X11 is started.  The users need to have a valid home directory.
Simply run X11 programs as those users to automatically use untrusted
connections:

	$ doas -u puffy xeyes

Don't use untrusted connections with your own user that can access X11
normally, programs can simply read your trusted Xauthority cookie and
gain privileged access that way.
