# Remote Code Execution
A **remote code execution** (RCE) vulnerability allows an attacker to execute arbitrary code on you server. On a web-server, RCE vulnerabilities are typically cause when untrusted input from the HTTP request is evaluated as code.
## Remote Code Execution in Python
Python code can be evaluated dynamically using the global `eval(…)` and `exec(…)` functions. The former expects a string representing a (single) valid Python expression, while the later can execute multiple expressions – making it able to create new module, class, and function definitions. Both functions have access to the global and local state at the point of invocation.
Passing untrusted string as code to be evaluated allows an attacker to execute arbitrary code in your Python runtime – meaning they can steal sensitive information, read files from disk, or install malware. This is very dangerous!
To mitigate remote code execution attacks, you must ensure any strings are taken from a trusted source, or validated against an allow-list. To be totally secure, it’s often better to avoid `eval(…)` and `exec(…)` functions of Python altogether.
## Domain Specific Languages
Dynamic evaluation is often used to build *Domain Specific Languages* (DSLs) that allow expert users to write simple expressions that query data or encode business logic. If you find yourself writing a DSL in Python, consider using the `ast` (*Abstract Syntax Tree*) module, which allows you to parse expressions and evaluate each node atomically. This will help you “sandbox” the functions a user can invoke, removing the risks of arbitrary code execution.
Here’s a simple example of a DSL that can evaluate mathematical expressions:
“`python import ast, operator, mathdef safe_eval(expression): “””Evaluate a simple mathematical function by parsing an expression into an abstract syntax tree and safely evaluating each node in turn.””” def find_math_function(x, *args): return getattr(math, x) binary_operations = { unary_operations = { operations = tuple(binary_operations) + tuple(unary_operations) syntax_tree = ast.parse(expression, mode=’eval’) def _eval(node): return _eval(syntax_tree) safe_eval(“1 + 1”) # Will return 2 |
## CWEs
* [CWE-94](https://cwe.mitre.org/data/definitions/94.html)