9

Prologue: I know that many people already tried to sandbox Python code within Python and failed, but I haven't seen the approach to additionally preprocess the scripts as text and reject scripts containing keywords like __base__ that could be used to recover hidden __buuiltins__. I think this approach is new and hasn't been proofed to fail yet - has it?

I plan to write a multiplayer strategy game where players may not normally interact with their units using keyboard/mouse commands, but only through scripts they have to submit to change the units' automatic behaviour. This is based on the idea of http://screeps.com.

I would love to write that in Python 3, but the main problem seems to be the secure execution of untrusted foreign player scripts on the server. I know that I may not trust exec() or eval(), even when passing them empty globals and locals as environment. I also know that simply erasing __builtins__ also does not work because one can still easily restore them using Python's introspection capabilities as described here: http://nedbatchelder.com/blog/201302/finding_python_3_builtins.html

I already learned that PyPy or Jython might have some kind of sandboxing feature that would probably work for my purpose, but I would somehow prefer to stay with the CPython reference interpreter. Also, I could only find examples where those sandboxing features work for entire programs, but none that consists of a main program running untrusted scripts as child threads and communicating with them efficiently.


But I think I have one more chance: I can preprocess the submitted scripts literally and search for strings like __class__ or __base__ and reject scripts containing those keywords. I would also have to replace eval() and exec() in the script with my own, secured functions that also reject to run code containing those keywords.

Would this approach, together with overwriting all potentially dangerous items (which ones would that be?) using a custom globals argument for exec() be secure? Which keywords would I have to look for?

If not, why would that fail? Can you suggest a better solution?

Byte Commander
  • 6,506
  • 6
  • 44
  • 71
  • You should read this other SO question [How can I sandbox Python in pure Python?](http://stackoverflow.com/q/3068139) (this seems to be a duplicate, but the other is now rather old...), and maybe [Python sandbox](https://pypi.python.org/pypi/pysandbox/) but it seems to support only 2.x – Serge Ballesta Mar 01 '16 at 09:03
  • @SergeBallesta Thanks, the question is good, but its answers are not really what I want yet. Those mentioning `exec` are too less secure and those mentioning other interpreters do also not really fit what I want. Same for PyPy. – Byte Commander Mar 01 '16 at 09:18

1 Answers1

1

I'm not sure that this is a good idea. There are possibilities using pypy, or even a dedicate project python sandbox that has already dealt with much of system isolation. But the former needs a good deal of work to build a secure environment, and the latter does not directly support Python 3.x

But the author of pysandbox has stopped development since 2013, because he declared in its github site

pysandbox is BROKEN BY DESIGN, please move to a new sandboxing solution (run python in a sandbox, not the opposite!) https://lwn.net/Articles/574215/*

If you can accept a limited syntax, it would certainly much much more secure to define a dedicated grammar and build a custom interpretor with PythonLexYacc.

I must admit this is more hints than a full answer, but it is the best I can do now (and python sandbox was not referenced of that former SO question

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • pysandbox is strongly discouraged by the author has he found vulnerabilities: https://lwn.net/Articles/574215/ – Byte Commander Mar 01 '16 at 09:24
  • @ByteCommander: thanks for the reference. I'll try to update my answer with it for future reference, but it confirm my first opinion that building a secure Python interpretor is a wrong solution to a real question :-( – Serge Ballesta Mar 01 '16 at 09:37
  • But if I get it right, they only do their isolation by using Python methods to limit the scripts. My approach would be to also preprocess the raw script as text and simply reject all scripts that contain special keywords like `__base__` which is often used to break out and recreate the `__builtins__`. That's a different approach, isn't it? At least I couldn't find anything about that on the web yet. – Byte Commander Mar 01 '16 at 09:39
  • @ByteCommander: my reading is is you reject every construct that may break the secrure sandbox you end with an interpretor that cannot be used *[f]or something more complex than evaluating "1+(2\*3)"* – Serge Ballesta Mar 01 '16 at 09:50
  • Unfortunately the aim of my game is to allow people to fully control their units using regular Python... So neither PLY nor being too restrictive is a good option... :( – Byte Commander Mar 01 '16 at 10:57