Eval in Python



This is an interesting hacking utility in Python that allows a Python program to run Python code within itself.

The eval () method parses the expression passed to it and runs the Python expression (code) in program.

eval syntax:

  eval (expression, globals = None, locals = None)  
  • expression: this string is parsed and evaluated as a Python expression
  • global (optional): a dictionary to specify available global methods and variables.
  • locals (optional): another dictionary to specify the available local methods and variables.

Let`s explore this with a simple Python program:

from math import *

 

def secret_function ():

return "Secret key is 1234 "

  

def function_creator ():

 

# expression to evaluate

expr = raw_input ( "Enter the function (in terms of x):" )

 

# variable used in expression

  x = int ( raw_input ( "Enter the value of x : " ))

  

# evaluating expression

y = eval (expr)

 

# print the assessed result

print ( "y = {}" . format (y)) 

 

if __ name__ = = " __ main__ " :

function_creator ()

function_creator — is a function that evaluates user-generated math functions.

Consider the output:

 Enter the function (in terms of x): x * (x + 1) * (x + 2 ) Enter the value of x: 3 y = 60 

Let`s analyze the code a bit:

  • The above function accepts any expression in the x variable as input.
  • Then the user must enter the value x .
  • Finally, we evaluate the python expression using the built-in function eval () by passing expr as an argument.

Eval vulnerability issues

Our current version of function_creator has several vulnerabilities.

The user can easily reveal hidden values ​​in the program or call a dangerous function, as eval will do whatever is passed to it.

For example, if you enter like this:

  Enter the function (in terms of x): secret_function () Enter the value of x: 0 

You will get the output:

  y = Secret key is 1234 

Also consider the situation when you imported the os module into your python program. The os module provides a portable way to use operating system functions such as reading or writing a file. One command can delete all files on your system!

Of course, in most cases (like desktop programs) the user cannot do more than he could by writing his own Python script, but in some applications ( e.g. web applications, kiosk computers) this can be a risk!

The solution is to restrict eval to only those functions and variables that we want to make available.

Making eval safe

The eval function comes with the ability to explicitly pass a list of functions or variables to which it can access. We need to pass it as an argument as a dictionary.

Consider the example below:

from math import *

  

def secret_function ():

return "Secret key is 1234"

 

def function_creator ():

 

# expression to evaluate

expr = raw_input ( " Enter the function (in terms of x): " )

  

  # variable used in expression

x = int ( raw_input ( "Enter the value of x:" ))

 

# pass variable x in the safe dictionary

safe_dict [ ` x` ] = x

  

# evaluating expression

y = eval (expr, { "__ builtins__" : None }, safe_dict)

 

# print the evaluated result

  print ( "y = {}" . format (y))

 

if __ name__ = = "__ main__" :

 

# list of safe methods

safe_list = [ ` acos` , `asin` , `atan` , `atan2` , ` ceil` , `cos` ,

  `cosh` , ` degrees` , `e` , < / code> `exp` , ` fabs` , `floor` ,

  ` fmod` , `frexp` , `hypot` , ` ldexp` , `log` , `log10` ,

  ` modf` , `pi` , `pow` , ` radians` , ` sin` , ` sinh` , `sqrt` ,

`tan` , `tanh` ]

  

# create a dictionary of safe methods

safe_dict = dict ([(k, locals (). get (k, None )) for k in safe_list])

  

function_creator ()

Now if we try to run the above program as:

  Enter the function (in terms of x): secret_function () Enter the value of x: 0 

We get the output:

  NameError: name `secret_function` is not defined 

Let`s analyze the above code step by step:

  • Before in total, we create a list of methods that we want to resolve as safe_list .
  • Next, we create a dictionary of safe methods. In this dictionary, keys — these are method names, and values ​​ — their local namespaces.
      safe_dict = dict ([(k, locals (). get (k, None)) for k in safe_list]) 

    locals () — it is a built-in method that returns a dictionary that maps all methods and variables in the local scope with their namespaces.

  •   safe_dict [`x`] = x  

    Here we add the local variable x to safe_dict. No local variable other than x will be identified by eval .

  • eval accepts dictionaries local and global variables as arguments. So, to ensure that none of the built-in methods are available for the eval expression, we pass in another dictionary along with safe_dict as shown below:
      y = eval (expr, {"__builtins __": None}, safe_dict) 

So we made our function eval safe from any possible hacks!

Using Eval

eval is not as often used for security reasons as we have explored above.

However, it is convenient in some situations such as:

  • You might want to use it to allow users to enter their own "scriptlets": small expressions (or even small functions) that can be used to customize the behavior of a complex system.
  • eval also different It is used in applications that need to evaluate mathematical expressions. It`s much easier than writing an expression parser.

This blog is provided by Nikhil Kumar . If you like Python.Engineering and would like to contribute, you can also write an article using contrib.python.engineering, or email your article to [email protected] See my article appearing on the Python.Engineering homepage and help other geeks.

Please post comments if you find anything wrong or if you would like to share more information on the topic discussed above.