Browser Sandboxing: User Seatbelting
A cybersecurity expert discusses the concepts behind sandboxing, and the basic command line options available to get started.
Join the DZone community and get the full member experience.
Join For FreeSeatbelt, the predecessor to the modern app sandbox in *OS systems, has four major components: user space services provided by libsandbox.1.dylib and other system libraries, a mach server for logging, and two kernel extensions. We're going to start to dig into userspace services, and we'll start with sandbox-exec.
First, let's take a look at the internals of sandbox-exec. Let's do a little static analysis first.
So this is the first interesting tidbit. If you look at the man page for sandbox exec, you see four different command line options:
-f profile-file
Read the profile from the file named profile-file.
-n profile-name
Use the pre-defined profile profile-name.
-p profile-string
Specify the profile to be used on the command line.
-D key=value
Set the profile parameter key to value.
Looking at this decompilation sample, we see D, f, n, and p, but we also have c, lower case d, e, and t. Let's see what these might do in the disassembly first.
Trying sandbox-exec with these options yields interesting results: -t and -e error out of the code, displaying the help information. -c spawns the program, and -d seems to do nothing (likely a debug flag that processes everything except for the submitted program). We'll test this in LLDB.
First, running with the '-c' flag redirects execution to a code block that calls sandbox_apply_container()
. If we look through the arguments to sandbox_apply_container()
, you can see that the argument to the -c option is one of those arguments (the second, in fact). Tracing execution, you can see an eventual system call out of the executable to, it seems, set up a sandbox. The -d option seems to just skip the execvp()
call that replaces the current process image with the new program's image from the command line.
So, we've seen a large number of interesting calls into the libsandbox.1.dylib library, which is really what we were looking for. We wanted to have some idea of what these calls are, so we have some clue as to how sandboxing is implemented from user space.
What we've been able to find out is that the magic seems to happen, on Mojave at least, in sandbox_apply_container()
, which allows you to apply restrictions based on either a string containing TinyScheme code, a file containing TinyScheme code, a named profile (these names are no-internet, no-network, no-write, no-write-except-temporary, and pure-compilation; you can see them in the disassembled file or by running strings against sandbox-exec).
This is a departure from previous implementations of this sandbox - this code used to be called in sandbox_init()
. This is interesting as it indicates that this private sandbox API is still maintained by apple, and is likely built into the new app sandbox functionality.
Opinions expressed by DZone contributors are their own.
Comments