Security of Python's eval() on untrusted strings?

user79758 picture user79758 · Mar 19, 2009 · Viewed 14.9k times · Source

If I am evaluating a Python string using eval(), and have a class like:

class Foo(object):
    a = 3
    def bar(self, x): return x + a

What are the security risks if I do not trust the string? In particular:

  1. Is eval(string, {"f": Foo()}, {}) unsafe? That is, can you reach os or sys or something unsafe from a Foo instance?
  2. Is eval(string, {}, {}) unsafe? That is, can I reach os or sys entirely from builtins like len and list?
  3. Is there a way to make builtins not present at all in the eval context?

There are some unsafe strings like "[0] * 100000000" I don't care about, because at worst they slow/stop the program. I am primarily concerned about protecting user data external to the program.

Obviously, eval(string) without custom dictionaries is unsafe in most cases.

Answer

Jerub picture Jerub · Mar 19, 2009

eval() will allow malicious data to compromise your entire system, kill your cat, eat your dog and make love to your wife.

There was recently a thread about how to do this kind of thing safely on the python-dev list, and the conclusions were:

  • It's really hard to do this properly.
  • It requires patches to the python interpreter to block many classes of attacks.
  • Don't do it unless you really want to.

Start here to read about the challenge: http://tav.espians.com/a-challenge-to-break-python-security.html

What situation do you want to use eval() in? Are you wanting a user to be able to execute arbitrary expressions? Or are you wanting to transfer data in some way? Perhaps it's possible to lock down the input in some way.