Stephen Hansen wrote:
Dotan Barak wrote:
<snip>
... eval("my_number < 10", {"__builtins__":None}, {})
<snip>
Hm, is this true, though? Is there anything subtle or dangerous possible
here? He's using eval-- so no statements, its only an expression. He's
passing in a 'globals' which has __builtins__ set to None, so this
environment has access to -- basically nothing. Then the locals
dictionary is empty as well, though I assume he'll fill it with things
like my_number.
A simple expression is enough to write to files, for example.
Try this expression in Python 3.0:
[x for x in ().__class__.__base__.__subclasses__() if x.__name__ ==
'_FileIO'][0]('hello.txt', 'w').write('Hello, World!')
To explain, "().__class__.__base__.__subclasses__()" gives you a list of
all object-derived classes, i.e., of *all* classes that exist in the
surrounding program. If you can find just one class that allows you to
do something subtle or dangerous, you're done.
See also:
- "Controlling Access to Resources Within The Python Interpreter"
(http://people.cs.ubc.ca/~drifty/papers/python_security.pdf)
- http://evoque.gizmojo.org/usage/restricted/
To write your own restricted expression parser, the standard module
"ast" is quite useful. For example, ast.parse("my_number < 10") gives
you a syntax tree similar to this:
ast.Expr(ast.Compare(ops=[ast.Lt], left=ast.Name(id="my_number"),
comparators=[ast.Num(n=10)]))
From there, you can implement your own logic to traverse the tree,
which gives you very fine-grained control over the kinds of expressions
to allow, where to look up variable names, how to react to errors, etc.
Kind Regards,
M.F.
--
http://mail.python.org/mailman/listinfo/python-list