Introducing the SELinux Sandbox

May 26, 2009 09:35

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.  
  • 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.
  • Can not "Open or Create any files on the system". 
    • 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
  • Can not use the network. 
  • Should only be able to read a small amount of the system
    • 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.
    • 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

Which shows the sandbox domain is not allowed to open /etc/passwd

But I can execute
> cat /etc/passwd | sandbox cut -d: -f1 > /tmp/users

But if I wanted to use sandbox to read random locations on the system,
> sandbox ls -lZ /tmp
/bin/ls: cannot open directory /tmp: Permission denied
[Exit 2]

I think this is a very powerful concept and could be used to confine random scripts that handle untrusted data, without the admin needing to write much policy.  You can play around with the tool and see what you think, although it will generate lots of AVC messages.

Creating the Sandbox policy.

I ran system-config-selinux, I selected Policy Modules and clicked on New.  When I got to the "Select type of the application/user role to be confined, I selected user application.  Sandbox can be run by administrators or normal users so this made sense.




I called the policy sandbox, I lied about an executable /sbin/sandbox and then



Finally I told the tool to transition from unconfined_u user role




I just clicked to the end and installed the policy using the generated sandbox.sh

I could then use the runcon command to run a random binary as sandbox_t.

Now I went in an started editing the policy, I removed the "permissive sandbox_t" line which the gui tool adds automatically.  I also remove files_read_etc_files.    To make it more tightly locked down,

I added

files_rw_all_inherited_files(sandbox_t)

to allow sandbox_t to use any file on the file system that is handed to the process.

I also added sandbox_file_t type and allows sandbox_t to manage this type.

Say you wanted to create a sandbox domain that can just connect to port 25, you could go through the same steps and when you get to the network connection section you can add the ability to connect to this port.

Previous post Next post
Up