Безопасность eval() в Python для ненадежных строк?
Если я оцениваю строку Python с помощью eval () и у меня есть класс типа:
classFoo(object): a = 3 defbar(self, x): return x + a
Каковы риски безопасности, если я не доверяю строке? В частности:
eval(string, {"f": Foo()}, {}) Небезопасно? То есть, вы можете получить доступ к os или sys или чему-то небезопасному из экземпляра Foo?
eval(string, {}, {}) Небезопасно? То есть могу ли я получить доступ к os или sys полностью из встроенных функций, таких как len и list?
Есть ли способ сделать так, чтобы встроенные функции вообще не присутствовали в контексте eval?
Есть некоторые небезопасные строки, такие как "[0] * 100000000", которые меня не волнуют, потому что в худшем случае они замедляют / останавливают программу. В первую очередь меня беспокоит защита пользовательских данных, внешних по отношению к программе.
Очевидно, eval(string) что без пользовательских словарей в большинстве случаев небезопасно.
Переведено автоматически
Ответ 1
eval() позволит вредоносным данным скомпрометировать всю вашу систему, убить вашу кошку, съесть вашу собаку и заняться любовью с вашей женой.
Недавно была тема о том, как безопасно выполнять подобные действия в списке python-dev , и выводы были следующими:
Это действительно сложно сделать правильно.
Требуются исправления для интерпретатора python, чтобы блокировать многие классы атак.
Не делайте этого, если вы действительно не хотите.
В какой ситуации вы хотите использовать eval ()? Вы хотите, чтобы пользователь мог выполнять произвольные выражения? Или вы хотите каким-либо образом передавать данные? Возможно, можно каким-то образом заблокировать входные данные.
Ответ 2
Вы не можете обезопасить eval с помощью такого подхода с занесением в черный список. Смотрите, Eval действительно опасен, чтобы найти примеры ввода, которые будут выполнять сегментацию интерпретатора CPython, предоставлять доступ к любому классу, который вам нравится, и так далее.
Ответ 3
Вы можете добраться до os с помощью встроенных функций: __import__('os').
Для python 2.6+ может помочь модуль ast; в частности ast.literal_eval, хотя это зависит от того, что именно вы хотите вычислить.
Ответ 4
Note that even if you pass empty dictionaries to eval(), it's still possible to segfault (C)Python with some syntax tricks. For example, try this on your interpreter: eval("()"*8**5)