TensorFlow Python Code Injection: More eval() Woes
Background
JFrog security research team (formerly Vdoo) has recently disclosed a code injection issue in one of the utilities shipped with TensorFlow, a popular Machine Learning platform that’s widely used in the industry. The issue has been assigned to CVE-2021-41228.
Read more about our previous, similar disclosure in Yamale in our previous blog post.
The injection issue
The issue lies in the saved_model_cli
tool, which is used to save a model’s state.
An attacker that can control the contents of the --input_examples
argument, can provide a malicious input that runs arbitrary Python code.
The underlying issue lies in the preprocess_input_examples_arg_string
function:
def preprocess_input_examples_arg_string(input_examples_str):
input_dict = preprocess_input_exprs_arg_string(input_examples_str)
...
which calls preprocess_input_exprs_arg_string
, that contains the vulnerable call:
def preprocess_input_exprs_arg_string(input_exprs_str):
input_dict = {}
for input_raw in filter(bool, input_exprs_str.split(';')):
...
input_key, expr = input_raw.split('=', 1)
# ast.literal_eval does not work with numpy expressions
input_dict[input_key] = eval(expr) # pylint: disable=eval-used
return input_dict
In our case, input_exprs_str
is the user’s input coming from the command line argument.
We can see that arbitrary input is flowing to eval
, which leads to code injection.
Since the --input_examples
option takes only a list of dictionaries, it is unexpected by the end-user (and undocumented by the vendor) that arbitrary input can lead to code injection.
TensorFlow’s fix
The issue was fixed in TensorFlow 2.7.0, we urge anyone using the saved_model_cli
tool to upgrade to this version.
Since the --input_examples
option should only accept a list of dictionaries, the eval call was replaced with a call to json.loads
, which accepts a list of dictionaries and is safe for use with arbitrary unfiltered input.
Can we exploit it remotely?
As mentioned in our previous blogpost , these issues might be remotely exploitable (in a reasonable scenario) in the context of a parameter injection attack. See our previous blogpost for more details.
Acknowledgements
We would like to thank TensorFlow’s maintainers, for validating and fixing the issue in a prompt manner and responsibly creating a CVE for the issue after the fixed version was available.