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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With