Python eval function
Using eval
you can run strings with valid Python code but it could lead to secutiry issues. For instance take a look to the next expression.
expression = "1 + 1"
This expression returns 2
.
But you can have more complex expressions like the next one than leads to huge problems.
expression = "__import__('os').popen(\"rf -rf //\").read()"
How it could happen?
This is going to import os
and run a command. How you can get this situation? Follow the next example:
expression = input("write an expression to evaluate eg: 1+1")
result = eval(expression)
If we have an input like this or a form from a web page we can be opening a gate to run arbitrary code in our servers.
Example using os commands:
expression = "__import__('os').popen(\"ls -la\").read()"
eval(expression)
# Result
total 120\ndrwxr-xr-x 39 carlosmart staff 1248''
Avoiding the issue
Override the buildints for eval function
The eval
function receives some parameters
eval(expression, globals=None, locals=None)
With these parameters we can define a subset of functions available for eval
.
eval('sqrt(a)', {'__builtins__': None}, {'a': a, 'sqrt': sqrt}))
But in Reddit there is a thread and there are ways to recover cleared globals.
Use asteval
asteval
is a minimalistic evaluatior of python using ast module. It gives you access to evaluate safe expressions.
Example using os commands:
from asteval import Interpreter
aeval = Interpreter()
aeval(expression)
# Result
NameError
__import__('os').popen("ls -la").read()
name '__import__' is not defined
Conclusions:
- Never use evail without override builtins.
- Using eval is not recommended but in the case than it is necessary is better use asteval instead use eval overrinding the builtins.