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 или слишком много мелких деталей, чтобы все работало правильно?


person flybywire    schedule 18.08.2010    source источник
comment
См. Также: stackoverflow.com/questions/594266/equation-parsing-in -python   -  person kennytm    schedule 18.08.2010
comment
Это может решить вашу проблему? github.com/ blob /   -  person Balakrishnan    schedule 15.02.2018


Ответы (4)


можно ли исправить проблемы с безопасностью eval или слишком много мелких деталей, чтобы заставить его работать правильно?

Определенно последнее - умный хакер всегда сумеет обойти ваши меры предосторожности.

Если вас устраивают простые выражения с использованием только литералов элементарного типа, используйте ast.literal_eval - вот для чего! Для чего-нибудь более интересного я рекомендую пакет синтаксического анализа, например ply, если вы знакомы и знакомы с классический подход lexx / yacc или pyparsing для возможно более питонического подхода.

person Alex Martelli    schedule 18.08.2010
comment
По-прежнему возможен сбой ast.literal_eval: / - person Antti Haapala; 26.07.2017
comment
Это не работает для расширенной математики, например 3*2. - person theGtknerd; 28.08.2018

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

person Ned Batchelder    schedule 09.06.2012

Проблемы с безопасностью не поддаются (даже близко к этому).

Я бы использовал pyparsing, чтобы преобразовать выражение в список токенов (это не должно быть слишком сложно, потому что грамматика проста), а затем обрабатывать токены индивидуально.

Вы также можете использовать модуль ast для создания Python AST (поскольку вы используете допустимый синтаксис Python), но это может быть связано с небольшими дырами в безопасности.

person Katriel    schedule 18.08.2010
comment
Я думаю, что это не сработает, потому что я установил для locals и globals значение None, чтобы они не были видны изнутри выражения eval. - person flybywire; 18.08.2010
comment
@flybywire: извиняюсь, это правда; отредактировал. Тем не менее, это все еще плохая идея. - person Katriel; 18.08.2010
comment
@flybywire: stackoverflow.com/ questions / 661084 / - person Katriel; 18.08.2010
comment
@katrielalex, не могли бы вы перечислить проблемы, которые вы видите с безопасностью eval. Я нашел этот stackoverflow.com/ questions / 661084 / на SO, а @jerub предоставляет ссылку на проблемы с eval. Кроме того, есть ли еще какие-то проблемы, о которых нужно знать? - person Gangadhar; 18.08.2010
comment
@Ganga, думали ли вы, например, о том, как (1).__class__.__bases__[0].__subclasses__() дает вам все классы, существующие в вашей системе? Для начала ... - person Alex Martelli; 18.08.2010
comment
@Gangadhar: Я не знаю, вы можете вызвать ошибку, например, users_str = "[[]]*8**50". Я посмотрю, смогу ли я найти другой способ, но даже если я не смогу, нет никакой гарантии, что никто не сможет. - person Katriel; 18.08.2010
comment
возможен сбой интерпретатора python с ast.literal_eval - person Antti Haapala; 26.07.2017

Perl имеет модуль Safe eval http://perldoc.perl.org/Safe.html

Поиск в Google «Python-эквивалент Perl Safe» обнаруживает http://docs.python.org/2/library/rexec.html

но этот Python "ограниченный exec" устарел.

--

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

Это то, что я мог бы использовать для своих собственных инструментов, но не в Интернете.

Однако я надеюсь, что когда-нибудь полностью безопасные версии будут доступны на многих / любых языках.

person Krazy Glew    schedule 05.12.2013