229
Demonstrative Examples
Example 1:
edit-config.pl: This CGI script is used to modify settings in a configuration file.
Example Language: Perl (Bad)
use CGI qw(:standard);
sub config_file_add_key {
my ($fname, $key, $arg) = @_;
# code to add a field/key to a file goes here
}
sub config_file_set_key {
my ($fname, $key, $arg) = @_;
# code to set key to a particular file goes here
}
sub config_file_delete_key {
my ($fname, $key, $arg) = @_;
# code to delete key from a particular file goes here
}
sub handleConfigAction {
my ($fname, $action) = @_;
my $key = param('key');
my $val = param('val');
# this is super-efficient code, especially if you have to invoke
# any one of dozens of different functions!
my $code = "config_file_$action_key(\$fname, \$key, \$val);";
eval($code);
}
$configfile = "/home/cwe/config.txt";
print header;
if (defined(param('action'))) {
handleConfigAction($configfile, param('action'));
}
else {
print "No action specified!\n";
}
The script intends to take the 'action' parameter and invoke one of a variety of functions
based on the value of that parameter - config_file_add_key(), config_file_set_key(), or
config_file_delete_key(). It could set up a conditional to invoke each function separately, but eval()
is a powerful way of doing the same thing in fewer lines of code, especially when a large number
of functions or variables are involved. Unfortunately, in this case, the attacker can provide other
values in the action parameter, such as:
Example Language: (Attack)
add_key(",","); system("/bin/ls");
This would produce the following string in handleConfigAction():
Example Language: (Result)
config_file_add_key(",","); system("/bin/ls");
Any arbitrary Perl code could be added after the attacker has "closed off" the construction of the
original function call, in order to prevent parsing errors from causing the malicious eval() to fail
before the attacker's payload is activated. This particular manipulation would fail after the system()
call, because the "_key(\$fname, \$key, \$val)" portion of the string would cause an error, but this is
irrelevant to the attack because the payload has already been activated.
Example 2:
This simple script asks a user to supply a list of numbers as input and adds them together.
CWE Version 4.14
CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')
CWE-95: Improper Neutralization of Directives
in Dynamically Evaluated Code ('Eval Injection') 230
Example Language: Python (Bad)
def main():
sum = 0
numbers = eval(input("Enter a space-separated list of numbers: "))
for num in numbers:
sum = sum + num
print(f"Sum of {numbers} = {sum}")
main()
The eval() function can take the user-supplied list and convert it into a Python list object, therefore
allowing the programmer to use list comprehension methods to work with the data. However, if
code is supplied to the eval() function, it will execute that code. For example, a malicious user could
supply the following string:
Example Language: (Attack)
__import__('subprocess').getoutput('rm -r *')
This would delete all the files in the current directory. For this reason, it is not recommended to use
eval() with untrusted input.
A way to accomplish this without the use of eval() is to apply an integer conversion on the input
within a try/except block. If the user-supplied input is not numeric, this will raise a ValueError. By
avoiding eval(), there is no opportunity for the input string to be executed as code.
Example Language: Python (Good)
def main():
sum = 0
numbers = input("Enter a space-separated list of numbers: ").split(" ")
try:
for num in numbers:
sum = sum + int(num)
print(f"Sum of {numbers} = {sum}")
except ValueError:
print("Error: invalid input")
main()
An alternative, commonly-cited mitigation for this kind of weakness is to use the ast.literal_eval()
function, since it is intentionally designed to avoid executing code. However, an adversary could
still cause excessive memory or stack consumption via deeply nested structures [REF-1372], so
the python documentation discourages use of ast.literal_eval() on untrusted data [REF-1373].
Observed Examples
Reference Description
CVE-2022-2054 Python compiler uses eval() to execute malicious strings as Python code.
https://www.cve.org/CVERecord?id=CVE-2022-2054
CVE-2021-22204 Chain: regex in EXIF processor code does not correctly determine where a
string ends (CWE-625), enabling eval injection (CWE-95), as exploited in the
wild per CISA KEV.
https://www.cve.org/CVERecord?id=CVE-2021-22204
CVE-2021-22205 Chain: backslash followed by a newline can bypass a validation step
(CWE-20), leading to eval injection (CWE-95), as exploited in the wild per
CISA KEV.
https://www.cve.org/CVERecord?id=CVE-2021-22205
CVE-2008-5071 Eval injection in PHP program.
https://www.cve.org/CVERecord?id=CVE-2008-5071
CVE-2002-1750 Eval injection in Perl program.
https://www.cve.org/CVERecord?id=CVE-2002-1750
CWE Version 4.14
CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')
CWE-95: Improper Neutralization of Directives
in Dynamically Evaluated Code ('Eval Injection')