Python Forum

Full Version: eval() function security
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
i want to use eval() to evaluate arithmetic expressions provided by a string. the expressions may come from an untrusted source such as a web form. is there a definite way to filter the string to keep eval() safe while still allowing most arithmetic expressions? i'm thinking to allow alphanumeric and ()+-*/ and nothing else. if some other character is there just substitute None and let the web result say the expression is invalid.
No. You are going to have to include '.' as well for decimal numbers, right? At that point you have attribute access and function calls possible. I don't think you can allow letters and have it be safe. If you need letters, I would recommend parsing the mathematical expression yourself, and not leave it to eval.
I once used eval in an IRC bot to evaluate arithmetic expressions. Luckily the person was a white hat and kindly shown me an example of exploiting eval to gain access to my desktop. Had complete control to remove files or add them to my computer. I have never used eval again in a setting where there is an untrusted string. I would rather write up my own way to evaluate arithmetic expressions from now on. It might take a little more code, but it is worth it.
eval or exec from unthrusted source is always a bad idea in all languages.
Even formats like XML, YAML, JSON do allow code execution. JSON does not affect the Python world, but its a valid JavaScript Object.
XML supports loops (bad) and YAML can execute Python code or other code.
Can look at project that try to make it safer,most build on top of ast module.
simpleeval | ASTEVAL.
How safe the are have not i no look into.
To to do a quick test with some something that should obviously fail.
(my_env) E:\div_code\my_env
>>> from simpleeval import simple_eval
>>>
>>> simple_eval("500 + 99")
599

# eval() will try to delete
>>> eval('__import__("os").remove("spam")')
FileNotFoundError: [WinError 2] System cannot find specified file: 'spam'

# Fail
>>> simple_eval('__import__("os").remove("spam")')
simpleeval.FunctionNotDefined: Function '__import__' not defined, for expression
(Sep-21-2019, 07:00 AM)metulburr Wrote: [ -> ]I once used eval in an IRC bot to evaluate arithmetic expressions. Luckily the person was a white hat and kindly shown me an example of exploiting eval to gain access to my desktop. Had complete control to remove files or add them to my computer. I have never used eval again in a setting where there is an untrusted string. I would rather write up my own way to evaluate arithmetic expressions from now on. It might take a little more code, but it is worth it.
this is exactly my concern. i used to be a gray-hat hacker long ago.

i will try out simpleval and try to break it and see how that goes.
it doesnt look like you can import anything with simple_eval
Error:
simpleeval.FunctionNotDefined: Function '__import__' not defined, for expression '__import__("math").fabs(-10)'.
Would there be a way to specify the modules allowed to import, such as math or decimal, etc.?
(Sep-22-2019, 04:01 PM)metulburr Wrote: [ -> ]Would there be a way to specify the modules allowed to import, such as math or decimal, etc.?
Should work,look like is made so can extent quite easy.
>>> from simpleeval import SimpleEval
>>> from math import sqrt
>>> 
>>> s = SimpleEval(functions={"sqrt": sqrt})
>>> s.eval('sqrt(42) * 2')
12.96148139681572
Or.
>>> import simpleeval
>>> import math
>>> 
>>> simpleeval.DEFAULT_FUNCTIONS["cos"] = math.cos
>>> simpleeval.simple_eval("cos(5) * 9")
2.552959669169036
so, you just add functions to it as needed.