Python eval: is it still dangerous if I disable builtins and attribute access?

后端 未结 6 957
甜味超标
甜味超标 2020-12-02 12:38

We all know that eval is dangerous, even if you hide dangerous functions, because you can use Python\'s introspection features to dig down into things and re-extract them. F

6条回答
  •  一生所求
    2020-12-02 13:07

    Controlling the locals and globals dictionaries is extremely important. Otherwise, someone could just pass in eval or exec, and call it recursively

    safe_eval('''e("""[c for c in ().__class__.__base__.__subclasses__() 
        if c.__name__ == \'catch_warnings\'][0]()._module.__builtins__""")''', 
        globals={'e': eval})
    

    The expression in the recursive eval is just a string.

    You also need to set the eval and exec names in the global namespace to something that isn't the real eval or exec. The global namespace is important. If you use a local namespace, anything that creates a separate namespace, such as comprehensions and lambdas, will work around it

    safe_eval('''[eval("""[c for c in ().__class__.__base__.__subclasses__()
        if c.__name__ == \'catch_warnings\'][0]()._module.__builtins__""") for i in [1]][0]''', locals={'eval': None})
    
    safe_eval('''(lambda: eval("""[c for c in ().__class__.__base__.__subclasses__()
        if c.__name__ == \'catch_warnings\'][0]()._module.__builtins__"""))()''',
        locals={'eval': None})
    

    Again, here, safe_eval only sees a string and a function call, not attribute accesses.

    You also need to clear out the safe_eval function itself, if it has a flag to disable safe parsing. Otherwise you could simply do

    safe_eval('safe_eval("", safe=False)')
    

提交回复
热议问题