Introduction
The
__code__
attribute of a Python function can be overwritten, allowing us to break out of a constrained namespace and use an elevated one.
We can view all the attributes of a Python object using print(func.__dir__())
. If we run this on the print
function object for example, be able to see its __code__
attribute.
We can overwrite this attribute with the code of another function or a lambda. Lambdas are generally easier when working with code injections.
Example
Output:
1
2
Namespace Escalation
We can use this property to escalate to a namespace with more functions available. Consider the following exec()
injection with a limited namespace.
Note
Notice that the globals available to use in the
exec()
function have been limited. In this case, onlyprint()
can be called.
Failed exploit
Output:
We get the error that the os
module is not defined, which make sense since it’s not included in the restricted namespace of the exec
.
Now, lets try the same code with a different injection. This time we’re going to overwrite the __code__
attribute of print
with that of a custom lambda. We’ll then run print()
.
Working exploit
Output:
EXPLOITED!
Success
The
exec
, it’s using the namespace ofnew_print
which has access to theos
module and all the default Python built-ins.
With this change, print(os.popen('echo EXPLOITED!').read())
is running as if it’s not in the constrained namespace.