2009-03-19 2 views
22

Если я оценка строки Python с помощью Eval(), и есть класс, как:Безопасность eval() на Python на ненадежных строках?

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

+0

Да, если есть импорт sys sys.dostuff в строке, в которой вы делаете eval, и вы не доверяете строкам, материал может стать настоящим уродливым. – Vasil

+0

eval имеет приятное свойство, которое позволяет только выражения. Поэтому такие вещи, как =, импорт и печать, не допускаются. – 2009-03-19 05:06:58

+6

Попробуйте 'eval ('__ import __ (" sys "). Stdout.write (" Hello Joe ")')' –

ответ

13

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

43

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

Был недавно нить о том, как сделать этот вид вещи благополучно в списке питон-Дев, и выводы были:

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

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

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

+2

+1: Кто вредоносный пользователь вставляет вредоносный код, который вы eval() - ing? Найти этого человека - серьезно. Большая часть «eval is insecure» гипотетически размахивает руками о каком-то злобном человеке, которого никто не может действительно идентифицировать. –

+7

@S. Lott - Не является ли одной из движущих идей безопасности, чтобы предотвратить * плохие вещи, а не потом, надеясь, что вы сможете идентифицировать злоумышленника и убедить их не делать это снова? Зачем препятствовать хорошей практике? –

+2

Любая ситуация, когда человек в большом Интернете, чтобы писать ненадежный код для запуска в ваших системах, требует, чтобы ненадежные люди не могли атаковать. «Кто этот человек» - если вы написали что-то небезопасное с eval(), и я знал? Я должен показать вам, что вы не должны этого делать. – Jerub

4

Вы, вероятно, лучше поворачивать вопрос вокруг:

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

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

+0

Или, рассмотрите это: найдите человека, который держит вредоносный код в ваших выражениях eval. Просветите этого человека о последствиях их антисоциального поведения. Шутки в сторону. Кто помещает код в выражения eval? –

+3

@ S.Lott. Если он пишет криптографические программы, то это либо Кэрол, либо Ева, и для обработки электронной почты его [email protected], но я не знаю, узнали ли мы, кто это в общем случае. – MarkusQ

+0

Я пошел бы на один шаг вперед и спрошу, почему вы хотите это сделать вообще. –

6

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

+0

Можете ли вы опубликовать пример этих трюков? – phihag

+0

Эй, почему это вызвало segfault? – jacob

+1

Он переполняет стек компилятора. –

9

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

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

2

В учебном пособии Марка Пилгрима Dive into Python есть очень хорошее article on the un-safety of eval().

Цитируется по статье:

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

+1

Ссылка больше не действительна. – GingerPlusPlus

+0

@GingerPlusPlus: Спасибо, похоже, что Марк переместил свой домен. Я обновил ссылки. –