Ответ 1
Вы не можете обеспечить eval с таким подходом черного списка. См. Eval действительно опасен для примеров ввода, которые будут segfault интерпретатора CPython, предоставить доступ к любому классу, который вам нравится, и так далее.
Если я оцениваю строку 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?Есть некоторые небезопасные строки типа "[0] * 100000000" Меня не волнует, потому что в худшем случае они замедляют/останавливают программу. Я в первую очередь обеспокоен защитой пользовательских данных, внешних по отношению к программе.
Очевидно, что eval(string)
без пользовательских словарей в большинстве случаев небезопасно.
Вы не можете обеспечить eval с таким подходом черного списка. См. Eval действительно опасен для примеров ввода, которые будут segfault интерпретатора CPython, предоставить доступ к любому классу, который вам нравится, и так далее.
eval()
позволит вредоносным данным скомпрометировать всю вашу систему, убить вашу кошку, съесть свою собаку и заняться любовью с вашей женой.
Недавно был рассказ о том, как безопасно сделать это в списке python-dev, и были сделаны следующие выводы:
Начните здесь, чтобы прочитать о проблеме: http://tav.espians.com/a-challenge-to-break-python-security.html
В какой ситуации вы хотите использовать eval()? Вы хотите, чтобы пользователь мог выполнять произвольные выражения? Или вы хотите каким-то образом передать данные? Возможно, возможно каким-то образом заблокировать вход.
Вы можете перейти к os
с помощью встроенных функций: __import__('os')
.
Для python 2.6+ может помочь ast module; в частности ast.literal_eval
, хотя это зависит от того, что вы хотите оценить.
Обратите внимание, что даже если вы передаете пустые словари на eval(), все еще возможно segfault (C) Python с некоторыми трюками синтаксиса. Например, попробуйте это на вашем интерпретаторе: eval("()"*8**5)
Вероятно, вам лучше решить вопрос:
Например, если вы хотите, чтобы пользователь вводил алгебраическое выражение для оценки, подумайте о том, чтобы ограничить их именами, числами и конкретным набором операторов и функций. Не используйте строки eval(), содержащие что-либо еще.
Существует очень хорошая статья статьи о небезопасности eval()
в Mark Pilgrim Dive in Python.
Цитата из этой статьи:
В конце концов, можно безопасно оценивать ненадежные выражения Python, для некоторого определения "безопасного", что оказывается, не очень полезно в реальная жизнь. Хорошо, если вы просто играя вокруг, и его штраф, если вы только когда-либо передавайте ему доверенный ввод. Но все остальное просто просит беда.