python что такое eval
И снова про опасность eval()
Сколько было сломано копий при обсуждении вопроса «Возможно ли сделать eval безопасным?» — невозможно сосчитать. Всегда находится кто-то, кто утверждает, что нашёл способ оградиться от всех возможных последствий выполнения этой функции.
Когда мне понадобилось найти развёрнутый ответ на этот вопрос, я наткнулся на один пост. Меня приятно удивила глубина исследования, так что я решил, что это стоит перевести.
Коротко о проблеме
Какие есть решения?
Ну а теперь-то мы в безопасности?
Итак, давайте разберёмся, что же здесь происходит. Начнём с этого:
Далее в коде нам надо будет дважды искать класс, так что создадим функцию:
Чтобы вызвать функцию, надо как-то её назвать, но, так как мы будем выполнять этот код внутри eval ‘a, мы не можем ни объявить функцию (используя def ), ни использовать оператор присвоения, чтобы привязать нашу лямбду к какой-нибудь переменной.
Однако, есть и третий вариант: параметры по умолчанию. При объявлении лямбды, как и при объявлении любой обычной функции, мы можем задать параметры по умолчанию, так что если мы поместим весь код внутри ещё одной лямбды, и зададим ей нашу, как параметр по умолчанию, — мы добьёмся желаемого:
Итак, мы имеем функцию, которая умеет искать классы, и можем обращаться к ней по имени. Что дальше? Мы создадим объект класса code (внутренний класс, его экземпляром, например, является свойство func_code объекта функции):
Из всех инициализующих параметров нас интересует только «KABOOM». Это и есть последовательность байт-кодов, которую будет использовать наш объект, и, как вы уже могли догадаться, эта последовательность не является «хорошей». На самом деле любого байт-кода из неё хватило бы, так как всё это — бинарные операторы, которые будут вызваны при пустом стеке, что приведёт к segfault ‘у CPython. «KABOOM» просто выглядит забавнее, спасибо lvh за этот пример.
Ну и теперь, когда у нас есть функция, мы можем её выполнить. Конкретно эта функция попытается выполнить наш некорректно составленный байт-код и приведёт к краху интерпретатора.
Вот весь код ещё раз:
Заключение
Итак, надеюсь теперь ни у кого не осталось сомнений в том, что eval НЕ БЕЗОПАСЕН, даже если убрать доступ к глобальным и встроенным переменным.
Сейчас мы запускали eval в пустом окружении, исходя из того, что указанный в статье код — это весь код нашей программы.
В случае использования eval ‘а в реальном приложении злоумышленник может получить доступ ко всем классам, которые вы используете, так что его возможности не будут ограничены практически ничем.
Проблема всех подобных попыток сделать eval безопасным в том, что они все основаны на идее «чёрных списков», идее о том, что надо убрать доступ ко всем вещам, которые, как нам кажется, могут быть опасны при использовании в eval ‘е. С такой стратегией практически нет шансов на победу, ведь если окажется незапрещённым хоть что-то, система будет уязвима.
Когда я проводил исследование этой темы, я наткнулся на защищенный режим выполнения eval ‘а в Python, который является ещё одной попыткой побороть эту проблему:
Вкратце, он работает следующим образом: если __builtins__ внутри eval отличаются от «официальных» — eval переходит в защищенный режим, в котором закрыт доступ к некоторым опасным свойствам, таким как func_code у функций. Более подробное описание этого режима можно найти тут, но, как мы уже видели выше, он тоже не является «серебряной пулей».
И всё-таки, можно ли сделать eval безопасным? Сложно сказать. Как мне кажется, злоумышленнику не удастся навредить без доступа к объектам с двумя нижними подчёркиваниями, обрамляющими имя, так что возможно, если исключить из обработки все строки с двумя нижними подчёркиваниями, то мы будем в безопасности. Возможно.
В треде на Reddit я нашёл короткий сниппет, позволяющий нам в eval получить «оригинальные» __builtins__:
Встроенная функция Python eval ()
Дата публикации Oct 19, 2019
Давайте разберемся со встроенной функцией eval () в python.
Это будет короткая статья о функции eval в python, в которой я объясню вам функцию eval, ее синтаксис и несколько вопросов, которые часто задают в интервью, чтобы вы четко поняли ее и с легкостью ответили на эти вопросы. Чтобы получить полный код, нажмите на мойGitHub репозиторийснизу:
Тан-N-Прабх / Python
github.com
Давайте начнем:
1. Что такое eval () в python и каков его синтаксис?
Синтаксис
Синтаксис функции eval показан ниже:
Аргументы или параметры
Возвращаемое значение
Возвращаемое значение будет результатом вычисленного выражения. Часто тип возвращаемого значения будет целым числом.
2. Где в основном используется функция eval?
Функция Eval в основном используется в ситуациях или приложениях, которые должны оценивать математические выражения. Также, если пользователь хочет вычислить строку в коде, он может использовать функцию eval, потому что функция eval оценивает строковое выражение и в результате возвращает целое число.
3. В чем разница между input () и eval ()?
Теперь вы все знаете, что input () принимает пользовательский ввод, но когда пользователь вводит целое число в качестве входных данных, функция ввода возвращает строку, но в случае eval она будет оценивать возвращаемое значение из строки в целое число. Я знаю, что большинство из вас смущены, позвольте мне прояснить ваше замешательство, приведя пример:
Смотрите, как я уже сказал, я ввел целое число10+ 10где я ожидал результата20 (10 + 10)но метод ввода вернул строку с тем же введенным значением.
4. Можем ли мы выполнить математические операции, используя функцию eval, приведите пример?
Да, мы можем выполнять математические операции, используя функцию eval, как показано ниже:
Посмотрите, как я сказал, если вы передаете входные данные в виде строки, а функция eval вычисляет выражение и возвращает результат в виде целого числа.
Это все, что вам нужно знать, чтобы начать работу с функцией eval в python, теперь вы знаете все ответы на поставленные выше вопросы. Одни и те же вопросы могут задаваться не всегда, дело в том, чтобы лучше понять концепции, тогда вы сможете ответить на любые вопросы. Если вы хотите потратить некоторое время на чтение материала о функции eval, я рекомендую вам, ребята, прочитать документацию по функции eval, показанную ниже:
docs.python.org
Спасибо, ребята, это конец статьи, как я уже сказал, это небольшая статья. Если у вас, ребята, есть какие-то сомнения или если вы застряли с чем-то, пожалуйста, дайте мне знать в комментариях ниже, я обязательно отвечу на все ваши вопросы. Ладно время прощаться, прекрасного дня.
Что делает eval () Python?
в книге, которую я читаю на Python, он продолжает использовать код eval(input(‘blah’))
Я читаю документацию, и я ее понимаю, но я до сих пор не вижу, как она меняет
9 ответов
функция eval позволяет программе Python запускать код Python внутри себя.
пример eval (интерактивная оболочка):
в этом случае eval используется для принуждения строки, возвращенной из input в выражении и интерпретации. Обычно это считается плохой практикой.
много хороших ответов здесь, но ни один не описывает использование eval в контексте globals= и locals= kwargs. Они могут использоваться для ограничения методов, доступных через eval метод. Например, если вы загружаете новый интерпретатор python, то locals() и globals() будет то же самое и выглядеть примерно так:
дополнительно все __builtins__ доступно.
Ok. Таким образом, мы видим один метод, который мы хотим разоблачить, и пример одного (из многих, которые могут быть гораздо более коварными) метода, который мы не хотим разоблачать. Так давайте блокировать всё.
мы эффективно заблокировали все __builtins__ методы и как таковые принесли уровень защиты в нашу систему. На этом этапе мы можем начать добавлять обратно методы,которые мы хотим выставить.
теперь у нас есть метод cpu_count доступен, все еще блокируя все, что мы не хотим. На мой взгляд, это супер мощный и явно из области других ответов не общая реализация. Есть множество применений для что-то вроде этого и до тех пор, пока оно обрабатывается правильно, я лично чувствую eval можно безопасно использовать к большому значению.
что-то еще, что круто об этих kwargs это то, что вы можете начать использовать стенографию для своего кода. Предположим, вы используете eval как часть конвейера для выполнения некоторого импортированного текста. Текст не должен иметь точный код, он может следовать формату файла шаблона и выполнять все, что вы хотите. Для пример:
eval() анализирует переданную строку как выражение Python и возвращает результат. Например, eval(«1 + 1») интерпретирует и выполняет выражение «1 + 1» и возвращает результат (2).
одна из причин, по которой вы можете быть смущены, заключается в том, что приведенный вами код включает в себя уровень косвенности. Внутренний вызов функции (ввод) выполняется первым, поэтому пользователь видит приглашение «бла». Давайте представим, что они отвечают «1 + 1 «(кавычки добавлены для ясности, не вводите их при запуске program), функция ввода возвращает эту строку, которая затем передается внешней функции (eval), которая интерпретирует строку и возвращает результат (2).
raw_input() теперь input() в python 3.X версий. Таким образом, наиболее часто встречающийся пример использования eval() его использование для обеспечения функциональности, которая input() в 2.x версия python. raw_input вернул введенные пользователем данные в виде строки, а input оценил значение введенных данных и вернул его.
eval(input(«bla bla»)) таким образом, реплицирует функциональность input() в 2.x, т. е. оценка введенных пользователем данных.
короче: eval() оценивает переданные ему Аргументы и, следовательно, eval(‘1 + 1’) возвращены 2.
возможно, вводящий в заблуждение пример чтения строки и ее интерпретации.
читать его как переменную и изменить ее:
Я опаздываю, чтобы ответить на этот вопрос, но, похоже, никто не дает четкого ответа на этот вопрос.
если пользователь вводит числовое значение, input() вернет строку.
и eval() будет оценивать возвращаемое значение (или выражение), которое является строкой и возвращает целое число/float.
конечно, это плохая практика. int() или float() вместо eval() в этом случае.
Функция eval() в Python
Функция eval() в Python используется для синтаксического анализа строки выражения, как выражения Python и последующего ее выполнения.
expression – обязательный строковый параметр, он анализируется и выполняется, как выражение Python.
globals – словарь, используемый для определения доступных для выполнения выражений. Стандартные встроенные методы доступны, если явно не ограничены с помощью элемента ‘__builtins__’: None.
locals – используется для указания локальных переменных и методов, доступных для функции eval().
Пример
Давайте сначала рассмотрим простой пример функции eval() в python.
eval() с пользовательским вводом
Приведенный выше пример функции eval() очень ограничен и не оправдывает ее возможности. Сила функции заключается в динамическом выполнении операторов. Мы можем выполнять произвольные объекты кода с помощью функции eval().
Давайте посмотрим на более сложный пример, где мы попросим пользователя ввести функции для выполнения.
На изображении ниже показан пример выполнения указанного выше скрипта Python.
Без функции eval мы не можем выполнять команды, введенные пользователем. В этом сила функции eval().
Риски безопасности
Вот почему, когда вы используете функцию eval() для выполнения кода ввода пользователя, вам необходимо убедиться, что введенные пользователем данные сначала проверяются, и если они в порядке, то выполняется только их. Вот тогда и пригодятся параметры globals и locals.
Глобальные и локальные переменные
Прежде чем мы решим, какие функции мы должны сделать доступными для eval(), нам нужно выяснить, какие все функции и переменные присутствуют в глобальной и локальной области. Мы можем найти эту информацию с помощью встроенных функций locals(), globals() и dir().
Давайте посмотрим на пример, где мы узнаем функции и переменные, доступные в глобальной и локальной области.
Это множество функций, к которым у eval() будет доступ. Большинство из них взяты из модуля __builtins__ и math.
Посмотрим, что произойдет, если мы укажем значение globals, как пустой словарь в функции eval.
Таким образом, для функции eval по-прежнему доступны встроенные методы. Если вы хотите ограничить доступ только к нескольким встроенным методам, вы можете указать его значение для глобальных переменных. Например, приведенный ниже код позволяет функции eval() выполнять только встроенную функцию min.
Давайте посмотрим на другой пример, где я предоставляю значение locals и отключаю доступ ко всем встроенным функциям для eval().
Давайте посмотрим на последний пример, в котором я разрешаю доступ только к некоторым методам из математического модуля. Мы также сопоставляем square_root с функцией sqrt для удобства чтения человеком.
Я ничего не указал для встроенных функций, поэтому они будут доступны для функции eval().
Ниже приведен еще один пример выполнения, показывающий, что встроенные функции доступны для выполнения.
Функция eval() в Python
Функция Python eval() преобразует и вычисляет переданные ей выражения.
Используйте этот метод только для тестирования. Функция eval() не очищает переданные ей выражения. Это может легко стать лазейкой на вашем сервере, если злоумышленники выполнят здесь код Python.
Функция eval() function анализирует выражения и запускает переданный ей код в качестве параметра в программе Python.
Пример 1: Передача выражения для добавления двух локальных переменных
В приведенном выше фрагменте кода мы передали выражение «a + b» функции eval(), чтобы добавить две локальные переменные: a, b.
Пример 2: функция Python eval() с пользовательским вводом
В приведенном выше примере мы приняли ввод от пользователя и присвоили его переменным. Кроме того, мы передали выражение для умножения этих двух входных значений.
С модулем Pandas
Функция Python eval также может работать с модулем Pandas. Функция pandas.eval() принимает выражение и выполняет то же самое в программе python.
Пример 1. Передача выражения с inplace = TRUE
В приведенном выше примере мы создали фрейм данных и передали выражение для выполнения в скрипте python.
Поскольку inplace установлено в TRUE, значения данных, полученные из выражения, будут сохранены в том же объекте dataframe ‘data’.
Пример 2: Выполнение выражения в скрипте Python с inplace = FALSE
В приведенном выше фрагменте кода мы передали inplace = FALSE функции eval(). Таким образом, результаты выражения будут сохранены в новом объекте фрейма данных «data1».