The other day some of my colleagues and I were discussing a recent request for the Linux Kernel to add "security sandbox" functionality. We talked about how we could do this with SELinux. The discussions brought up an old Bug report of my about writing policy for the "little things". SELinux does a great job of confining System Services, but what about applications executed by users. The bug report talked about confining grep, awk, ls ... The idea was couldn't we stop the grep or the mv command from suddenly opening up a network connection and copying off my /etc/shadow file to parts unknown.
Could we write an SELinux policy that allows users to build scripts to process untrusted content into some output that they could safely use.
cat /tmp/UNTRUSTEDCONTENT | sandbox /sbin/filter.sh > /tmp/SEMITRUSTEDCONTENT
Another possible use case would be to tie sandbox into GRID jobs, or Condor. I could image an administrator saying that I will allow a grid job to run on my machine but I want SELinux to sandbox the job and make sure it causes no harm to my system, or from my system. I do not want GRID jobs becoming Spam Bots or somehow attacking the rest of my system. I definitely do not want them touching my homedir, since that is where firefox stores my credit card data.
I decided to write a policy called sandbox, it took me approximately 10 button clicks using system-config-selinux/polgengui in F11. I will show you how I did this later in the blog, if you are interested. You could use runcon to cause unconfined_t user domain to transition to the sandbox_t domain, but I decided to build a new tool called /usr/bin/sandbox that would do this for you.
The tool and policy are currently available in selinux-policy-3.6.12-41.fc11 and policycoreutils-2.0.62-12.6.fc11. My current intention with sandbox is not to handle X Apps, since these apps want to write all over the home directory ~/.gconf, ~/gnome., ~/.config ... and all over /tmp, along with use privs to talk to the X Server. I have some ideas on this for the future that I hope to experiment with.
So what were my security goals in writing sandbox.
Can not "Open or Create any files on the system".
Can not use the network.
Should only be able to read a small amount of the system
The sandbox command can take a --type (-t) qualifier to allow it to run the job with an alternative domain. So you could write policy to only run sandbox's with out shared libraries, or you could run a sandbox that is able to use one or two network ports.
sandbox command has a --mount (-m) option. This will mount a tmpfs file system under /mnt, labeled sandbox_file_t, then it cd to this directory so the sandboxed apps can write to their current working directory.
Multiple sandboxes could be running at the same time so we want to make sure they can not interact together, so I added "mcs" protection to them. Each sandbox runs with a slightly different MCS label meaning that one process can not interfere with another.
Sandbox is allowed to write to the terminal, since users would expect this.
One test I have run with it is
> sandbox id -Z
unconfined_u:unconfined_r:sandbox_t:s0:c87,c905
This command shows that sandbox ran the id command under the sandbox_t domain and chose the MCS label s-:c87,c905
If I wanted to create a file of users on my system from the /etc/passwd file, I could try
> sandbox cut -d: -f1 /etc/passwd > /tmp/users
/bin/cut: /etc/passwd: Permission denied
Read more: Dan Walsh's Blog
Could we write an SELinux policy that allows users to build scripts to process untrusted content into some output that they could safely use.
cat /tmp/UNTRUSTEDCONTENT | sandbox /sbin/filter.sh > /tmp/SEMITRUSTEDCONTENT
Another possible use case would be to tie sandbox into GRID jobs, or Condor. I could image an administrator saying that I will allow a grid job to run on my machine but I want SELinux to sandbox the job and make sure it causes no harm to my system, or from my system. I do not want GRID jobs becoming Spam Bots or somehow attacking the rest of my system. I definitely do not want them touching my homedir, since that is where firefox stores my credit card data.
I decided to write a policy called sandbox, it took me approximately 10 button clicks using system-config-selinux/polgengui in F11. I will show you how I did this later in the blog, if you are interested. You could use runcon to cause unconfined_t user domain to transition to the sandbox_t domain, but I decided to build a new tool called /usr/bin/sandbox that would do this for you.
The tool and policy are currently available in selinux-policy-3.6.12-41.fc11 and policycoreutils-2.0.62-12.6.fc11. My current intention with sandbox is not to handle X Apps, since these apps want to write all over the home directory ~/.gconf, ~/gnome., ~/.config ... and all over /tmp, along with use privs to talk to the X Server. I have some ideas on this for the future that I hope to experiment with.
So what were my security goals in writing sandbox.
- Has to be able to execute any binary on the system in a domain called sandbox_t.
- Since the goal here is to make a general purpose tool that anyone could use in a script, I did not want to limit the user to a particular app.
- Later we added a sandbox_file_t type that sandbox apps can Manage, files, directories, sock_files, fifo_files
- sandbox_file_t is only currently created if you execute sandbox as root, with the -M flag, this creates a temporary file system mount labeled sandbox_file_t under /mnt
- Sandbox_t needs to be able to read the executables, in order to execute them, we might experiment with using fexece, although there are currently no python bindings.
- sandbox_t domain to use shared libraries, so sandbox_t can read all libraries on the system.
- sandbox_t can use any open file descriptors passed to it by the shell, or any other app that would be able to execute the sandbox domain.
- But it remember it CANNOT OPEN or CREATE any file.
One test I have run with it is
> sandbox id -Z
unconfined_u:unconfined_r:sandbox_t:s0:c87,c905
This command shows that sandbox ran the id command under the sandbox_t domain and chose the MCS label s-:c87,c905
If I wanted to create a file of users on my system from the /etc/passwd file, I could try
> sandbox cut -d: -f1 /etc/passwd > /tmp/users
/bin/cut: /etc/passwd: Permission denied
Read more: Dan Walsh's Blog