Подтвердить что ты не робот

Безопасность Python eval() на ненадежных строках?

Если я оцениваю строку Python с помощью eval() и имею класс вроде:

class Foo(object):
    a = 3
    def bar(self, x): return x + a

Каковы риски безопасности, если я не доверяю строке? В частности:

  • Является ли eval(string, {"f": Foo()}, {}) небезопасным? То есть, вы можете достичь os или sys или что-то небезопасное из экземпляра Foo?
  • Является ли eval(string, {}, {}) небезопасным? То есть, могу ли я получить os или sys целиком из встроенных функций, таких как len и list?
  • Есть ли способ заставить встроенные компоненты вообще не присутствовать в контексте eval?

Есть некоторые небезопасные строки типа "[0] * 100000000" Меня не волнует, потому что в худшем случае они замедляют/останавливают программу. Я в первую очередь обеспокоен защитой пользовательских данных, внешних по отношению к программе.

Очевидно, что eval(string) без пользовательских словарей в большинстве случаев небезопасно.

4b9b3361

Ответ 1

Вы не можете обеспечить eval с таким подходом черного списка. См. Eval действительно опасен для примеров ввода, которые будут segfault интерпретатора CPython, предоставить доступ к любому классу, который вам нравится, и так далее.

Ответ 2

eval() позволит вредоносным данным скомпрометировать всю вашу систему, убить вашу кошку, съесть свою собаку и заняться любовью с вашей женой.

Недавно был рассказ о том, как безопасно сделать это в списке python-dev, и были сделаны следующие выводы:

  • Это действительно сложно сделать правильно.
  • Он требует исправлений для интерпретатора python для блокировки многих классов атак.
  • Не делай этого, если не хочешь.

Начните здесь, чтобы прочитать о проблеме: http://tav.espians.com/a-challenge-to-break-python-security.html

В какой ситуации вы хотите использовать eval()? Вы хотите, чтобы пользователь мог выполнять произвольные выражения? Или вы хотите каким-то образом передать данные? Возможно, возможно каким-то образом заблокировать вход.

Ответ 3

Вы можете перейти к os с помощью встроенных функций: __import__('os').

Для python 2.6+ может помочь ast module; в частности ast.literal_eval, хотя это зависит от того, что вы хотите оценить.

Ответ 4

Обратите внимание, что даже если вы передаете пустые словари на eval(), все еще возможно segfault (C) Python с некоторыми трюками синтаксиса. Например, попробуйте это на вашем интерпретаторе: eval("()"*8**5)

Ответ 5

Вероятно, вам лучше решить вопрос:

  • Какие выражения вы хотите оценить?
  • Можете ли вы убедиться, что только строки, соответствующие узко определенному синтаксису, являются eval() d?
  • Затем подумайте, безопасно ли это.

Например, если вы хотите, чтобы пользователь вводил алгебраическое выражение для оценки, подумайте о том, чтобы ограничить их именами, числами и конкретным набором операторов и функций. Не используйте строки eval(), содержащие что-либо еще.

Ответ 6

Существует очень хорошая статья статьи о небезопасности eval() в Mark Pilgrim Dive in Python.

Цитата из этой статьи:

В конце концов, можно безопасно оценивать ненадежные выражения Python, для некоторого определения "безопасного", что оказывается, не очень полезно в реальная жизнь. Хорошо, если вы просто играя вокруг, и его штраф, если вы только когда-либо передавайте ему доверенный ввод. Но все остальное просто просит беда.