Вопрос-Ответ

Security of Python's eval() on untrusted strings?

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

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

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

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


  1. eval(string, {"f": Foo()}, {}) Небезопасно? То есть, вы можете получить доступ к os или sys или чему-то небезопасному из экземпляра Foo?

  2. eval(string, {}, {}) Небезопасно? То есть могу ли я получить доступ к os или sys полностью из встроенных функций, таких как len и list?

  3. Есть ли способ сделать так, чтобы встроенные функции вообще не присутствовали в контексте eval?

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

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

Переведено автоматически
Ответ 1

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

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


  • Это действительно сложно сделать правильно.

  • Требуются исправления для интерпретатора python, чтобы блокировать многие классы атак.

  • Не делайте этого, если вы действительно не хотите.

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

В какой ситуации вы хотите использовать 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)

python