Quarantine for untrusted applications
There are many buggy applications out there, and there's very
little that prevents one application to do very bad things to the user
running it. Buffer overruns in applications are pretty common (see
buffer overrun in pine, for example), and we do not want malicious
incoming mail to delete user's files, do we?
What can we do with that? Fixing all applications is hard, as some
of them are closed-source, and there's much too much open-sourced ones.
One possible solution is to design sandbox (or quarantine), and run
untrusted applications inside sandbox. When sandbox is properly setup,
buffer overrun in application is not that dangerous. It will
still be able to harm data it is working with, but it can no longer
broadcast your .ssh/identity to the world.
There are quite a few projects that are trying to deal with it:
- (1) Goldberg, Wagner, Thomas, Brewer: Janus: A secure
environment for untrusted helper applications: confining the wily
hacker. It uses ptrace-like interface to trace untrusted executable
and not let it do dangerous things. It has slight problem:
it does not work. Due to volatile memory problems,
application is able to circumvent protection. [Estabilishing shared
memory between two programs, then doing
open(pointer_to_shared_memory), and rapidly changing content of
shared memory. If you are lucky, kernel sees other path than
monitor.]
- (2) Dan, Mohindra, Ramaswami, Sitaram: ChakraVyuha:
A Sandbox Operating System Environment for Controlled Execution of
Alien Code. They put all their changes into linux kernel. I tried to
contact IBM to get sources, but did not get them.
- (3) User
mode linux: is linux emulator on top of linux. With some
modifications, it could be used as sandbox. Getting the networking
right would be pretty hard to do without root priviledges, through.
- (4) myself: podfuk
is system for placing filesystems into userland. In combination with
root priviledges and setuid chrooter, it could be used to restricting
filesystem operations.
- (5) Deny and allow. Other method how to do sandbox would be to add
capabilities like "user can read his own files". Then, you run
untrusted applications without those capabilities. That would not
work with applications more complicated than grep. (That was deny
part). Now, if app wants to do some more complicated operation, it
has to nicely ask sandbox to do the work for her. (But you don't
want to modify each application, do you). LD_PRELOAD is the way to
go here.
- (6) subterfugue is python
(ouch) system that uses ptrace() to do various things to
applications. Rot13-ing all data apps write using write syscall is
example of its power. It is powerfull enough to properly sandbox
application. Volatile memory races can be solved by copying data
into memory that is read-write to sandbox, but read-only to
sandboxed application. And that can be done with some
trickery. This is currently my favourite toy. Its
disadvantage is that it is slow -- python is
interpretted language.
Details about subterfugue solution
Problem with ptrace() is than in-memory arguments can change
between sandbox checking them and kernel executing them. (See example
near janus.) My solution looks like this:
- /tmp/mmap-safe file is opened read-only as filehandle
123. This handle is passed to untrusted application.
- When application does first syscall, mmap() of handle 123 into
0x3f000000 area of memory is executed on its behalf.
- When application does syscall like open("./foo"), name is
resolved into "/bar/foo", which is then written to
/tmp/mmap-safe. Pointer to "./foo" is changed into
0x3f000000 (or similar), which now contains
"/bar/foo". (It is tiny a bit more complicated than this, as
we want multiple apps to be able to enter syscall at once, but you got
the idea.)
- Application is prevented from tampering with handle 123. (Module NoClose123)
- Application is prevented from tampering with memory at 0x3f000000. (Module NoMunmap)
I believe this is safe. It has few problems, through:
/proc/self is symlink which depends on who is
looking. /proc/XXX/fd/X is symlink which says it is pointing
to some bogus place, but actually works if you try anyway.
Gnome sandbox
My "gnome sandbox" currently looks like this:
- subterfugue has option to put its own output onto fd3, so that it is
not mixed with stdout nor stderr of task being sandboxed.
- PathSandbox trick reads config file. It is able to reread config
file at will (and will reread config file on SIGUSR1 or SIGUSR2).
- when unallowed operation is encountered, question is written onto
fd3. Gnome part parses output on fd3, and asks user the question. If
operation is to be allowed, SIGUSR1 is sent, otherwise SIGUSR2 is
sent. [This has big advantage of being able to use manually: killall
-USR1 python is not that difficult to do manually.] Config file is
reloaded.
- gnome frontend may decide to modify config file when it is asking
question. That's ok: config will be reloaded by python backend.
It has big advantage of gnome part (written in C) being cleanly
separated from python part.
Pavel Machek
pavel@ucw.cz