Is it possible to get the erroneous variable when getting a NameError exception?
Michael Fötsch
foetsch at yahoo.com
Sat Dec 26 07:34:18 EST 2009
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.
More information about the Python-list
mailing list