Executing untrusted code

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Aug 20 20:38:09 CEST 2009

On Thu, 20 Aug 2009 08:16:51 -0700, Emanuele D'Arrigo wrote:

> Fair enough. In this context, let's say I do this:
> import __builtin__
> import imp
> originalBuiltins = imp.new_module("OriginalBuiltins")
> def readOnlyOpen(filename):
>     return originalBuiltins.open(filename, "r")
> __builtin__.open = readOnlyOpen

Have you actually tested this? I don't think it works the way you think 
it does.

>>> import __builtin__
>>> import imp
>>> originalBuiltins = imp.new_module("OriginalBuiltins")
>>> originalBuiltins.open
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'open'

So your strategy fails to provide read-only file access.

But moving on...

> In what ways would the untrusted string be able to obtain the original,
> built-in open function and open a file for writing?

That's hardly even a challenge.

>>> __builtin__.open = readOnlyOpen
>>> anUntrustedString = """import __builtin__
... reload(__builtin__)
... open('junk', 'w').write('a')
... """
>>> exec(anUntrustedString, {})
>>> open('junk').read()

Not only have I broken your "read only" open within the call to exec, but 
I've broken it outside as well. With a little bit more effort, I could 
probably save and restore the open, so that my untrusted string could 
write to files inside the exec(), but code outside of the exec() would 
still see the readOnlyOpen.


More information about the Python-list mailing list