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()
'a'


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.




-- 
Steven



More information about the Python-list mailing list