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

StackOverflow https://stackoverflow.com/questions/661084

  •  20-08-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

Есть очень хороший статья о безопасности оон в eval() в книге Марка Пилигрима Погружение в Python Учебник.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top