как обеспечить безопасное выполнение eval (и, возможно, exe c) - PullRequest
0 голосов
/ 29 мая 2020

ВНИМАНИЕ: НЕ ЗАПУСКАЙТЕ КОД НИЖЕ НА РАБОЧИХ МАШИНАХ, ЭТО МОЖЕТ ПРИВЕСТИ К НЕОБРАТИМЫМ ПОСЛЕДСТВИЯМ (ЕСЛИ ВЫ ХОТИТЕ ПОПРОБОВАТЬ ЭТО, ИСПОЛЬЗУЙТЕ ВИРТУАЛЬНЫЕ МАШИНЫ)

Я знаю, что eval и exe c довольно опасны вещи, но можно ли полностью защититься от возможных проблем? (в случае с exe c - вряд ли там все слишком проблематично c, но есть надежда на безопасное выполнение eval),

вот что у меня: eval (s, {'__builtins __': {}})

но я знаю, что, например, это можно обойти несколькими способами, например:

s = """
(lambda fc=(
    lambda n: [
        c for c in 
            ().__class__.__bases__[0].__subclasses__() 
            if c.__name__ == n
        ][0]
    ):
    fc("function")(
        fc("code")(
            0,0,0,0,"KABOOM",(),(),(),"","",0,""
        ),{}
    )()
)()
"""

для краткости я опущу подробности происходящего

В приведенном выше примере мы использовали список всех подклассов класса объекта для создания объектов кода и классов функций. Точно так же вы можете получить (и создать экземпляр) любой класс, который существует в программе на момент вызова eval (). Вот еще один пример того, что можно сделать:

s = """
[
    c for c in 
    ().__class__.__bases__[0].__subclasses__() 
    if c.__name__ == "Quitter"
][0](0)()
"""

Когда я исследовал этот топи c, я наткнулся на защищенный режим выполнения eval в Python, что является еще одной попыткой преодолеть это проблема:

>>> eval("(lambda:0).func_code", {'__builtins__':{}})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
RuntimeError: function attributes not accessible in restricted mode

Короче говоря, это работает следующим образом: если __builtins__ внутри eval отличаются от «официальных», eval переходит в защищенный режим, который запрещает доступ к некоторым опасным свойствам, таким как func_code для функций.

в принципе, вы можете обойти ограничение, используя этот код (здесь мы получаем «официальный» __builtins__):

s = """[
    c for c in ().__class__.__base__.__subclasses__() 
    if c.__name__ == 'catch_warnings'
][0]()._module.__builtins__
"""

мой вопрос: это можно ли до конца избежать проблем с eval?

...