Multi-multi-user: sandboxing with multiple user accounts

Discussion in 'all things UNIX' started by Gullible Jones, Feb 15, 2013.

Thread Status:
Not open for further replies.
  1. Hungry Man already did a tutorial on this on his blog, but I figured I had something to contribute with a simpler approach. This ends up working out kind of similar to Sandboxie. It does not involve any use of ACLs, only standard UNIX DAC; and should work on any UNIX, not just Linux.

    Obviously some caveats apply. Like MAC, this will not protect you from a kernel vulnerability; it will not protect you from individual applications being compromised; and it will not prevent data leaks between applications running in the same "sandbox." Also, all manner of X11 hackery is probably possible, unless you choose to use a separate Xephyr session for each sandbox.

    Also, creating secondary user account can only be done as root (unless you want to make your system less secure). So on multi-user setups, limited users will need the admin's permission to create new sandboxes.

    Anyway, here's how you do it.

    Create your sandbox user.

    The "sandbox" is just another user account, minus some of the normal privilges. e.g. If your username is jdoe, you could run

    useradd -m -g users -G audio -s /bin/false jdoe-box0

    There are a few noteworthy things here...

    - The sandbox user should not have membership in any more groups than strictly necessary. Membership in the audio group is required for playing sounds on some distros, though not on ones that use Pulseaudio. On the majority of distros (and on *BSD) no additional groups should be necessary.

    - For security (and convenience) reasons, you do not want this user to be able to log in. Therefore you should set the login shell to /bin/false or somesuch.

    - Note also the account's name, which is derived from the name of the main user. This is to preserve your sanity in multi-user environments. Different "primary" users should never share a sandbox user; that would give them access to each other's sandboxed data, with no way to tell whose was whose. Likewise, keep in mind that you might want to add more sandbox accounts at some point.

    Grant access to the new user through sudo

    Add a line to sudoers allowing your account to invoke commands in the sandbox account, without a password. e.g. for the example above with jdoe, it would be

    jdoe ALL=(jdoe-box0) NOPASSWD: ALL

    Make sure you specify the sandbox user only. If you specify "ALL" or some other user, that will effectively ruin your system's security.

    Grant the new user access to your X sesion

    Unless you decide to use a Xephyr display for the sandbox user, you'll unfortunately have to add something like the following to your ~/.xprofile, or somewhere else it will get loaded on login:

    xhost +si:localuser:jdoe-box0

    This will allow the sandbox account access to your X session. Obviously this must be done for every additional sandbox account. As a precaution against abuse of X-related privileges, xhost settings should probably not be changed globally on multiuser systems.

    Launch some applications

    Like this, for instance:

    sudo -u jdoe-box0 firefox

    If you want to make it automatic, just create a desktop launcher that invokes whatever program in that fashion.

    If too much cruft accumulates in your sandbox account, you can start a shell in the account with sudo:

    sudo -u jdoe-box0 bash

    And then cd into the home directory and delete whatever offends you.

    Further considerations

    You probably want to block read access to your main account's data, otherwise your documents could be read from the sandbox account. Some distros (Arch Linux for instance) keep user home directories private by default; most don't. If yours doesn't, you can remedy that by running something like:

    chmod 0700 /home/jdoe

    Usually this does not have to be run as root.

    You could also keep your sandboxes world-readable by chmodding them 755 and setting the accounts' umask to 0022. This isn't really necessary though - you have full access to the sandbox account through sudo, so you can just launch whatever program (video player, PDF reader, etc.) in the sandbox.


    This method of "sandboxing" is probably relatively weak, compared to a well designed chroot jail or AppArmor profile. However, it IMO has an advantage over both of them in simplicity; it's easy to do it right.

    That said, sandbox accounts are full (if limited) user accounts, and provide full read and execute access to most of the filesystem, including setuid binaries. So:

    - Don't assume this tactic is safe for production environments.
    - Don't let it lull you into a false sense of security.
    - Don't blame me if something goes horribly wrong. (I did warn you!)

    To put it even more bluntly: sandbox accounts rely on there not being local privilege escalation exploits. Unfortunately, local exploits crop up all the time on most UNIXes. So keep that software up to date! If you're on a distro like Slackware, that doesn't provide binary kernel updates, then I'd also advice compiling a new kernel from time to time.

    Other thoughts

    It would be cool to have some kind of Sandboxie-like GUI for managing multiple user accounts. Maybe I'll see if I can create one, at some point in the indefinite future... Once I've got a handle on writing GUIs.

    Finally, thanks for this go to Hungry Man, for answering some of my earlier questions on it and outlining a similar process on his blog. I'd also like to thank an anonymous poster on some forgotten Linux news site, for offering the opinion that the most pathological idea in the history of UNIX has been the association of one user with one user account. Here's to thinking outside the box.

    Edit: one final note - at least some Window managers (e.g. Metacity) will display the user a program is running as. So keeping track of which windows are from which sandbox account will likely not be an issue.
    Last edited by a moderator: Feb 15, 2013
  2. One more thing: on some distros (e.g. OpenSUSE 12.2) you may have to export the correct value for DISPLAY when running graphical applications, e.g.

    sudo -u jdoe-box0 DISPLAY=$DISPLAY firefox

    Otherwise the application will fail to launch. Not sure why this only happens on some distros, if anyone can explain I'd be interested.

    Edit: ah, this is a matter of sudo settings; it's because sudo is not preserving environment variables. Which is probably a good thing, actually. Anyway, the DISPLAY=$DISPLAY hack works, so what the heck.
    Last edited by a moderator: Feb 15, 2013
Thread Status:
Not open for further replies.