On Feb 22, 2009, at 5:15 PM, Martin v. Löwis wrote:
What is the objective of this code? Is it a complete sandbox?
If not, is a complete sandbox based on it available somehow for
review?

From a cursory look at Tav's CPython patch, I'd describe it as follows:

    Requires: an existing Python code execution environment
              which does not expose unsafe interpreter
              functionality to the (untrusted) code it runs,

    Provides: a way for the trusted code outside of that
              restricted environment to wrap functions
              (which may reference trusted objects) in
              closures which can be passed into the restricted
              environment as completely opaque objects
              whose internal state (including any referenced
              trusted objects) cannot be accessed from the
              untrusted code.

When I say 'requires', I mean 'requires to be useful'; the patch can be applied to vanilla CPython, but isn't useful on its own.

Building blocks for a restricted execution environment as required by the patch are commonly provided in templating libraries; Tav mentions Genshi in particular. By default, Genshi templates don't come with security built in -- you can do what you please in a template. However, since Genshi manually constructs a Python AST from Python code in the template, one can restrict the AST and modify the builtins exposed to the template environment, making things like filesystem access, import and other sensitive system facilities unavailable.

Even with those unavailable, untrusted code can break out of containment by accessing object.__subclasses__ or gaining access to gi_frame and gi_code. This means you can't, for instance, pass into the untrusted code a closure which operates on trusted objects. Tav's patch addresses this particular problem.

To give you a complete sandbox to play with, I just violently ripped out the relevant code from Genshi, added some glue, and slapped it all together in a single file along with Tav's pure-Python code which is functionally equivalent to the CPython patch he submitted. The result, tested on 2.5.1 and nothing else:

    <http://radian.org/~krstic/sandbox.py>

As is, sandbox allows you to execute untrusted Python code which won't have access to import, __import__, eval, exec, execfile, open, and to which you can pass closures which reference trusted objects which the untrusted code can't get at.

Example:

>>> import sandbox
>>> import sys
>>> import md5
>>> def trusted_pwd_closure(password):
...    def get_pwd():
...        return md5.md5(password).hexdigest()
...    return get_pwd
...
>>> context = dict(pwd=trusted_pwd_closure('secret'))
>>> sandbox.run_string("print pwd()", context)
>>> sandbox.run_string("print pwd.func_closure[0].cell_contents", context)
[snip]
AttributeError: 'function' object has no attribute 'func_closure'

Without Tav's patch, the untrusted code can extract our password ('secret') from the closure with that last statement.

To run whole files in the sandbox:
>>> sandbox.run_file('/some/path/file.py')

Finally, disclaimer: I put this together in *15 minutes*. I'm sure I missed something, this isn't secure, etc. It's just a proof of concept. Void where prohibited, etc.

Cheers,

--
Ivan Krstić <krs...@solarsail.hcs.harvard.edu> | http://radian.org

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to