Untrusted code execution

Steven D'Aprano steve at pearwood.info
Tue Apr 5 21:43:50 EDT 2016


On Wed, 6 Apr 2016 03:48 am, Chris Angelico wrote:

> On Wed, Apr 6, 2016 at 3:26 AM, Jon Ribbens
> <jon+usenet at unequivocal.co.uk> wrote:
>> The received wisdom is that restricted code execution in Python is
>> an insolubly hard problem, but it looks a bit like my 7-line example
>> above disproves this theory, 

Jon's 7-line example doesn't come even close to providing restricted code
execution in Python. What it provides is a restricted subset of expression
evaluation, which is *much* easier. It's barely more powerful than the
ast.safe_eval function. That doesn't make it useless, but it does mean that
it's not solving the problem of "restricted code execution".


[Jon again]
>> provided you choose carefully what you 
>> provide in your restricted __builtins__ - but people who knows more
>> than me about Python seem to have thought about this problem for
>> longer than I have and come up with the opposite conclusion so I'm
>> curious what I'm missing.

You're missing that they're trying to allow enough Python functionality to
run useful scripts (not just evaluate a few arithmetic expressions), but
without allowing the script to break out of the restricted environment and
do things which aren't permitted.

For example, check out Tav's admirable work some years ago on trying to
allow Python code to read but not write files:

http://tav.espians.com/a-challenge-to-break-python-security.html

and followups to that post here:

http://tav.espians.com/paving-the-way-to-securing-the-python-interpreter.html
http://tav.espians.com/update-on-securing-the-python-interpreter.html


You should also read Guido's comments on capabilities:

http://neopythonic.blogspot.com.au/2009/03/capabilities-for-python.html

As Zooko says, Guido's "best argument is that reducing usability (in terms
of forbidding language features, especially module import) and reducing the
usefulness of extant library code" would make the resulting interpreter too
feeble to be useful.

Look at what you've done: you've restricted the entire world of Python down
to, effectively, a calculator and a few string methods. That's not to say
that a calculator and a few string methods won't be useful to someone, but
the next Javascript it is not...


[Chris]
> No, it doesn't disprove anything. All you've shown is "here's a piece
> of code that hasn't yet been compromised". :) What you're missing is a
> demonstrated exploit against your code. I can't provide one, but it's
> entirely possible that one will be found.
> 
> Your code is a *lot* safer for using 'eval' rather than 'exec'.
> Otherwise, you'd be easily exploited using exceptions, which carry a
> ton of info. But even so, I would not bet money (much less the
> security of my systems) on this being safe.

I think Jon is on the right approach here for restricting evaluation of
evaluation, which is a nicely constrained and small subset of Python. He's
not allowing unrestricted arbitrary code execution: he has a very
restricted (too restricted -- what the hell can you do with just int, str
and len?) whitelist of functions that are allowed, and the significant
restriction that dunder names aren't allowed.

This makes his function a tiny DSL for calculators and equivalent. I think
that, if it checks out, it would make a good addition to the standard
library.


All the obvious, and even not-so-obvious, attack tools are gone: eval, exec,
getattr, type, __import__. Because you're not supporting Python 2, the
various func.func_* attack surfaces are all gone. Since you can't access
dunders directly, and the obvious indirect methods like eval and getattr
aren't available, I don't think that any of the usual attacks will work.

Keep in mind that Jon's burden is easier: he doesn't need to worry about the
caller's environment, only his own environment. So long as the attacker
can't inject code into his "safe eval" code, the attacker can monkey-patch
their own built-ins and it simply doesn't matter.

(If the attacker can monkey-patch Jon's code, they can do anything they
like.)


I think this approach is promising enough that Jon should take it to a few
other places for comments, to try to get more eyeballs. Stackoverflow and
Reddit's /r/python, perhaps. 

Please do followup here with any results, positive or negative.




-- 
Steven




More information about the Python-list mailing list