Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you protect a python variable with exec()?

Tags:

python

This is kind of a hacky Python question.

Consider the following Python code:

def controlled_exec(code):
  x = 0
  def increment_x():
    nonlocal x
    x += 1

  globals = {"__builtins__": {}} # remove every global (including all python builtins)
  locals = {"increment_x": increment_x} # expose only the increment function

  exec(code, globals, locals)

  return x

I expect this function to provide a controlled code API, which simply counts the number of increment_x() calls. I tried it and I get the correct behavior.

# returns 2
controlled_exec("""\
increment_x()
increment_x()
""")

I assume this way of doing is not secure, but I wonder out of curiosity. Can I set x to an arbitrary value (say negative) by executing code via controlled_exec(...) ? How would I do that?

like image 899
Bix Avatar asked Feb 28 '26 12:02

Bix


1 Answers

Yes, x can be set to an arbitrary value by code executed by controlled_exec.

Consider the following demo:

def controlled_exec(code):
  x = 0
  def increment_x():
    nonlocal x
    x += 1
    print(f"{x=}")

  globals = {"__builtins__": {}} # remove every global (including all python builtins)
  locals = {"increment_x": increment_x} # expose only the increment function

  exec(code, globals, locals)

  return x


controlled_exec("""\
increment_x()
increment_x.__closure__[0].cell_contents = -100
increment_x()
""")

This outputs

x=1
x=-99

This is really no way to "secure" exec. No matter what you do, at the end of the day you're executing arbitrary Python code, which is just as free to access and modify the state of the Python interpreter as the code that you write.

To highlight just how difficult it would be meaningfully secure exec, note that despite your attempt to hide builtins from the executed code, an attacker can still access any builtin via

increment_x.__globals__['__builtins__']

This is just one of dozens of tricks that someone trying to exploit this function could use.

The fact that we can modify the variable x is really a tame example. There's literally nothing stopping the code passed to controlled_exec from doing more disastrous things, like wiping your hard drive or downloading malware.

like image 182
Brian Avatar answered Mar 03 '26 03:03

Brian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!