Sandboxing Python

Chris Angelico rosuav at gmail.com
Sat Aug 22 20:04:50 EDT 2015


On Sun, Aug 23, 2015 at 9:52 AM, Mark Lawrence <breamoreboy at yahoo.co.uk> wrote:
> On 23/08/2015 00:44, Chris Angelico wrote:
>>
>> On Sun, Aug 23, 2015 at 9:25 AM, Mark Lawrence <breamoreboy at yahoo.co.uk>
>> wrote:
>>>
>>> I was always led to believe that the subject was a difficult thing to do,
>>> but here
>>>
>>> https://www.reddit.com/r/learnpython/comments/3huz4x/how_to_do_math_inside_raw_input/
>>> is a safe solution in only 23 characters, or are there any discernable
>>> flaws
>>> in it?
>>
>>
>>
>> I'm sorry, I can't see which solution you're talking about there -
>> maybe I just don't know how to read reddit properly. Can you paste the
>> proposed code please?
>>
>> The best I can see there is "use eval but with no builtins". That's
>> fundamentally flawed because you don't need builtins to break stuff.
>> All you need is a literal, from which you can snag everything else via
>> its attributes.
>>
>> However, for this situation, I would be recommending ast.literal_eval,
>> which *is* safe. It's a lot more powerful than "split it into number,
>> operator, number" as mentioned at the end, but still can't majorly
>> break anything.
>>
>> ChrisA
>>
>
> <code>
>>>> import os
>>>> eval("os.system('rm -rf /')", {"__builtins__":None})
> Traceback (most recent call last):
>   File "<pyshell#8>", line 1, in <module>
>     eval("os.system('rm -rf /')", {"__builtins__":None})
>   File "<string>", line 1, in <module>
> TypeError: 'NoneType' object is not subscriptable
> </code>
>
> <comment>
> Surely I must I have missed your meaning because I needed just 23 characters
> and zero extra lines to create a safe sandbox for this, but you've said that
> the core developers have tried and failed to do this. It appears that I
> didn't just wipe out my entire filesystem and you've stated quite
> matter-of-factly that there is no safe solution... so what happened here?
> Why didn't my filesystem just get wiped out?
> </comment>

Got it, thanks. The answer is: It's easy to make something you can't
yourself break out of. It just means you don't know all the tricks.

http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html

>>> cmd="""[c for c in ().__class__.__base__.__subclasses__() if c.__name__ == 'catch_warnings'][0]()._module.__builtins__["__import__"]("os").system("echo Hello")"""
>>> eval(cmd,{"__builtins__":None})
Hello
0

Et voila. Arbitrary module loading, arbitrary code execution, have fun.

ChrisA



More information about the Python-list mailing list