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

Reply via email to