Bypass Python sandboxes
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Get a hacker's perspective on your web apps, network, and cloud
Find and report critical, exploitable vulnerabilities with real business impact. Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
These are some tricks to bypass python sandbox protections and execute arbitrary commands.
Command Execution Libraries
The first thing you need to know is if you can directly execute code with some already imported library, or if you could import any of these libraries:
Remember that the open and read functions can be useful to read files inside the python sandbox and to write some code that you could execute to bypass the sandbox.
Python2 input() function allows executing python code before the program crashes.
Python try to load libraries from the current directory first (the following command will print where is python loading modules from): python3 -c 'import sys; print(sys.path)'

Bypass pickle sandbox with the default installed python packages
Default packages
You can find a list of pre-installed packages here: https://docs.qubole.com/en/latest/user-guide/package-management/pkgmgmt-preinstalled-packages.html Note that from a pickle you can make the python env import arbitrary libraries installed in the system. For example, the following pickle, when loaded, is going to import the pip library to use it:
For more information about how pickle works check this: https://checkoway.net/musings/pickle/
Pip package
Trick shared by @isHaacK
If you have access to pip or pip.main() you can install an arbitrary package and obtain a reverse shell calling:
You can download the package to create the reverse shell here. Please, note that before using it you should decompress it, change the setup.py, and put your IP for the reverse shell:
Eval-ing python code
Note that exec allows multiline strings and ";", but eval doesn't (check walrus operator)
If certain characters are forbidden you can use the hex/octal/B64 representation to bypass the restriction:
Other libraries that allow to eval python code
Operators and short tricks
Bypassing protections through encodings (UTF-7)
In this writeup UFT-7 is used to load and execute arbitrary python code inside an apparent sandbox:
It is also possible to bypass it using other encodings, e.g. raw_unicode_escape and unicode_escape.
Python execution without calls
If you are inside a python jail that doesn't allow you to make calls, there are still some ways to execute arbitrary functions, code and commands.
RCE with decorators
RCE creating objects and overloading
If you can declare a class and create an object of that class you could write/overwrite different methods that can be triggered without needing to call them directly.
RCE with custom classes
You can modify some class methods (by overwriting existing class methods or creating a new class) to make them execute arbitrary code when triggered without calling them directly.
Crating objects with metaclasses
The key thing that metaclasses allow us to do is make an instance of a class, without calling the constructor directly, by creating a new class with the target class as a metaclass.
Creating objects with exceptions
When an exception is triggered an object of the Exception is created without you needing to call the constructor directly (a trick from @_nag0mez):
More RCE
Read file with builtins help & license
Builtins
If you can access the __builtins__ object you can import libraries (notice that you could also use here other string representation shown in the last section):
No Builtins
When you don't have __builtins__ you are not going to be able to import anything nor even read or write files as all the global functions (like open, import, print...) aren't loaded.
However, by default python imports a lot of modules in memory. These modules may seem benign, but some of them are also importing dangerous functionalities inside of them that can be accessed to gain even arbitrary code execution.
In the following examples you can observe how to abuse some of this "benign" modules loaded to access dangerous functionalities inside of them.
Python2
Python3
Below there is a bigger function to find tens/hundreds of places were you can find the builtins.
Python2 and Python3
Builtins payloads
Globals and locals
Checking the globals and locals is a good way to know what you can access.
Below there is a bigger function to find tens/hundreds of places were you can find the globals.
Discover Arbitrary Execution
Here I want to explain how to easily discover more dangerous functionalities loaded and propose more reliable exploits.
Accessing subclasses with bypasses
One of the most sensitive parts of this technique is being able to access the base subclasses. In the previous examples this was done using ''.__class__.__base__.__subclasses__() but there are other possible ways:
Finding dangerous libraries loaded
For example, knowing that with the library sys it's possible to import arbitrary libraries, you can search for all the modules loaded that have imported sys inside of them:
There are a lot, and we just need one to execute commands:
We can do the same thing with other libraries that we know can be used to execute commands:
Moreover, we could even search which modules are loading malicious libraries:
Moreover, if you think other libraries may be able to invoke functions to execute commands, we can also filter by functions names inside the possible libraries:
Recursive Search of Builtins, Globals...
This is just awesome. If you are looking for an object like globals, builtins, open or anything just use this script to recursively find places where you can find that object.
You can check the output of this script on this page:
https://github.com/carlospolop/hacktricks/blob/master/generic-methodologies-and-resources/python/bypass-python-sandboxes/broken-reference/README.mdPython Format String
If you send a string to python that is going to be formatted, you can use {} to access python internal information. You can use the previous examples to access globals or builtins for example.
Note how you can access attributes in a normal way with a dot like people_obj.__init__ and dict element with parenthesis without quotes __globals__[CONFIG]
Also note that you can use .__dict__ to enumerate elements of an object get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)
Some other interesting characteristics from format strings is the possibility of executing the functions str, repr and ascii in the indicated object by adding !s, !r, !a respectively:
Moreover, it's possible to code new formatters in classes:
More examples about format string examples can be found in https://pyformat.info/
Check also the following page for gadgets that will read sensitive information from Python internal objects:
Sensitive Information Disclosure Payloads
From format to RCE loading libraries
According to the TypeMonkey chall from this writeup it's possible to load arbitrary libraries from disk abusing the format string vulnerability in python.
As reminder, every time an action is performed in python some function is executed. For example 2*3 will execute (2).mul(3) or {'a':'b'}['a'] will be {'a':'b'}.__getitem__('a').
You have more like this in the section Python execution without calls.
A python format string vuln doesn't allow to execute function (it's doesn't allow to use parenthesis), so it's not possible to get RCE like '{0.system("/bin/sh")}'.format(os).
However, it's possible to use []. Therefore, if a common python library has a __getitem__ or __getattr__ method that executes arbitrary code, it's possible to abuse them to get RCE.
Looking for a gadget like that in python, the writeup purposes this Github search query. Where he found this one:
This gadget allows to load a library from disk. Therefore, it's needed to somehow write or upload the library to load correctly compiled to the attacked server.
The challenge actually abuses another vulnerability in the server that allows to create arbitrary files in the servers disk.
Dissecting Python Objects
In some CTFs you could be provided with the name of a custom function where the flag resides and you need to see the internals of the function to extract it.
This is the function to inspect:
dir
globals
__globals__ and func_globals(Same) Obtains the global environment. In the example you can see some imported modules, some global variables and their content declared:
See here more places to obtain globals
Accessing the function code
__code__ and func_code: You can access this attribute of the function to obtain the code object of the function.
Getting Code Information
Disassembly a function
Notice that if you cannot import dis in the python sandbox you can obtain the bytecode of the function (get_flag.func_code.co_code) and disassemble it locally. You won't see the content of the variables being loaded (LOAD_CONST) but you can guess them from (get_flag.func_code.co_consts) because LOAD_CONSTalso tells the offset of the variable being loaded.
Compiling Python
Now, let us imagine that somehow you can dump the information about a function that you cannot execute but you need to execute it.
Like in the following example, you can access the code object of that function, but just reading the disassemble you don't know how to calculate the flag (imagine a more complex calc_flag function)
Creating the code object
First of all, we need to know how to create and execute a code object so we can create one to execute our function leaked:
Recreating a leaked function
In the following example, we are going to take all the data needed to recreate the function from the function code object directly. In a real example, all the values to execute the function code_type is what you will need to leak.
Bypass Defenses
In previous examples at the beginning of this post, you can see how to execute any python code using the compile function. This is interesting because you can execute whole scripts with loops and everything in a one liner (and we could do the same using exec).
Anyway, sometimes it could be useful to create a compiled object in a local machine and execute it in the CTF machine (for example because we don't have the compiled function in the CTF).
For example, let's compile and execute manually a function that reads ./poc.py:
If you cannot access eval or exec you could create a proper function, but calling it directly is usually going to fail with: constructor not accessible in restricted mode. So you need a function not in the restricted environment to call this function.
Decompiling Compiled Python
Using tools like https://www.decompiler.com/ one can decompile given compiled python code.
Check out this tutorial:
Decompile compiled python binaries (exe, elf) - Retreive from .pycMisc Python
Assert
Python executed with optimizations with the param -O will remove asset statements and any code conditional on the value of debug.
Therefore, checks like
will be bypassed
References
Get a hacker's perspective on your web apps, network, and cloud
Find and report critical, exploitable vulnerabilities with real business impact. Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
Learn & practice AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Last updated