Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
eval() function security
#1
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.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
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.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
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.
Recommended Tutorials:
Reply
#4
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.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
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
Reply
#6
(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.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#7
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.?
Recommended Tutorials:
Reply
#8
(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
Reply
#9
so, you just add functions to it as needed.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  make eval() safe Skaperen 5 2,615 Mar-24-2022, 05:47 PM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020