Python: сделать безопасным eval
Я хочу простой способ сделать "API калькулятора" в Python.
В настоящий момент меня не волнует точный набор функций, которые будет поддерживать калькулятор.
Я хочу, чтобы он получил строку, скажем "1+1"
и вернул строку с результатом, в нашем случае "2"
.
Есть ли способ сделать eval
безопасным для такой вещи?
Для начала я бы сделал
env = {}
env["locals"] = None
env["globals"] = None
env["__name__"] = None
env["__file__"] = None
env["__builtins__"] = None
eval(users_str, env)
чтобы вызывающий пользователь не мог испортить мои локальные переменные (или увидеть их).
Но я уверен, что многому занимаюсь здесь.
Являются ли проблемы безопасности eval
исправлены или есть слишком много мелких деталей, чтобы заставить его работать правильно?
Ответы
Ответ 1
- проблемы безопасности eval, исправляемые или есть слишком много мелких деталей чтобы он работал правильно?
Определенно последнее - умный хакер всегда сможет найти способ защитить ваши меры предосторожности.
Если вас устраивают простые выражения, используя только литералы элементарного типа, используйте ast.literal_eval - для чего это! Для любого любителя я рекомендую пакет синтаксического анализа, например ply, если вы знакомы и комфортно с классическим подходом lexx/yacc или pyparsing для возможного более питонического подхода.
Ответ 2
Можно получить доступ к любому классу, который был определен в этом процессе, и затем вы можете создать его экземпляр и вызвать на нем методы. Можно выполнить sephfault интерпретатор CPython или заставить его выйти. Смотрите: Eval действительно опасен
Ответ 3
Проблемы безопасности не являются (даже близкими к возможностям).
Я бы использовал pyparsing
, чтобы разобрать выражение в списке токенов (это не должно быть слишком сложно, потому что грамматика прямо), а затем обрабатывать жетоны индивидуально.
Вы также можете использовать модуль ast
для создания АСТ Python (поскольку вы используете действительный синтаксис Python), но это может быть открытыми для тонких дыр в безопасности.
Ответ 4
Perl имеет безопасный модуль eval http://perldoc.perl.org/Safe.html
Googling "эквивалент Python Perl Safe" находит
http://docs.python.org/2/library/rexec.html
но этот "ограниченный exec" на Python устарел.
-
В целом безопасность "eval" на любом языке является большой проблемой. Атаки SQL-инъекций - всего лишь пример такой дыры в безопасности. У Perl Safe были ошибки безопасности на протяжении многих лет - последнее, что я помню, это было безопасно, за исключением деструкторов на объектах, возвращенных из безопасного eval.
Это то, что я могу использовать для своих собственных инструментов, но не для веб-страниц.
Однако я надеюсь, что когда-нибудь полностью обеспеченные оценки будут доступны на многих/любых языках.