15

I want to simulate (unsafe) client code on my server, and I am looking for a suitable language to do so. I'd prefer having the clients write in the same language as I will use to simulate.

  • safety is the primary concern
  • preferably a well known language (easy for clients to learn syntax)
  • should be easy to disable/enable language features useable in the sandbox
  • would be a plus if I could actually simulate the code step by step

Ideally I would simply construct a few interfaces (and publish these), load the clients code, and simulate that code by allowing it to only use my interfaces + a subset of the standard API I carefully selected.

During this simulation I should be able to limit resources (time and memory) used by the clients code. Bonus would be if I could simulate the code step by step, that way I could always return a deterministic solution.

Performance is not really an issue. The idea is to allow clients to write a custom AI for a small game/puzzle. The game would be simulated (on the server!) and the result returned to the user.

Originally I was thinking of constructing an external DSL myself, including a parser and evaluator, but perhaps there is a ready-to-use solution out there?

Antiz
  • 1,424
  • 1
  • 13
  • 20

5 Answers5

5

My choice would be to use some scripting language that can be used without automatically providing access to some extensive framework (like .Net or Java) - it is easier to add features than to limit them. Game engine scripting languages like LUA may be an option and usually come with implementations for multiple platforms to use them in.

General considerations:

Whatever language/framework you pick, make sure you can recover from/accept risk of:

  • fatal exceptions (like stack overflow due to recursive functions)
  • unbounded memory allocations/ out of memory exceptions
  • long running tasks

Beware of exposing APIs that allow users to create new threads/tasks/synchronization objects (locks/semaphores) outside of your control or building on platform that provides such API. Allowing such methods may open resources of your server to unlimited consumption or DOS/deadlocks...

Note that long running tasks is a problem with any reasonable language as you can't determine if a program ever ends by looking at it - halting problem. You have to figure out a solution no matter what platform you choose.

.Net/C#:

You can check out Terrarium which does exactly this in .Net - running untrusted code on user's machine in a sandboxed environment.

.Net provides a way to restrict usage of multiple APIs - How to: Run Partially Trusted Code in a Sandbox is a good starting point. Note that as @Andrew points out it is good idea to verify if an assembly provided by a user (either directly or compiled from user's sources) does not use APIs that you don't like (or even the other way around - uses just APIs that you do allow) in addition to basic sandboxing. Partially trusted code running in a separate AppDomain gives you ok protection from not-too-hostile code.

Stack overflows are hard to prevent in general and require a custom host to handle in .Net. Long running tasks can be terminated with Thread.Abort or shutting down the AppDomain with the user's code.

CSJ
  • 3,641
  • 2
  • 19
  • 29
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
1

I would recommend .NET (C#, VB and F#). You can take advantage of the JIT to have a server programmatically compile code, use reflection to analyze it, and have each client run in a separate AppDomain for security and code isolation.

poy
  • 10,063
  • 9
  • 49
  • 74
  • I would like to avoid having to use reflection upon the provided code myself. I was hoping to find a language/environment that simply compiles the code for me, checking whether it meets my constraints and either rejects or accepts this piece of code. Accepted code should be safe for me to run (as many times as I like). – Antiz Jan 28 '13 at 22:58
  • .NET allows you to programmatically compile your code. I believe you can also add security attributes to your abstract class which should allow some control there too. – poy Jan 29 '13 at 14:14
  • AppDomains do look interesting, hoping some other people with experience might drop by to support your point. – Antiz Jan 30 '13 at 12:01
  • +1. I've added more .Net links in my post. Note that "reflection" seem to be used in broader sence - you need IL reader to actually analyze compiled code. – Alexei Levenkov Jan 31 '13 at 06:29
1

Java has the concept of SecurityManager which enables you to fine tune what can or cannot run in your virtual machine.

It also allows you to compile code and load the resulting classes at runtime. You can then run whatever code is in those classes, provided the SecurityManager does not throw a SecurityException because the operation is not permitted.

This post shows a contrived example that compiles, loads and runs some code (provided as text source code) at runtime.

This other post gives directions to run untrusted (and potentially malicious) code.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • +1. Would you mind checking/commenting if issues I mentioned in my answer (SO, OOM, long running code...) are applicable to Java case and how one handles them? – Alexei Levenkov Jan 31 '13 at 06:31
  • SO and OOM can be caught in a catch all block that exits the thread running the alien code and releases resources. Long running code could be a little more problematic if run in another thread within the same JVM (Java does not really provide a mechanism to "kill" a thread) - but if that is a risk, the code could be run in a different process (i.e. another JVM) in which case a simple call to the OS can kill that other process. – assylias Jan 31 '13 at 07:20
1

If you want to run code provided by your end users, and you want it to use a language they likely already know, why not JavaScript?

It's possible to sandbox JavaScript in a WebWorker (a concurrent thread that's isolated from the main JavaScript app and has no access to shared memory or globals such as the Window object and the DOM, and only a single avenue for communication with the main thread).

The only security issue I can think of would be limiting the hardware resources consumed by one, but I haven't looked into that -- it may very well be possible with one of the JavaScript runtimes. You'd also want to find a way to prevent one WebWorker from spawning additional ones. You'd have to add some extra code to make sure someone's WebWorker gets automatically shut down after a certain amount of time.

I haven't tried serverside WebWorkers yet, but from the looks of it NodeJS, Rhino, and PhantomJS all support it. Node and Rhino provide different environments than a typical web browser while PhantomJS is a full browser engine (WebKit) running headless. From the perspective of a WebWorker, they'd probably all look the same.

Richard Connamacher
  • 3,115
  • 19
  • 21
  • Also, if you want additional sandboxing on top of WebWorkers themselves, Rhino runs the whole JavaScript engine inside a sandboxed JVM. – Richard Connamacher Jan 31 '13 at 18:06
  • Indeed. Things like the SecurityManager can be used to add an extra level of isolation around the scripted code. Also the great benefit is also that apart from the scripts themselves most code can be written in a strongly typed language, which is a real plus for bigger projects such as games with custom scripted AI. +1 – Stijn de Witt Feb 01 '13 at 23:47
0

If you really want "well known", ADsafe is a subset of JavaScript that's effectively sandboxed, though it has a few quirks (e.g. avoiding this).

Java has "class loaders" which can restrict the classes that a class has access to (see SecureClassLoader). I'm a bit hazy on the details, but it's essentially what's used to provide Java applet security. I don't know if it can restrict memory usage, but restricting CPU time is not too difficult (don't let it spawn threads and kill the thread running the untrusted code after a timeout).

(I am fondly reminded of Robocode which runs untrusted AI attempting to kill other untrusted AI within the constraints of the game. The main difference is that it was intended to run on end-users' computers, though there were sites doing automated ranking. It was my introduction to Java, though I note that it now supports .NET, probably due to the similarity of the two languages.)

tc.
  • 33,468
  • 5
  • 78
  • 96
  • Robocode indeed looks very similar to what I am trying to do, but quite a bit more advanced already. I doubt I can disable constructs such as 'while', 'foreach' etc in Java trough, correct? ADsafe is interesting but I think its more suited for processing the DOM, not so much for interacting with custom interfaces i defined. But i might be wrong. – Antiz Jan 28 '13 at 23:11