0

I am trying to build a web application (running on Linux servers) in which the user will upload an executable, the executable will be ran against a particular input available on the server (fed via STDIN), and the output (read from STDOUT) will be returned to the user.

Of course, I do not want the user to be able to do anything malicious on my server. I would like to run the executable in a sandbox, or otherwise prevent the executable from executing sensitive system calls.

I have no idea where to start from. I checked out User-Mode Linux, but it seems to have too much overhead (many executables will be running in parallel, and having a VM for each one is way too much overhead).

How should I proceed?

Edit: I understand this is something one normally avoids. I understand there are risks. Consider this as something you would do for the sake of learning how it can be done. I have seen it done before on places like CodePad and geordi, sometimes it is a very convenient thing to do.

Sinan Taifour
  • 110
  • 1
  • 6
  • Not much of a learning experience if someone else just tells you how to do it... – womble Nov 27 '09 at 21:50
  • Oh, and have you even bothered to read the about page on codepad.org? – womble Nov 27 '09 at 21:51
  • 1
    Yes. I spent the last 3 hours trying to figure out how he used geordi to do what he has done, with no luck whatsoever. I thus turned to ServerFault. – Sinan Taifour Nov 27 '09 at 21:54
  • 1
    I am not asking for someone to "tell me how to do it", I just asked "how to proceed". I am stuck. I just need a direction to start with. – Sinan Taifour Nov 27 '09 at 21:57
  • E-mail the person behind codepad.org and ask them. – womble Nov 27 '09 at 22:09
  • I already did email that person, even before coming to ServerFault. I feel the question is on the line between sysadmin and prorgramming; you might find a tool that enforces a jail around the executable (sysadmin) or might need to code something yourself (programming). – Sinan Taifour Nov 28 '09 at 08:11
  • I must say, we do find an awful lot of tools here at serverfault. – womble Nov 28 '09 at 18:24

5 Answers5

4

You're taking a massive, massive risk running untrusted code. I would completely rethink both what I wanted to do and the fundamental assumptions of my project if the answer to my problem I came up with was "run untrusted code from arbitrary users on my server".

womble
  • 96,255
  • 29
  • 175
  • 230
  • Others have done it, and it works. Checkout www.codepad.org :) – Sinan Taifour Nov 27 '09 at 21:31
  • Done it, yes. Works... not so much. I'm pretty sure I've got enough info out of that service to confirm a hole, but I'm not one to go crashing machines at a whim -- and I'm not even particularly good at breaking into things. – womble Nov 27 '09 at 21:55
  • I am interested to see what you found. Could you please link to the pastie you ran? – Sinan Taifour Nov 27 '09 at 22:00
4

You can give a try to librestrict.

It is a small library designed to be LD_PRELOAD-ed before starting a given executable, basically works by chroot()ing into a given directory, then removing all capabilities (except ones based on a whitelist) then setuid()-ing to a given user, preventing the given executable from doing nasty things.

One of the beauties of this program is that it chroot()s after the system has loaded all the necessary libraries, therefore if you are lucky (it does not want to dl() some other libs) you can use it with an empty directory, as a chroot() environment.

Though, it's a bit old and undocumented, you can give it a try, I can give you a hand.

asdmin
  • 2,050
  • 17
  • 28
  • This is unsafe. Don't do it. LD_PRELOAD is a request, not a demand... an arbitrary user-supplied executable can easily inline system calls (int 0x80 or similar) and LD_PRELOAD will be none the wiser. –  Nov 30 '09 at 06:04
  • what kind of system calls are you afraid of? – asdmin Nov 30 '09 at 18:07
2

I think running executables in a VM is your best bet. For example, there's a bot on the #bash IRC channel that allows for the execution of arbitrary shell code...by running it inside a qemu based VM and then capturing the stdout of that process. UML is probably a reasonably good solution.

The new lguest stuff (http://lguest.ozlabs.org/) is probably better; this is "container" mechanism, rather than a full-on "virtualization" solution; something like Solaris Zones. I don't know what the state of this project is right now.

larsks
  • 43,623
  • 14
  • 121
  • 180
1

Does it have to be an executable file? Could you restrict uploaded programs to be for example source code in some scripting language (python, ruby) which have some kind of sandbox executing environment. Or bytecode for something like C# or Java? At least C# and Java have built in security mechanism for allowing and disallowing operations.

You could then more easily restrict what the uploaded programs can do and cannot do.

Juha Syrjälä
  • 1,081
  • 10
  • 19
  • Well yes, it can be a scripting language. I actually started off by allowing just Ruby and sandboxing it, but I was wondering how this could be generalized, thus giving more options to my users. – Sinan Taifour Nov 28 '09 at 13:41
0

I tried something similar, and have chosen grsecurity-enabled kernel plus read-only bind mounts for sharing system files between host and sandbox. Then the testing app was started in chroot-ed sandbox. When done, all processes belonging to sandbox user are killed with SIGKILL and any user-modifiable files erased and replaced from original. While it may not be so completely safe as virtual machine it comes very close when done right. The advantage is much less overhead.

Juraj
  • 257
  • 3
  • 9