Software Sandboxing: The Basics

vinipsmaker1 pts0 comments

Software sandboxing: The basics

Software sandboxing: The basics

Menu

Home

PDF

EPUB

JSON Feed

Diving into the territory of software sandboxing is diving into mostly uncharted<br>territory. The necessary pieces to implement good sandboxing in your software<br>are scattered all-around and the pioneers haven’t yet gathered enough knowledge<br>into an unified mappa mundi that can guide new sailors through some well<br>understood safe routes. In this blog post I’ll offer my own share of experiences<br>that I have acquired while working on sandboxing support for Emilua. Writing<br>style will suffer a little because I’ll err on the side of repeating myself too<br>much to avoid any misunderstandings.

Do keep in mind that some Lua code samples here require the<br>unreleased Emilua 0.11 (just grab a recent commit from the repo’s development<br>branch).

First, let’s get some informal (but useful) definition for sandboxing just to<br>make sure we’re on the same page. Here’s<br>the<br>definition that was used by Julien Tinnes and Chris Evans at Hack In The Box<br>Malaysia 2009:

The ability to restrict a process' privileges:

Programmatically;

Without administrative authority on the machine;

Discretionary privilege dropping.

That’s a very good definition to keep the ball rolling. Let’s quickly iterate<br>over each point individually to make them crystal clear. However keep in mind<br>that the opinions I possess today are a little different from the<br>opinions J. Tinnes and C. Evans had during the 2009 talk (especially around “is<br>it okay to use superuser APIs?”), so my explanations will differ a little and<br>guide you towards what I consider better practices for 2025.

Programmatic privilege dropping

OSes present different interfaces to users and software developers. System<br>administrators traditionally rely on filesystem permissions to isolate services<br>(UNIX daemons). If we allowed third-party programs to freely change such<br>permissions then it’d nullify the policies the sysadmin was trying to enforce to<br>begin with.

Furthermore third-party programs abstract their own virtual worlds and most of<br>the time UNIX filesystem permissions aren’t a good fit to model the security<br>policies such other virtual worlds require. Do you use UNIX permission modes to<br>define who can see your Twitter feed or message you on Identi.ca? Filesystem<br>permissions aren’t the only knobs sysadmins possess to restrict access rights,<br>but the reasoning developed here also apply to these other knobs.

Nonetheless a process inevitably runs on top of an OS and there are<br>kernel-exposed resources the process interacts with (e.g. files). It’s this<br>interface that matters to the software developer. Web browsers such as Firefox<br>run DRM plugins and it’s desirable to run such third-party plugins without<br>allowing them to have full access to every file that Firefox has access to<br>(usually every file in the user’s HOME directory). Traditional tools such as<br>setuidgid can’t help here and their usefulness is limited as interfaces<br>sysadmins turn to. setuidgid and similar tools aren’t interfaces intended for<br>the software developer to use.

XKCD 1200: Authorization

For programmatic privilege dropping, traditional UNIX interfaces are a poor<br>match, and OSes where this gap actually matters will provide extended interfaces<br>that go beyond traditional UNIX (e.g. FreeBSD’s Capsicum and Linux’s Seccomp).

Dropping privileges without root

When good interfaces for sandboxing weren’t available, programmers found their<br>way to create sandboxes anyway by abusing mechanisms available only to the<br>superuser. The most emblematic technique in this class is a helper suid binary<br>that’ll configure a chroot jail.

The obvious problem with these approaches is that they aren’t available to all<br>programs. Allowing any program to install suid binaries defeat any security<br>measures. Suid binaries equal to temporally raising privileges to full<br>administrative authority over the system. Privileges should only ever decrease,<br>never increase (principle of least privilege).

Another related concern here is to not design APIs that backfire by<br>exponentially increasing the kernel attack surface. The Docker boom popularized<br>Linux namespaces as a mechanism to cheaply isolate services. However within a<br>nested user namespace, the process runs as superuser (within that namespace),<br>and code paths within the kernel that would normally only be available to the<br>superuser are now available to every user. We have over a decade of kernel code<br>that was never written with this premise in mind. This decision caused security<br>problems in the past, and it’s bound to happen again. To quote Andy Lutomirski:

I consider the ability to use CLONE_NEWUSER to acquire CAP_NET_ADMIN over<br>any network namespace and to thus access the network configuration API to be a<br>huge risk. For example, unprivileged users can program iptables. I’ll eat my hat<br>if there are no privilege escalations in there.

— Andy...

software sandboxing interfaces privilege unix available

Related Articles