Безопасность eval () Python для ненадежных строк? - PullRequest
22 голосов
/ 19 марта 2009

Если я оцениваю строку 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) без пользовательских словарей в большинстве случаев небезопасно.

Ответы [ 6 ]

45 голосов
/ 19 марта 2009

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

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

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

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

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

15 голосов
/ 10 июня 2012

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

10 голосов
/ 20 марта 2009

Вы можете добраться до os, используя встроенные функции: __import__('os').

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

6 голосов
/ 19 марта 2009

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

4 голосов
/ 19 марта 2009

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

  1. Какие выражения вы хотите вычислить?
  2. Можете ли вы убедиться, что только строки, соответствующие некоторому узко определенному синтаксису, являются eval () d?
  3. Тогда подумайте, если , что безопасно.

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

2 голосов
/ 03 января 2010

Существует очень хорошая статья о небезопасности eval() в учебнике Марка Пилигрима Dive into Python .

Цитируется из этой статьи:

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

...